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
}
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;
}
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
}
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;
}
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;
}
Aggregations