use of org.jikesrvm.osr.ExecutionState in project JikesRVM by JikesRVM.
the class BaselineExecutionStateExtractor method extractState.
/**
* Implements ExecutionStateExtractor.extractState.
*
* @param thread : the suspended thread, the registers and stack frames are used.
* @param osrFPoff : the osr method's stack frame offset
* @param methFPoff : the real method's stack frame offset
* @param cmid : the top application method ( system calls are unwounded ).
*
* return a ExecutionStateExtractor object.
*/
@Override
public ExecutionState extractState(RVMThread thread, Offset osrFPoff, Offset methFPoff, int cmid) {
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("BASE execStateExtractor starting ...");
}
byte[] stack = thread.getStack();
if (VM.VerifyAssertions) {
int fooCmid = Magic.getIntAtOffset(stack, methFPoff.plus(STACKFRAME_METHOD_ID_OFFSET));
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("fooCmid = " + fooCmid);
VM.sysWriteln(" cmid = " + cmid);
}
VM._assert(fooCmid == cmid);
}
ArchBaselineCompiledMethod fooCM = (ArchBaselineCompiledMethod) CompiledMethods.getCompiledMethod(cmid);
NormalMethod fooM = (NormalMethod) fooCM.getMethod();
VM.disableGC();
Address rowIP = Magic.objectAsAddress(stack).loadAddress(osrFPoff.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) {
if (bcIndex == -1) {
VM.sysWriteln("osrFPoff = ", osrFPoff);
VM.sysWriteln("instr_beg = ", Magic.objectAsAddress(fooCM.getEntryCodeArray()));
for (int i = (osrFPoff.toInt()) - 10; i < (osrFPoff.toInt()) + 10; i++) {
VM.sysWriteln(" stack[" + i + "] = " + stack[i]);
}
Offset ipIndex = ipOffset.toWord().rsha(LG_INSTRUCTION_WIDTH).toOffset();
VM.sysWriteln("ipIndex : ", ipIndex);
VM.sysWriteln("bcIndex : " + bcIndex);
}
VM._assert(bcIndex != -1);
}
// create execution state object
ExecutionState state = new ExecutionState(thread, methFPoff, cmid, bcIndex, osrFPoff);
/* 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();
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("BC Index : " + bcIndex);
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();
}
// type. We should remove non-reference type
for (int i = 0, n = localTypes.length; i < n; i++) {
// then set the localType to uninitialized, see VM spec, bytecode verifier
if (localTypes[i] == ClassTypeCode) {
if (!fooCM.referenceMaps.isLocalRefType(fooM, ipOffset.plus(1 << LG_INSTRUCTION_WIDTH), i)) {
localTypes[i] = VoidTypeCode;
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("GC maps disagrees with type matcher at " + i + "th local");
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: do not call BaselineCompilerImpl.getFirstLocalOffset(method)
Offset startLocalOffset = methFPoff.plus(BaselineCompilerImpl.locationToOffset(fooCM.getGeneralLocalLocation(0)));
Offset stackOffset = methFPoff.plus(fooCM.getEmptyStackOffset());
// for locals
getVariableValue(stack, startLocalOffset, localTypes, fooCM, LOCAL, state);
// for stacks
getVariableValue(stack, stackOffset, stackTypes, fooCM, STACK, state);
if (VM.TraceOnStackReplacement) {
state.printState();
}
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("BASE executionStateExtractor done ");
}
return state;
}
use of org.jikesrvm.osr.ExecutionState in project JikesRVM by JikesRVM.
the class OptExecutionStateExtractor method getExecStateSequence.
private ExecutionState getExecStateSequence(RVMThread thread, byte[] stack, Offset ipOffset, Offset fpOffset, int cmid, Offset tsFPOffset, TempRegisters registers, EncodedOSRMap osrmap) {
// go through the stack frame and extract values
// In the variable value list, we keep the order as follows:
// L0, L1, ..., S0, S1, ....
/* go over osr map element, build list of VariableElement.
* assuming iterator has ordered element as
* L0, L1, ..., S0, S1, ...
*
* ThreadSwitch
* threadSwitchFromOsr
* FOO <-- fpOffset
*
* Also, all registers saved by threadSwitchFromDeopt method
* is restored in "registers", address for object is converted
* back to object references.
*
* This method should be called in non-GC critical section since
* it allocates many objects.
*/
// for 64-bit type values which have two int parts.
// this holds the high part.
int lvalue_one = 0;
int lvtype_one = 0;
// now recover execution states
OSRMapIterator iterator = osrmap.getOsrMapIteratorForMCOffset(ipOffset);
if (VM.VerifyAssertions)
VM._assert(iterator != null);
ExecutionState state = new ExecutionState(thread, fpOffset, cmid, iterator.getBcIndex(), tsFPOffset);
MethodReference mref = MemberReference.getMethodRef(iterator.getMethodId());
state.setMethod((NormalMethod) mref.peekResolvedMethod());
// this is not caller, but the callee, reverse it when outside
// of this function.
state.callerState = null;
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("osr map table of " + state.meth.toString());
}
while (iterator.hasMore()) {
if (iterator.getMethodId() != state.meth.getId()) {
ExecutionState newstate = new ExecutionState(thread, fpOffset, cmid, iterator.getBcIndex(), tsFPOffset);
mref = MemberReference.getMethodRef(iterator.getMethodId());
newstate.setMethod((NormalMethod) mref.peekResolvedMethod());
// this is not caller, but the callee, reverse it when outside
// of this function.
newstate.callerState = state;
state = newstate;
if (VM.TraceOnStackReplacement) {
VM.sysWriteln("osr map table of " + state.meth.toString());
}
}
// create a VariableElement for it.
boolean kind = iterator.getKind();
char num = iterator.getNumber();
byte tcode = iterator.getTypeCode();
byte vtype = iterator.getValueType();
int value = iterator.getValue();
iterator.moveToNext();
if (VM.TraceOnStackReplacement) {
VM.sysWrite((kind == LOCAL) ? "L" : "S");
VM.sysWrite((int) num);
VM.sysWrite(" , ");
if (vtype == ICONST) {
VM.sysWrite("ICONST ");
VM.sysWrite(value);
} else if (vtype == PHYREG) {
VM.sysWrite("PHYREG ");
VM.sysWrite(GPR.lookup(value).toString());
} else if (vtype == SPILL) {
VM.sysWrite("SPILL ");
VM.sysWrite(value);
}
VM.sysWriteln();
}
switch(tcode) {
case INT:
{
int ibits = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
state.add(new VariableElement(kind, num, tcode, ibits));
break;
}
case FLOAT:
{
float fv = (float) getDoubleFrom(vtype, value, stack, fpOffset, registers);
int ibits = Magic.floatAsIntBits(fv);
state.add(new VariableElement(kind, num, tcode, ibits));
break;
}
case HIGH_64BIT:
{
lvalue_one = value;
lvtype_one = vtype;
break;
}
case LONG:
{
long lbits = getLongBitsFrom(lvtype_one, lvalue_one, vtype, value, stack, fpOffset, registers);
lvalue_one = 0;
lvtype_one = 0;
state.add(new VariableElement(kind, num, LONG, lbits));
break;
}
case DOUBLE:
{
double dv = getDoubleFrom(vtype, value, stack, fpOffset, registers);
long lbits = Magic.doubleAsLongBits(dv);
state.add(new VariableElement(kind, num, tcode, lbits));
break;
}
// To be VERIFIED.
case RET_ADDR:
{
int bcIndex = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
state.add(new VariableElement(kind, num, tcode, bcIndex));
break;
}
case WORD:
{
// KV:TODO
if (VM.BuildFor64Addr) {
if (VM.VerifyAssertions) {
VM._assert(VM.NOT_REACHED);
} else {
VM.sysFail("Case not yet implemented for 64-bit addresssing.");
}
}
int word = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
state.add(new VariableElement(kind, num, tcode, word));
break;
}
case REF:
{
Object ref = getObjectFrom(vtype, value, stack, fpOffset, registers);
state.add(new VariableElement(kind, num, tcode, ref));
break;
}
default:
if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
break;
}
// switch
}
return state;
}
use of org.jikesrvm.osr.ExecutionState 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.jikesrvm.osr.ExecutionState in project JikesRVM by JikesRVM.
the class OptExecutionStateExtractor method getExecStateSequence.
private ExecutionState getExecStateSequence(RVMThread thread, byte[] stack, Offset ipOffset, Offset fpOffset, int cmid, Offset tsFPOffset, TempRegisters registers, EncodedOSRMap osrmap) {
// go through the stack frame and extract values
// In the variable value list, we keep the order as follows:
// L0, L1, ..., S0, S1, ....
/* go over osr map element, build list of VariableElement.
* assuming iterator has ordered element as
* L0, L1, ..., S0, S1, ...
*
* RVMThread.ThreadSwitch
* OptSaveVolatile.threadSwitchFromDeopt
* FOO <-- fpOffset
*
* Also, all registers saved by threadSwitchFromDeopt method
* is restored in "registers", address for object is converted
* back to object references.
*
* This method should be called in non-GC critical section since
* it allocates many objects.
*/
// for 64-bit type values which have two int parts.
// this holds the high part.
int lpart_one = 0;
// now recover execution states
OSRMapIterator iterator = osrmap.getOsrMapIteratorForMCOffset(ipOffset);
if (VM.VerifyAssertions)
VM._assert(iterator != null);
ExecutionState state = new ExecutionState(thread, fpOffset, cmid, iterator.getBcIndex(), tsFPOffset);
MethodReference mref = MemberReference.getMethodRef(iterator.getMethodId());
state.setMethod((NormalMethod) mref.peekResolvedMethod());
state.callerState = null;
while (iterator.hasMore()) {
if (iterator.getMethodId() != state.meth.getId()) {
ExecutionState newstate = new ExecutionState(thread, fpOffset, cmid, iterator.getBcIndex(), tsFPOffset);
mref = MemberReference.getMethodRef(iterator.getMethodId());
newstate.setMethod((NormalMethod) mref.peekResolvedMethod());
// this is not caller, but the callee, reverse it when outside
// of this function.
newstate.callerState = state;
state = newstate;
}
// create a VariableElement for it.
boolean kind = iterator.getKind();
int num = iterator.getNumber();
byte tcode = iterator.getTypeCode();
byte vtype = iterator.getValueType();
int value = iterator.getValue();
iterator.moveToNext();
switch(tcode) {
case INT:
{
int ibits = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
state.add(new VariableElement(kind, num, tcode, ibits));
break;
}
case FLOAT:
{
float fv = (float) getDoubleFrom(vtype, value, stack, fpOffset, registers);
int ibits = Magic.floatAsIntBits(fv);
state.add(new VariableElement(kind, num, tcode, ibits));
break;
}
case HIGH_64BIT:
{
lpart_one = value;
break;
}
case LONG:
{
long lbits = getLongBitsFrom(vtype, lpart_one, value, stack, fpOffset, registers);
lpart_one = 0;
state.add(new // not use LONG2,
VariableElement(// not use LONG2,
kind, // not use LONG2,
num, // not use LONG2,
LONG, lbits));
break;
}
case DOUBLE:
{
double dv = getDoubleFrom(vtype, value, stack, fpOffset, registers);
long lbits = Magic.doubleAsLongBits(dv);
state.add(new VariableElement(kind, num, tcode, lbits));
break;
}
// To be VERIFIED.
case RET_ADDR:
{
int bcIndex = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
state.add(new VariableElement(kind, num, tcode, bcIndex));
break;
}
case REF:
{
Object ref = getObjectFrom(vtype, value, stack, fpOffset, registers);
state.add(new VariableElement(kind, num, tcode, ref));
break;
}
case WORD:
{
if (VM.BuildFor32Addr) {
int word = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
state.add(new VariableElement(kind, num, tcode, word));
} else {
long word = getLongBitsFrom(vtype, lpart_one, value, stack, fpOffset, registers);
lpart_one = 0;
state.add(new VariableElement(kind, num, tcode, word));
}
break;
}
default:
if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
break;
}
// switch
}
return state;
}
use of org.jikesrvm.osr.ExecutionState 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 threadSwitchFrom method 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) {
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.
*/
/* Following code is architecture dependent. In IA32, the return address
* saved in caller stack frames, so use osrFP to get the next instruction
* address of foo
*/
// get the next machine code offset of the real method
VM.disableGC();
Address osrFP = Magic.objectAsAddress(stack).plus(osrFPoff);
Address nextIP = Magic.getReturnAddressUnchecked(osrFP);
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, it becomes callee -> caller
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("OptExecState : recovered states " + thread.toString());
ExecutionState temp = state;
do {
VM.sysWriteln(temp.toString());
temp = temp.callerState;
} while (temp != null);
}
return state;
}
Aggregations