Search in sources :

Example 76 with Offset

use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.

the class BaselineExecutionStateExtractor method getVariableValue.

/* go over local/stack array, and build VariableElement. */
private static void getVariableValue(byte[] stack, Offset offset, byte[] types, ArchBaselineCompiledMethod compiledMethod, boolean kind, ExecutionState state) {
    int size = types.length;
    Offset vOffset = offset;
    for (int i = 0; i < size; i++) {
        if (VM.TraceOnStackReplacement) {
            Word content = Magic.getWordAtOffset(stack, vOffset.minus(BYTES_IN_ADDRESS));
            VM.sysWrite("0x", vOffset.minus(BYTES_IN_ADDRESS), "    0x");
            VM.sysWriteln(content);
            if ((types[i] == LongTypeCode) || (types[i] == DoubleTypeCode)) {
                content = Magic.getWordAtOffset(stack, vOffset.minus(2 * BYTES_IN_ADDRESS));
                VM.sysWrite("0x", vOffset.minus(2 * BYTES_IN_ADDRESS), "    0x");
                VM.sysWriteln(content);
            }
        }
        switch(types[i]) {
            case VoidTypeCode:
                vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                break;
            case BooleanTypeCode:
            case ByteTypeCode:
            case ShortTypeCode:
            case CharTypeCode:
            case IntTypeCode:
            case FloatTypeCode:
                {
                    int value = Magic.getIntAtOffset(stack, vOffset.minus(BYTES_IN_STACKSLOT));
                    vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                    byte tcode = (types[i] == FloatTypeCode) ? FLOAT : INT;
                    state.add(new VariableElement(kind, i, tcode, value));
                    break;
                }
            case LongTypeCode:
            case DoubleTypeCode:
                {
                    // KV: this code would be nicer if VoidTypeCode would always follow a 64-bit value. Rigth now for LOCAL it follows, for STACK it proceeds
                    Offset memoff = (kind == LOCAL) ? vOffset.minus(2 * BYTES_IN_STACKSLOT) : vOffset.minus(BYTES_IN_STACKSLOT);
                    long value = Magic.getLongAtOffset(stack, memoff);
                    byte tcode = (types[i] == LongTypeCode) ? LONG : DOUBLE;
                    state.add(new VariableElement(kind, i, tcode, value));
                    if (kind == LOCAL) {
                        // KV:VoidTypeCode is next
                        vOffset = vOffset.minus(2 * BYTES_IN_STACKSLOT);
                        i++;
                    } else {
                        // KV:VoidTypeCode was already in front
                        vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                    }
                    break;
                }
            case ReturnAddressTypeCode:
                {
                    VM.disableGC();
                    Address rowIP = Magic.objectAsAddress(stack).loadAddress(vOffset);
                    Offset ipOffset = compiledMethod.getInstructionOffset(rowIP);
                    VM.enableGC();
                    vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                    if (VM.TraceOnStackReplacement) {
                        Offset ipIndex = ipOffset.toWord().rsha(LG_INSTRUCTION_WIDTH).toOffset();
                        VM.sysWrite("baseline ret_addr ip ", ipIndex, " --> ");
                    }
                    int bcIndex = compiledMethod.findBytecodeIndexForInstruction(ipOffset.plus(INSTRUCTION_WIDTH));
                    if (VM.TraceOnStackReplacement) {
                        VM.sysWriteln(" bc " + bcIndex);
                    }
                    state.add(new VariableElement(kind, i, RET_ADDR, bcIndex));
                    break;
                }
            case ClassTypeCode:
            case ArrayTypeCode:
                {
                    VM.disableGC();
                    Object ref = Magic.getObjectAtOffset(stack, vOffset.minus(BYTES_IN_ADDRESS));
                    VM.enableGC();
                    vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                    state.add(new VariableElement(kind, i, REF, ref));
                    break;
                }
            case WordTypeCode:
                {
                    Word value = Magic.getWordAtOffset(stack, vOffset.minus(BYTES_IN_ADDRESS));
                    vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                    state.add(new VariableElement(kind, i, WORD, value));
                    break;
                }
            default:
                if (VM.VerifyAssertions)
                    VM._assert(VM.NOT_REACHED);
                break;
        }
    // switch
    }
// for loop
}
Also used : Word(org.vmmagic.unboxed.Word) Address(org.vmmagic.unboxed.Address) VariableElement(org.jikesrvm.osr.VariableElement) Offset(org.vmmagic.unboxed.Offset)

Example 77 with Offset

use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.

the class CodeInstaller method install.

public static boolean install(ExecutionState state, CompiledMethod cm) {
    RVMThread thread = state.getThread();
    byte[] stack = thread.getStack();
    Offset tsfromFPOffset = state.getTSFPOffset();
    Offset fooFPOffset = state.getFPOffset();
    int foomid = Magic.getIntAtOffset(stack, fooFPOffset.plus(STACKFRAME_METHOD_ID_OFFSET));
    CompiledMethod foo = CompiledMethods.getCompiledMethod(foomid);
    int cType = foo.getCompilerType();
    // this offset is used to adjust SP to FP right after return
    // from a call. 1 stack slot for return address and
    // 1 stack slot for saved FP of tsfrom.
    Offset sp2fpOffset = fooFPOffset.minus(tsfromFPOffset).minus(2 * BYTES_IN_STACKSLOT);
    // should given an estimated length, and print the instructions
    // for debugging
    Assembler asm = new Assembler(50, VM.TraceOnStackReplacement);
    // 1. generate bridge instructions to recover saved registers
    if (cType == CompiledMethod.BASELINE) {
        // unwind stack pointer, SP is FP now
        if (VM.BuildFor32Addr) {
            asm.emitADD_Reg_Imm(SP, sp2fpOffset.toInt());
        } else {
            asm.emitADD_Reg_Imm_Quad(SP, sp2fpOffset.toInt());
        }
        asm.generateJTOCloadWord(S0, cm.getOsrJTOCoffset());
        // restore saved EDI
        if (VM.BuildFor32Addr) {
            asm.emitMOV_Reg_RegDisp(EDI, SP, EDI_SAVE_OFFSET);
        } else {
            asm.emitMOV_Reg_RegDisp_Quad(EDI, SP, EDI_SAVE_OFFSET);
        }
        // restore saved EBX
        if (VM.BuildFor32Addr) {
            asm.emitMOV_Reg_RegDisp(EBX, SP, EBX_SAVE_OFFSET);
        } else {
            asm.emitMOV_Reg_RegDisp_Quad(EBX, SP, EBX_SAVE_OFFSET);
        }
        // restore frame pointer
        asm.emitPOP_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset());
        // do not pop return address and parameters,
        // we make a faked call to newly compiled method
        asm.emitJMP_Reg(S0);
    } else if (cType == CompiledMethod.OPT) {
        // /////////////////////////////////////////////////
        // recover saved registers from foo's stack frame
        // /////////////////////////////////////////////////
        OptCompiledMethod fooOpt = (OptCompiledMethod) foo;
        // foo definitely not save volatile
        boolean saveVolatile = fooOpt.isSaveVolatile();
        if (VM.VerifyAssertions) {
            VM._assert(!saveVolatile);
        }
        // assume SP is on foo's stack frame,
        int firstNonVolatile = fooOpt.getFirstNonVolatileGPR();
        int nonVolatiles = fooOpt.getNumberOfNonvolatileGPRs();
        int nonVolatileOffset = fooOpt.getUnsignedNonVolatileOffset();
        for (int i = firstNonVolatile; i < firstNonVolatile + nonVolatiles; i++) {
            if (VM.BuildFor32Addr) {
                asm.emitMOV_Reg_RegDisp(NONVOLATILE_GPRS[i], SP, sp2fpOffset.minus(nonVolatileOffset));
            } else {
                asm.emitMOV_Reg_RegDisp_Quad(NONVOLATILE_GPRS[i], SP, sp2fpOffset.minus(nonVolatileOffset));
            }
            nonVolatileOffset += BYTES_IN_STACKSLOT;
        }
        // adjust SP to frame pointer
        if (VM.BuildFor32Addr) {
            asm.emitADD_Reg_Imm(SP, sp2fpOffset.toInt());
        } else {
            asm.emitADD_Reg_Imm_Quad(SP, sp2fpOffset.toInt());
        }
        // restore frame pointer
        asm.emitPOP_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset());
        // branch to the newly compiled instructions
        asm.generateJTOCjmp(cm.getOsrJTOCoffset());
    }
    if (VM.TraceOnStackReplacement) {
        VM.sysWrite("new CM instr addr ");
        VM.sysWriteHex(Statics.getSlotContentsAsAddress(cm.getOsrJTOCoffset()));
        VM.sysWriteln();
        VM.sysWrite("JTOC register ");
        VM.sysWriteHex(Magic.getTocPointer());
        VM.sysWriteln();
        VM.sysWrite("Thread register ");
        VM.sysWriteHex(Magic.objectAsAddress(Magic.getThreadRegister()));
        VM.sysWriteln();
        VM.sysWriteln("tsfromFPOffset ", tsfromFPOffset);
        VM.sysWriteln("fooFPOffset ", fooFPOffset);
        VM.sysWriteln("SP + ", sp2fpOffset.plus(BYTES_IN_STACKSLOT));
    }
    // 3. set thread flags
    thread.isWaitingForOsr = true;
    thread.bridgeInstructions = asm.getMachineCodes();
    thread.fooFPOffset = fooFPOffset;
    thread.tsFPOffset = tsfromFPOffset;
    Address bridgeaddr = Magic.objectAsAddress(thread.bridgeInstructions);
    Memory.sync(bridgeaddr, thread.bridgeInstructions.length() << LG_INSTRUCTION_WIDTH);
    AOSLogging.logger.logOsrEvent("OSR code installation succeeded");
    return true;
}
Also used : OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) Address(org.vmmagic.unboxed.Address) RVMThread(org.jikesrvm.scheduler.RVMThread) Assembler(org.jikesrvm.compilers.common.assembler.ia32.Assembler) OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod) Offset(org.vmmagic.unboxed.Offset)

Example 78 with Offset

use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.

the class BaselineExecutionStateExtractor method getVariableValue.

/* go over local/stack array, and build VariableElement. */
private static void getVariableValue(byte[] stack, Offset offset, byte[] types, ArchBaselineCompiledMethod compiledMethod, boolean kind, ExecutionState state) {
    int size = types.length;
    Offset vOffset = offset;
    for (int i = 0; i < size; i++) {
        switch(types[i]) {
            case VoidTypeCode:
                vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                break;
            case BooleanTypeCode:
            case ByteTypeCode:
            case ShortTypeCode:
            case CharTypeCode:
            case IntTypeCode:
            case FloatTypeCode:
                {
                    int value = Magic.getIntAtOffset(stack, vOffset.minus(BYTES_IN_INT));
                    vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                    byte tcode = (types[i] == FloatTypeCode) ? FLOAT : INT;
                    state.add(new VariableElement(kind, i, tcode, value));
                    break;
                }
            case LongTypeCode:
            case DoubleTypeCode:
                {
                    // KV: this code would be nicer if VoidTypeCode would always follow a 64-bit value. Rigth now for LOCAL it follows, for STACK it proceeds
                    Offset memoff = (kind == LOCAL) ? vOffset.minus(BYTES_IN_DOUBLE) : VM.BuildFor64Addr ? vOffset : vOffset.minus(BYTES_IN_STACKSLOT);
                    long value = Magic.getLongAtOffset(stack, memoff);
                    byte tcode = (types[i] == LongTypeCode) ? LONG : DOUBLE;
                    state.add(new VariableElement(kind, i, tcode, value));
                    if (kind == LOCAL) {
                        // KV:VoidTypeCode is next
                        vOffset = vOffset.minus(2 * BYTES_IN_STACKSLOT);
                        // KV:skip VoidTypeCode
                        i++;
                    } else {
                        // KV:VoidTypeCode was already in front
                        vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                    }
                    break;
                }
            case ReturnAddressTypeCode:
                {
                    VM.disableGC();
                    Address rowIP = Magic.objectAsAddress(stack).loadAddress(vOffset.minus(BYTES_IN_ADDRESS));
                    Offset ipOffset = compiledMethod.getInstructionOffset(rowIP);
                    VM.enableGC();
                    vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                    if (VM.TraceOnStackReplacement) {
                        Offset ipIndex = ipOffset.toWord().rsha(LG_INSTRUCTION_WIDTH).toOffset();
                        VM.sysWrite("baseline ret_addr ip ", ipIndex, " --> ");
                    }
                    int bcIndex = compiledMethod.findBytecodeIndexForInstruction(ipOffset.plus(INSTRUCTION_WIDTH));
                    if (VM.TraceOnStackReplacement) {
                        VM.sysWriteln(" bc " + bcIndex);
                    }
                    state.add(new VariableElement(kind, i, RET_ADDR, bcIndex));
                    break;
                }
            case ClassTypeCode:
            case ArrayTypeCode:
                {
                    VM.disableGC();
                    Object ref = Magic.getObjectAtOffset(stack, vOffset.minus(BYTES_IN_ADDRESS));
                    VM.enableGC();
                    vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                    state.add(new VariableElement(kind, i, REF, ref));
                    break;
                }
            case WordTypeCode:
                {
                    Word value = Magic.getWordAtOffset(stack, vOffset.minus(BYTES_IN_ADDRESS));
                    vOffset = vOffset.minus(BYTES_IN_STACKSLOT);
                    state.add(new VariableElement(kind, i, WORD, value));
                    break;
                }
            default:
                if (VM.VerifyAssertions)
                    VM._assert(VM.NOT_REACHED);
                break;
        }
    // switch
    }
// for loop
}
Also used : Word(org.vmmagic.unboxed.Word) Address(org.vmmagic.unboxed.Address) VariableElement(org.jikesrvm.osr.VariableElement) Offset(org.vmmagic.unboxed.Offset)

Example 79 with Offset

use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.

the class OptExecutionStateExtractor method extractState.

@Override
public ExecutionState extractState(RVMThread thread, Offset osrFPoff, Offset methFPoff, int cmid) {
    /* perform machine and compiler dependent operations here
    * osrFPoff is the fp offset of
    * OptSaveVolatile.threadSwithFrom<...>
    *
    *  (stack grows downward)
    *          foo
    *     |->     <-- methFPoff
    *     |
    *     |    <tsfrom>
    *     |--     <-- osrFPoff
    *
    *
    * The <tsfrom> saves all volatiles, nonvolatiles, and scratch
    * registers. All register values for 'foo' can be obtained from
    * the register save area of '<tsfrom>' method.
    */
    byte[] stack = thread.getStack();
    // get registers for the caller ( real method )
    TempRegisters registers = new TempRegisters(thread.getContextRegisters());
    if (VM.VerifyAssertions) {
        int foocmid = Magic.getIntAtOffset(stack, methFPoff.plus(STACKFRAME_METHOD_ID_OFFSET));
        if (foocmid != cmid) {
            for (Offset o = osrFPoff; o.sGE(methFPoff.minus(2 * BYTES_IN_ADDRESS)); o = o.minus(BYTES_IN_ADDRESS)) {
                VM.sysWriteHex(Magic.objectAsAddress(stack).plus(o));
                VM.sysWrite(" : ");
                VM.sysWriteHex(Magic.getWordAtOffset(stack, o).toAddress());
                VM.sysWriteln();
            }
            CompiledMethod cm = CompiledMethods.getCompiledMethod(cmid);
            VM.sysWriteln("unmatch method, it should be " + cm.getMethod());
            CompiledMethod foo = CompiledMethods.getCompiledMethod(foocmid);
            VM.sysWriteln("but now it is " + foo.getMethod());
            walkOnStack(stack, osrFPoff);
        }
        VM._assert(foocmid == cmid);
    }
    OptCompiledMethod fooCM = (OptCompiledMethod) CompiledMethods.getCompiledMethod(cmid);
    /* Following code get the machine code offset to the
     * next instruction. All operation of the stack frame
     * are kept in GC critical section.
     * All code in the section should not cause any GC
     * activities, and avoid lazy compilation.
     */
    // get the next machine code offset of the real method
    VM.disableGC();
    Address methFP = Magic.objectAsAddress(stack).plus(methFPoff);
    Address nextIP = Magic.getNextInstructionAddress(methFP);
    Offset ipOffset = fooCM.getInstructionOffset(nextIP);
    VM.enableGC();
    EncodedOSRMap fooOSRMap = fooCM.getOSRMap();
    /* get register reference map from OSR map
     * we are using this map to convert addresses to objects,
     * thus we can operate objects out of GC section.
     */
    int regmap = fooOSRMap.getRegisterMapForMCOffset(ipOffset);
    {
        int bufCMID = Magic.getIntAtOffset(stack, osrFPoff.plus(STACKFRAME_METHOD_ID_OFFSET));
        CompiledMethod bufCM = CompiledMethods.getCompiledMethod(bufCMID);
        // SaveVolatile can only be compiled by OPT compiler
        if (VM.VerifyAssertions) {
            VM._assert(bufCM instanceof OptCompiledMethod);
        }
        restoreValuesFromOptSaveVolatile(stack, osrFPoff, registers, regmap, bufCM);
    }
    // return a list of states: from caller to callee
    // if the osr happens in an inlined method, the state is
    // a chain of recoverd methods.
    ExecutionState state = getExecStateSequence(thread, stack, ipOffset, methFPoff, cmid, osrFPoff, registers, fooOSRMap);
    // reverse callerState points
    ExecutionState prevState = null;
    ExecutionState nextState = state;
    while (nextState != null) {
        // 1. current node
        state = nextState;
        // 1. hold the next state first
        nextState = nextState.callerState;
        // 2. redirect pointer
        state.callerState = prevState;
        // 3. move prev to current
        prevState = state;
    }
    if (VM.TraceOnStackReplacement) {
        VM.sysWriteln("OptExecutionState : recovered states");
        ExecutionState temp = state;
        while (temp != null) {
            VM.sysWriteln(temp.toString());
            temp = temp.callerState;
        }
    }
    return state;
}
Also used : OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) ExecutionState(org.jikesrvm.osr.ExecutionState) Address(org.vmmagic.unboxed.Address) EncodedOSRMap(org.jikesrvm.osr.EncodedOSRMap) OptCompiledMethod(org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod) Offset(org.vmmagic.unboxed.Offset)

Example 80 with Offset

use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.

the class PostThreadSwitch method postProcess.

/* This method must be inlined to keep the correctness
   * This method is called at the end of threadSwitch, the caller
   * is threadSwitchFrom<...>
   */
@NoInline
public static void postProcess(RVMThread myThread) {
    /* We need to generate thread specific code and install new code.
    * We have to make sure that no GC happens from here and before
    * the new code get executed.
    */
    // add branch instruction from CTR.
    CodeArray bridge = myThread.bridgeInstructions;
    Address bridgeaddr = Magic.objectAsAddress(bridge);
    Offset offset = myThread.fooFPOffset.plus(STACKFRAME_RETURN_ADDRESS_OFFSET);
    Magic.objectAsAddress(myThread.getStack()).store(bridgeaddr, offset);
    myThread.fooFPOffset = Offset.zero();
    myThread.isWaitingForOsr = false;
    myThread.bridgeInstructions = null;
}
Also used : CodeArray(org.jikesrvm.compilers.common.CodeArray) Address(org.vmmagic.unboxed.Address) Offset(org.vmmagic.unboxed.Offset) NoInline(org.vmmagic.pragma.NoInline)

Aggregations

Offset (org.vmmagic.unboxed.Offset)215 Address (org.vmmagic.unboxed.Address)48 Inline (org.vmmagic.pragma.Inline)38 Entrypoint (org.vmmagic.pragma.Entrypoint)32 ObjectReference (org.vmmagic.unboxed.ObjectReference)21 CompiledMethod (org.jikesrvm.compilers.common.CompiledMethod)20 TypeReference (org.jikesrvm.classloader.TypeReference)17 RVMField (org.jikesrvm.classloader.RVMField)14 ForwardReference (org.jikesrvm.compilers.common.assembler.ForwardReference)13 OptCompiledMethod (org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod)13 NoInline (org.vmmagic.pragma.NoInline)13 RVMMethod (org.jikesrvm.classloader.RVMMethod)11 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)10 Word (org.vmmagic.unboxed.Word)10 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)9 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)9 RVMType (org.jikesrvm.classloader.RVMType)8 Register (org.jikesrvm.compilers.opt.ir.Register)8 RVMClass (org.jikesrvm.classloader.RVMClass)7 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)7