Search in sources :

Example 66 with NormalMethod

use of org.jikesrvm.classloader.NormalMethod in project JikesRVM by JikesRVM.

the class StackTrace method buildStackTrace.

private Element[] buildStackTrace(int first, int last) {
    Element[] elements = new Element[countFrames(first, last)];
    if (!VM.BuildForOptCompiler) {
        int element = 0;
        for (int i = first; i <= last; i++) {
            elements[element] = createStandardStackTraceElement(getCompiledMethod(i), instructionOffsets[i]);
            element++;
        }
    } else {
        int element = 0;
        for (int i = first; i <= last; i++) {
            CompiledMethod compiledMethod = getCompiledMethod(i);
            if ((compiledMethod == null) || (compiledMethod.getCompilerType() != CompiledMethod.OPT)) {
                // Invisible or non-opt compiled method
                elements[element] = createStandardStackTraceElement(compiledMethod, instructionOffsets[i]);
                element++;
            } else {
                Offset instructionOffset = Offset.fromIntSignExtend(instructionOffsets[i]);
                OptCompiledMethod optInfo = (OptCompiledMethod) compiledMethod;
                OptMachineCodeMap map = optInfo.getMCMap();
                int iei = map.getInlineEncodingForMCOffset(instructionOffset);
                if (iei < 0) {
                    elements[element] = createStandardStackTraceElement(compiledMethod, instructionOffsets[i]);
                    element++;
                } else {
                    int[] inlineEncoding = map.inlineEncoding;
                    int bci = map.getBytecodeIndexForMCOffset(instructionOffset);
                    for (; iei >= 0; iei = OptEncodedCallSiteTree.getParent(iei, inlineEncoding)) {
                        int mid = OptEncodedCallSiteTree.getMethodID(iei, inlineEncoding);
                        RVMMethod method = MemberReference.getMethodRef(mid).getResolvedMember();
                        int lineNumber = ((NormalMethod) method).getLineNumberForBCIndex(bci);
                        elements[element] = createOptStackTraceElement(method, lineNumber, instructionOffset, bci);
                        element++;
                        if (iei > 0) {
                            bci = OptEncodedCallSiteTree.getByteCodeOffset(iei, inlineEncoding);
                        }
                    }
                }
            }
        }
    }
    return elements;
}
Also used : OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) RVMMethod(org.jikesrvm.classloader.RVMMethod) OptMachineCodeMap(org.jikesrvm.compilers.opt.runtimesupport.OptMachineCodeMap) NormalMethod(org.jikesrvm.classloader.NormalMethod) BaselineCompiledMethod(org.jikesrvm.compilers.baseline.BaselineCompiledMethod) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod) OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) Offset(org.vmmagic.unboxed.Offset)

Example 67 with NormalMethod

use of org.jikesrvm.classloader.NormalMethod in project JikesRVM by JikesRVM.

the class BaselineExecutionStateExtractor method extractState.

@Override
public ExecutionState extractState(RVMThread thread, Offset tsFromFPoff, Offset methFPoff, int cmid) {
    if (VM.TraceOnStackReplacement) {
        VM.sysWriteln("BASE execStateExtractor starting ...");
    }
    AbstractRegisters contextRegisters = thread.getContextRegisters();
    byte[] stack = thread.getStack();
    if (VM.VerifyAssertions) {
        int fooCmid = Magic.getIntAtOffset(stack, methFPoff.plus(STACKFRAME_METHOD_ID_OFFSET));
        VM._assert(fooCmid == cmid);
    }
    ArchBaselineCompiledMethod fooCM = (ArchBaselineCompiledMethod) CompiledMethods.getCompiledMethod(cmid);
    NormalMethod fooM = (NormalMethod) fooCM.getMethod();
    // get the next bc index
    VM.disableGC();
    Address rowIP = Magic.objectAsAddress(stack).loadAddress(methFPoff.plus(STACKFRAME_RETURN_ADDRESS_OFFSET));
    Offset ipOffset = fooCM.getInstructionOffset(rowIP);
    VM.enableGC();
    // CAUTION: IP Offset should point to next instruction
    int bcIndex = fooCM.findBytecodeIndexForInstruction(ipOffset.plus(INSTRUCTION_WIDTH));
    // assertions
    if (VM.VerifyAssertions)
        VM._assert(bcIndex != -1);
    // create execution state object
    ExecutionState state = new ExecutionState(thread, methFPoff, cmid, bcIndex, tsFromFPoff);
    /* extract values for local and stack, but first of all
     * we need to get type information for current PC.
     */
    BytecodeTraverser typer = new BytecodeTraverser();
    typer.computeLocalStackTypes(fooM, bcIndex);
    byte[] localTypes = typer.getLocalTypes();
    byte[] stackTypes = typer.getStackTypes();
    // type. We should remove non-reference type
    for (int i = 0, n = localTypes.length; i < n; i++) {
        // if typer reports a local is reference type, but the GC map says no
        // then set the localType to uninitialized, see VM spec, bytecode verifier
        // CAUTION: gc map uses mc offset in bytes!!!
        boolean gcref = fooCM.referenceMaps.isLocalRefType(fooM, ipOffset.plus(INSTRUCTION_WIDTH), i);
        if (!gcref && (localTypes[i] == ClassTypeCode)) {
            // use gc map as reference
            localTypes[i] = VoidTypeCode;
            if (VM.TraceOnStackReplacement) {
                VM.sysWriteln("GC maps disgrees with type matcher at " + i + "th local");
                VM.sysWriteln();
            }
        }
    }
    if (VM.TraceOnStackReplacement) {
        Offset ipIndex = ipOffset.toWord().rsha(LG_INSTRUCTION_WIDTH).toOffset();
        VM.sysWriteln("BC Index : " + bcIndex);
        VM.sysWriteln("IP Index : ", ipIndex.plus(1));
        VM.sysWriteln("MC Offset : ", ipOffset.plus(INSTRUCTION_WIDTH));
        VM.sysWrite("Local Types :");
        for (byte localType : localTypes) {
            VM.sysWrite(" " + (char) localType);
        }
        VM.sysWriteln();
        VM.sysWrite("Stack Types :");
        for (byte stackType : stackTypes) {
            VM.sysWrite(" " + (char) stackType);
        }
        VM.sysWriteln();
    }
    // go through the stack frame and extract values
    // In the variable value list, we keep the order as follows:
    // L0, L1, ..., S0, S1, ....
    // adjust local offset and stack offset
    // NOTE: donot call BaselineCompilerImpl.getFirstLocalOffset(method)
    int bufCMID = Magic.getIntAtOffset(stack, tsFromFPoff.plus(STACKFRAME_METHOD_ID_OFFSET));
    CompiledMethod bufCM = CompiledMethods.getCompiledMethod(bufCMID);
    int cType = bufCM.getCompilerType();
    // restore non-volatile registers that could contain locals; saved by yieldpointfrom methods
    // for the moment disabled OPT compilation of yieldpointfrom, because here we assume baselinecompilation !! TODO
    TempRegisters registers = new TempRegisters(contextRegisters);
    WordArray gprs = registers.gprs;
    double[] fprs = registers.fprs;
    Object[] objs = registers.objs;
    VM.disableGC();
    // the threadswitchfrom... method on the other hand can be baseline or opt!
    if (cType == CompiledMethod.BASELINE) {
        if (VM.VerifyAssertions) {
            VM._assert(bufCM.getMethod().hasBaselineSaveLSRegistersAnnotation());
            VM._assert(methFPoff.EQ(tsFromFPoff.plus(((ArchBaselineCompiledMethod) bufCM).getFrameSize())));
        }
        Offset currentRegisterLocation = tsFromFPoff.plus(((ArchBaselineCompiledMethod) bufCM).getFrameSize());
        for (int i = LAST_FLOAT_STACK_REGISTER.value(); i >= FIRST_FLOAT_LOCAL_REGISTER.value(); --i) {
            currentRegisterLocation = currentRegisterLocation.minus(BYTES_IN_DOUBLE);
            long lbits = Magic.getLongAtOffset(stack, currentRegisterLocation);
            fprs[i] = Magic.longBitsAsDouble(lbits);
        }
        for (int i = LAST_FIXED_STACK_REGISTER.value(); i >= FIRST_FIXED_LOCAL_REGISTER.value(); --i) {
            currentRegisterLocation = currentRegisterLocation.minus(BYTES_IN_ADDRESS);
            Word w = Magic.objectAsAddress(stack).loadWord(currentRegisterLocation);
            gprs.set(i, w);
        }
    } else {
        // (cType == CompiledMethod.OPT)
        // KV: this code needs to be modified. We need the tsFrom methods to save all NON-VOLATILES in their prolog (as is the case for baseline)
        // This is because we don't know at compile time which registers might be in use and wich not by the caller method at runtime!!
        // For now we disallow tsFrom methods to be opt compiled when the caller is baseline compiled
        // todo: fix this together with the SaveVolatile rewrite
        OptCompiledMethod fooOpt = (OptCompiledMethod) bufCM;
        // foo definitely not save volatile.
        if (VM.VerifyAssertions) {
            boolean saveVolatile = fooOpt.isSaveVolatile();
            VM._assert(!saveVolatile);
        }
        Offset offset = tsFromFPoff.plus(fooOpt.getUnsignedNonVolatileOffset());
        // recover nonvolatile GPRs
        int firstGPR = fooOpt.getFirstNonVolatileGPR();
        if (firstGPR != -1) {
            for (int i = firstGPR; i <= LAST_NONVOLATILE_GPR.value(); i++) {
                Word w = Magic.objectAsAddress(stack).loadWord(offset);
                gprs.set(i, w);
                offset = offset.plus(BYTES_IN_ADDRESS);
            }
        }
        // recover nonvolatile FPRs
        int firstFPR = fooOpt.getFirstNonVolatileFPR();
        if (firstFPR != -1) {
            for (int i = firstFPR; i <= LAST_NONVOLATILE_FPR.value(); i++) {
                long lbits = Magic.getLongAtOffset(stack, offset);
                fprs[i] = Magic.longBitsAsDouble(lbits);
                offset = offset.plus(BYTES_IN_DOUBLE);
            }
        }
    }
    // save objects in registers in register object array
    int size = localTypes.length;
    for (int i = 0; i < size; i++) {
        if ((localTypes[i] == ClassTypeCode) || (localTypes[i] == ArrayTypeCode)) {
            short loc = fooCM.getGeneralLocalLocation(i);
            if (BaselineCompilerImpl.isRegister(loc)) {
                objs[loc] = Magic.addressAsObject(gprs.get(loc).toAddress());
            }
        }
    }
    VM.enableGC();
    // for locals
    getVariableValueFromLocations(stack, methFPoff, localTypes, fooCM, LOCAL, registers, state);
    // for stacks
    Offset stackOffset = methFPoff.plus(fooCM.getEmptyStackOffset());
    getVariableValue(stack, stackOffset, stackTypes, fooCM, STACK, state);
    if (VM.TraceOnStackReplacement) {
        state.printState();
    }
    if (VM.TraceOnStackReplacement) {
        VM.sysWriteln("BASE executionStateExtractor done ");
    }
    return state;
}
Also used : ExecutionState(org.jikesrvm.osr.ExecutionState) OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) Word(org.vmmagic.unboxed.Word) Address(org.vmmagic.unboxed.Address) BytecodeTraverser(org.jikesrvm.osr.BytecodeTraverser) AbstractRegisters(org.jikesrvm.architecture.AbstractRegisters) ArchBaselineCompiledMethod(org.jikesrvm.compilers.baseline.ppc.ArchBaselineCompiledMethod) OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod) Offset(org.vmmagic.unboxed.Offset) ArchBaselineCompiledMethod(org.jikesrvm.compilers.baseline.ppc.ArchBaselineCompiledMethod) NormalMethod(org.jikesrvm.classloader.NormalMethod) WordArray(org.vmmagic.unboxed.WordArray)

Example 68 with NormalMethod

use of org.jikesrvm.classloader.NormalMethod in project JikesRVM by JikesRVM.

the class SpecialCompiler method optCompile.

/**
 * <ol>
 *   <li>generate prologue PSEUDO_bytecode from the state.
 *   <li>make new bytecodes with prologue.
 *   <li>set method's bytecode to specialized one.
 *   <li>adjust exception map, line number map.
 *   <li>compile the method.
 *   <li>restore bytecode, exception, linenumber map to the original one.
 * </ol>
 *
 * @param state the execution state for the compilation
 * @return the compiled method produced by the optimizing compiler
 */
public static CompiledMethod optCompile(ExecutionState state) {
    NormalMethod method = state.getMethod();
    if (VM.TraceOnStackReplacement) {
        VM.sysWriteln("OPT : starts compiling " + method);
    }
    ControllerPlan latestPlan = ControllerMemory.findLatestPlan(method);
    OptOptions _options = null;
    if (latestPlan != null) {
        _options = latestPlan.getCompPlan().options.dup();
    } else {
        // no previous compilation plan, a long run loop promoted from baseline.
        // this only happens when testing, not in real code
        _options = new OptOptions();
        _options.setOptLevel(0);
    }
    // disable OSR points in specialized method
    _options.OSR_GUARDED_INLINING = false;
    CompilationPlan compPlan = new CompilationPlan(method, (OptimizationPlanElement[]) RuntimeCompiler.optimizationPlan, null, _options);
    // it is also necessary to recompile the current method
    // without OSR.
    /* generate prologue bytes */
    byte[] prologue = state.generatePrologue();
    int prosize = prologue.length;
    method.setForOsrSpecialization(prologue, state.getMaxStackHeight());
    int[] oldStartPCs = null;
    int[] oldEndPCs = null;
    int[] oldHandlerPCs = null;
    /* adjust exception table. */
    {
        // if (VM.TraceOnStackReplacement) {
        // VM.sysWriteln("OPT adjust exception table.");
        // }
        ExceptionHandlerMap exceptionHandlerMap = method.getExceptionHandlerMap();
        if (exceptionHandlerMap != null) {
            oldStartPCs = exceptionHandlerMap.getStartPC();
            oldEndPCs = exceptionHandlerMap.getEndPC();
            oldHandlerPCs = exceptionHandlerMap.getHandlerPC();
            int n = oldStartPCs.length;
            int[] newStartPCs = new int[n];
            System.arraycopy(oldStartPCs, 0, newStartPCs, 0, n);
            exceptionHandlerMap.setStartPC(newStartPCs);
            int[] newEndPCs = new int[n];
            System.arraycopy(oldEndPCs, 0, newEndPCs, 0, n);
            exceptionHandlerMap.setEndPC(newEndPCs);
            int[] newHandlerPCs = new int[n];
            System.arraycopy(oldHandlerPCs, 0, newHandlerPCs, 0, n);
            exceptionHandlerMap.setHandlerPC(newHandlerPCs);
            for (int i = 0; i < n; i++) {
                newStartPCs[i] += prosize;
                newEndPCs[i] += prosize;
                newHandlerPCs[i] += prosize;
            }
        }
    }
    CompiledMethod newCompiledMethod = RuntimeCompiler.recompileWithOptOnStackSpecialization(compPlan);
    // restore original bytecode, exception table, and line number table
    method.finalizeOsrSpecialization();
    {
        ExceptionHandlerMap exceptionHandlerMap = method.getExceptionHandlerMap();
        if (exceptionHandlerMap != null) {
            exceptionHandlerMap.setStartPC(oldStartPCs);
            exceptionHandlerMap.setEndPC(oldEndPCs);
            exceptionHandlerMap.setHandlerPC(oldHandlerPCs);
        }
    }
    // reverse back to the baseline
    if (newCompiledMethod == null) {
        if (VM.TraceOnStackReplacement) {
            VM.sysWriteln("OPT : fialed, because compilation in progress, " + "fall back to baseline");
        }
        return baselineCompile(state);
    }
    // mark the method is a specialized one
    newCompiledMethod.setSpecialForOSR();
    if (VM.TraceOnStackReplacement) {
        VM.sysWriteln("OPT : done");
        VM.sysWriteln();
    }
    return newCompiledMethod;
}
Also used : NormalMethod(org.jikesrvm.classloader.NormalMethod) OptimizationPlanElement(org.jikesrvm.compilers.opt.driver.OptimizationPlanElement) CompilationPlan(org.jikesrvm.compilers.opt.driver.CompilationPlan) ExceptionHandlerMap(org.jikesrvm.classloader.ExceptionHandlerMap) OptOptions(org.jikesrvm.compilers.opt.OptOptions) ControllerPlan(org.jikesrvm.adaptive.controller.ControllerPlan) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod)

Example 69 with NormalMethod

use of org.jikesrvm.classloader.NormalMethod in project JikesRVM by JikesRVM.

the class SpecialCompiler method baselineCompile.

/**
 * Compiles the method with the baseline compiler.
 * <ol>
 *   <li>generate  prologue (PSEUDO_bytecode) from the state.
 *   <li>make up new byte code with prologue.
 *   <li>set method's bytecode to the specilizaed byte code.
 *   <li>call BaselineCompilerImpl.compile,
 *    the 'compile' method is customized to process pseudo instructions,
 *    and it will reset the byte code to the original one, and adjust
 *    the map from bytecode to the generated machine code. then the
 *    reference map can be generated corrected relying on the original
 *    bytecode.
 * </ol>
 * <p>
 * NOTE: this is different from optCompile which resets the
 *    bytecode after compilation. I believe this minimizes the
 *    work to change both compilers.
 * @param state the execution state for the compilation
 * @return the compiled method produced by the baseline compiler
 */
public static CompiledMethod baselineCompile(ExecutionState state) {
    NormalMethod method = state.getMethod();
    if (VM.TraceOnStackReplacement) {
        VM.sysWriteln("BASE : starts compiling " + method);
    }
    /* generate prologue bytes */
    byte[] prologue = state.generatePrologue();
    if (VM.TraceOnStackReplacement) {
        VM.sysWriteln("prologue length " + prologue.length);
    }
    // the compiler will call setForOsrSpecialization after generating the reference map
    /* set a flag for specialization, compiler will see it, and
     * know how to do it properly.
     */
    method.setForOsrSpecialization(prologue, state.getMaxStackHeight());
    /* for baseline compilation, we do not adjust the exception table and line table
    * because the compiler will generate maps after compilation.
    * Any necessary adjustment should be made during the compilation
    */
    CompiledMethod newCompiledMethod;
    if (VM.BuildForIA32) {
        newCompiledMethod = org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl.compile(method);
    } else {
        if (VM.VerifyAssertions)
            VM._assert(VM.BuildForPowerPC);
        newCompiledMethod = org.jikesrvm.compilers.baseline.ppc.BaselineCompilerImpl.compile(method);
    }
    // compiled method was already set by BaselineCompilerImpl.compile
    // the call here does nothing
    // method.finalizeOsrSpecialization();
    // mark the method is a specialized one
    newCompiledMethod.setSpecialForOSR();
    if (VM.TraceOnStackReplacement) {
        // ((BaselineCompiledMethod)newCompiledMethod).printCodeMapEntries();
        VM.sysWriteln("BASE : done, CMID 0x" + Integer.toHexString(newCompiledMethod.getId()) + "(" + newCompiledMethod.getId() + ") JTOC offset " + Services.addressAsHexString(newCompiledMethod.getOsrJTOCoffset().toWord().toAddress()));
    }
    return newCompiledMethod;
}
Also used : NormalMethod(org.jikesrvm.classloader.NormalMethod) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod)

Example 70 with NormalMethod

use of org.jikesrvm.classloader.NormalMethod in project JikesRVM by JikesRVM.

the class BaselineCompiledMethod method encodeMappingInfo.

/**
 * Encode/compress the bytecode map, reference (GC) map and exception table
 *
 * @param referenceMaps to encode
 * @param bcMap unencoded bytecode to code array offset map
 */
public void encodeMappingInfo(ReferenceMaps referenceMaps, int[] bcMap) {
    int count = 0;
    int lastBC = 0, lastIns = 0;
    for (int i = 0; i < bcMap.length; i++) {
        if (bcMap[i] != 0) {
            int deltaBC = i - lastBC;
            int deltaIns = bcMap[i] - lastIns;
            if (VM.VerifyAssertions) {
                VM._assert(deltaBC >= 0 && deltaIns >= 0);
            }
            if (deltaBC <= 6 && deltaIns <= 31) {
                count++;
            } else {
                if (deltaBC > 65535 || deltaIns > 65535) {
                    VM.sysFail("BaselineCompiledMethod: a fancier encoding is needed");
                }
                count += 5;
            }
            lastBC = i;
            lastIns = bcMap[i];
        }
    }
    bytecodeMap = new byte[count];
    count = lastBC = lastIns = 0;
    for (int i = 0; i < bcMap.length; i++) {
        if (bcMap[i] != 0) {
            int deltaBC = i - lastBC;
            int deltaIns = bcMap[i] - lastIns;
            if (VM.VerifyAssertions) {
                VM._assert(deltaBC >= 0 && deltaIns >= 0);
            }
            if (deltaBC <= 6 && deltaIns <= 31) {
                bytecodeMap[count++] = (byte) ((deltaBC << 5) | deltaIns);
            } else {
                // From before, we know that deltaBC <= 65535 and deltaIns <= 65535
                bytecodeMap[count++] = (byte) 255;
                bytecodeMap[count++] = (byte) (deltaBC >> 8);
                bytecodeMap[count++] = (byte) (deltaBC & 255);
                bytecodeMap[count++] = (byte) (deltaIns >> 8);
                bytecodeMap[count++] = (byte) (deltaIns & 255);
            }
            lastBC = i;
            lastIns = bcMap[i];
        }
    }
    // TODO: it's likely for short methods we can share the bytecodeMap
    referenceMaps.translateByte2Machine(bcMap);
    this.referenceMaps = referenceMaps;
    ExceptionHandlerMap emap = ((NormalMethod) method).getExceptionHandlerMap();
    if (emap != null) {
        eTable = BaselineExceptionTable.encode(emap, bcMap);
    }
}
Also used : NormalMethod(org.jikesrvm.classloader.NormalMethod) ExceptionHandlerMap(org.jikesrvm.classloader.ExceptionHandlerMap)

Aggregations

NormalMethod (org.jikesrvm.classloader.NormalMethod)95 Test (org.junit.Test)66 OptOptions (org.jikesrvm.compilers.opt.OptOptions)45 CompiledMethod (org.jikesrvm.compilers.common.CompiledMethod)41 OptCompiledMethod (org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod)31 DefaultInlineOracle (org.jikesrvm.compilers.opt.inlining.DefaultInlineOracle)28 InlineOracle (org.jikesrvm.compilers.opt.inlining.InlineOracle)28 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)28 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)21 InlineSequence (org.jikesrvm.compilers.opt.inlining.InlineSequence)17 TypeReference (org.jikesrvm.classloader.TypeReference)15 ExceptionHandlerBasicBlockBag (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlockBag)15 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)15 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)13 ExceptionHandlerBasicBlock (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)13 Register (org.jikesrvm.compilers.opt.ir.Register)13 RVMMethod (org.jikesrvm.classloader.RVMMethod)8 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)8 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)8 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)8