use of org.jikesrvm.compilers.common.CompiledMethod in project JikesRVM by JikesRVM.
the class StackTrace method countFramesUninterruptible.
/**
* Walk the stack counting the number of stack frames encountered.
* The stack being walked is our stack, so code is Uninterruptible to stop the
* stack moving.
*
* @param stackTraceThread the thread whose stack is walked
* @return number of stack frames encountered
*/
@Uninterruptible
@NoInline
private int countFramesUninterruptible(RVMThread stackTraceThread) {
int stackFrameCount = 0;
Address fp;
/* Stack trace for the thread */
if (stackTraceThread == RVMThread.getCurrentThread()) {
fp = Magic.getFramePointer();
} else {
AbstractRegisters contextRegisters = stackTraceThread.getContextRegisters();
fp = contextRegisters.getInnermostFramePointer();
}
fp = Magic.getCallerFramePointer(fp);
while (Magic.getCallerFramePointer(fp).NE(StackFrameLayout.getStackFrameSentinelFP())) {
int compiledMethodId = Magic.getCompiledMethodID(fp);
if (compiledMethodId != StackFrameLayout.getInvisibleMethodID()) {
CompiledMethod compiledMethod = CompiledMethods.getCompiledMethod(compiledMethodId);
if ((compiledMethod.getCompilerType() != CompiledMethod.TRAP) && compiledMethod.hasBridgeFromNativeAnnotation()) {
// skip native frames, stopping at last native frame preceeding the
// Java To C transition frame
fp = RuntimeEntrypoints.unwindNativeStackFrame(fp);
}
}
stackFrameCount++;
fp = Magic.getCallerFramePointer(fp);
}
// VM.sysWriteln("stack frame count = ",stackFrameCount);
return stackFrameCount;
}
use of org.jikesrvm.compilers.common.CompiledMethod in project JikesRVM by JikesRVM.
the class StackTrace method countFrames.
/**
* Count number of stack frames including those inlined by the opt compiler
* @param first the first compiled method to look from
* @param last the last compiled method to look to
* @return the number of stack frames
*/
private int countFrames(int first, int last) {
int numElements = 0;
if (!VM.BuildForOptCompiler) {
numElements = last - first + 1;
} else {
for (int i = first; i <= last; i++) {
CompiledMethod compiledMethod = getCompiledMethod(i);
if ((compiledMethod == null) || (compiledMethod.getCompilerType() != CompiledMethod.OPT)) {
// Invisible or non-opt compiled method
numElements++;
} else {
Offset instructionOffset = Offset.fromIntSignExtend(instructionOffsets[i]);
OptCompiledMethod optInfo = (OptCompiledMethod) compiledMethod;
OptMachineCodeMap map = optInfo.getMCMap();
int iei = map.getInlineEncodingForMCOffset(instructionOffset);
if (iei < 0) {
numElements++;
} else {
int[] inlineEncoding = map.inlineEncoding;
for (; iei >= 0; iei = OptEncodedCallSiteTree.getParent(iei, inlineEncoding)) {
numElements++;
}
}
}
}
}
return numElements;
}
use of org.jikesrvm.compilers.common.CompiledMethod in project JikesRVM by JikesRVM.
the class StackTrace method lastRealMethod.
/**
* Find the first non-VM method at the end of the stack trace
* @param first the first real method of the stack trace
* @return compiledMethods.length-1 if no non-VM methods found else the index of
* the method
*/
private int lastRealMethod(int first) {
/* We expect an exception on the main thread to look like:
* at <invisible method>(Unknown Source:0)
* at org.jikesrvm.runtime.Reflection.invoke(Reflection.java:132)
* at org.jikesrvm.scheduler.MainThread.run(MainThread.java:195)
* at org.jikesrvm.scheduler.RVMThread.run(RVMThread.java:534)
* at org.jikesrvm.scheduler.RVMThread.startoff(RVMThread.java:1113
*
* and on another thread to look like:
* at org.jikesrvm.scheduler.RVMThread.run(RVMThread.java:534)
* at org.jikesrvm.scheduler.RVMThread.startoff(RVMThread.java:1113)
*/
int max = compiledMethods.length - 1;
if (Options.stackTraceFull) {
return max;
} else {
// Start at end of array and elide a frame unless we find a place to stop
for (int i = max; i >= first; i--) {
if (compiledMethods[i] == StackFrameLayout.getInvisibleMethodID()) {
// we found an invisible method, assume next method if this is sane
if (i - 1 >= 0) {
return i - 1;
} else {
// not sane => return max
return max;
}
}
CompiledMethod compiledMethod = getCompiledMethod(i);
if (compiledMethod.getCompilerType() == CompiledMethod.TRAP) {
// looks like we've gone too low
return max;
}
Class<?> frameClass = compiledMethod.getMethod().getDeclaringClass().getClassForType();
if ((frameClass != org.jikesrvm.scheduler.MainThread.class) && (frameClass != org.jikesrvm.scheduler.RVMThread.class) && (frameClass != org.jikesrvm.runtime.Reflection.class)) {
// Found a non-VM method
return i;
}
}
// No frame found
return max;
}
}
use of org.jikesrvm.compilers.common.CompiledMethod 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.jikesrvm.compilers.common.CompiledMethod 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;
}
Aggregations