use of org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod in project JikesRVM by JikesRVM.
the class GenerationContextTest method inliningInstanceMethodWithRegisterReceiver.
@Test
public void inliningInstanceMethodWithRegisterReceiver() throws Exception {
NormalMethod nm = getNormalMethodForTest("methodForInliningTests");
CompiledMethod cm = new OptCompiledMethod(-1, nm);
OptOptions opts = new OptOptions();
InlineOracle io = new DefaultInlineOracle();
GenerationContext gc = new GenerationContext(nm, null, cm, opts, io);
Class<?>[] argumentTypes = { Object.class, double.class, int.class, long.class };
NormalMethod callee = getNormalMethodForTest("emptyInstanceMethodWithParams", argumentTypes);
MethodOperand methOp = MethodOperand.VIRTUAL(callee.getMemberRef().asMethodReference(), callee);
Instruction callInstr = Call.create(CALL, null, null, methOp, 5);
RegisterOperand receiver = createMockRegisterOperand(TypeReference.JavaLangObject);
assertFalse(receiver.isPreciseType());
assertFalse(receiver.isDeclaredType());
receiver.setPreciseType();
Call.setParam(callInstr, 0, receiver);
RegisterOperand objectParam = prepareCallWithObjectParam(callInstr);
RegisterOperand doubleParam = prepareCallWithDoubleParam(callInstr);
RegisterOperand intParam = prepareCallWithIntParam(callInstr);
RegisterOperand longParam = prepareCallWithLongParam(callInstr);
callInstr.setPosition(new InlineSequence(nm));
ExceptionHandlerBasicBlockBag ebag = getMockEbag();
int nodeNumber = 12345;
gc.getCfg().setNumberOfNodes(nodeNumber);
GenerationContext child = gc.createChildContext(ebag, callee, callInstr);
assertThatStateIsCopiedFromParentToChild(gc, callee, child, ebag);
assertThatReturnValueIsVoid(child);
RegisterOperand thisArg = child.getArguments()[0].asRegister();
assertFalse(thisArg.isPreciseType());
assertTrue(thisArg.isDeclaredType());
TypeReference calleeClass = callee.getDeclaringClass().getTypeRef();
assertSame(thisArg.getType(), calleeClass);
RegisterOperand expectedLocalForReceiverParam = child.makeLocal(0, thisArg);
assertTrue(thisArg.sameRegisterPropertiesAs(expectedLocalForReceiverParam));
RegisterOperand firstArg = child.getArguments()[1].asRegister();
RegisterOperand expectedLocalForObjectParam = child.makeLocal(1, firstArg);
assertTrue(firstArg.sameRegisterPropertiesAs(expectedLocalForObjectParam));
RegisterOperand secondArg = child.getArguments()[2].asRegister();
RegisterOperand expectedLocalForDoubleParam = child.makeLocal(2, secondArg);
assertTrue(secondArg.sameRegisterPropertiesAs(expectedLocalForDoubleParam));
RegisterOperand thirdArg = child.getArguments()[3].asRegister();
RegisterOperand expectedLocalForIntParam = child.makeLocal(4, thirdArg);
assertTrue(thirdArg.sameRegisterPropertiesAs(expectedLocalForIntParam));
RegisterOperand fourthArg = child.getArguments()[4].asRegister();
RegisterOperand expectedLocalForLongParam = child.makeLocal(5, fourthArg);
assertTrue(fourthArg.sameRegisterPropertiesAs(expectedLocalForLongParam));
InlineSequence expectedInlineSequence = new InlineSequence(callee, callInstr.position(), callInstr);
assertEquals(expectedInlineSequence, child.getInlineSequence());
assertThatPrologueAndEpilogueAreWiredCorrectlyForChildContext(ebag, nodeNumber, child);
Enumeration<Instruction> prologueRealInstr = child.getPrologue().forwardRealInstrEnumerator();
Instruction receiverMove = prologueRealInstr.nextElement();
RegisterOperand expectedReceiver = receiver.copy().asRegister();
narrowRegOpToCalleeClass(expectedReceiver, calleeClass);
assertMoveOperationIsCorrect(callInstr, REF_MOVE, expectedLocalForReceiverParam, expectedReceiver, receiverMove);
Instruction objectMove = prologueRealInstr.nextElement();
RegisterOperand objectParamCopy = objectParam.copy().asRegister();
assertMoveOperationIsCorrect(callInstr, REF_MOVE, expectedLocalForObjectParam, objectParamCopy, objectMove);
Instruction doubleMove = prologueRealInstr.nextElement();
RegisterOperand doubleParamCopy = doubleParam.copy().asRegister();
assertMoveOperationIsCorrect(callInstr, DOUBLE_MOVE, expectedLocalForDoubleParam, doubleParamCopy, doubleMove);
Instruction intMove = prologueRealInstr.nextElement();
RegisterOperand intParamCopy = intParam.copy().asRegister();
assertMoveOperationIsCorrect(callInstr, INT_MOVE, expectedLocalForIntParam, intParamCopy, intMove);
Instruction longMove = prologueRealInstr.nextElement();
RegisterOperand longParamCopy = longParam.copy().asRegister();
assertMoveOperationIsCorrect(callInstr, LONG_MOVE, expectedLocalForLongParam, longParamCopy, longMove);
assertThatNoMoreInstructionsExist(prologueRealInstr);
BasicBlock epilogue = child.getEpilogue();
assertThatEpilogueLabelIsCorrectForInlinedMethod(child, expectedInlineSequence, epilogue);
assertThatEpilogueIsEmpty(epilogue);
assertThatNoRethrowBlockExists(child);
assertThatChecksWontBeSkipped(gc);
}
use of org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod 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;
}
use of org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod in project JikesRVM by JikesRVM.
the class OptExecutionStateExtractor method dumpStackContent.
@SuppressWarnings("unused")
private static void dumpStackContent(byte[] stack, Offset fpOffset) {
int cmid = Magic.getIntAtOffset(stack, fpOffset.plus(STACKFRAME_METHOD_ID_OFFSET));
OptCompiledMethod cm = (OptCompiledMethod) CompiledMethods.getCompiledMethod(cmid);
int firstNonVolatile = cm.getFirstNonVolatileGPR();
int nonVolatiles = cm.getNumberOfNonvolatileGPRs();
int nonVolatileOffset = cm.getUnsignedNonVolatileOffset() + (nonVolatiles - 1) * BYTES_IN_STACKSLOT;
VM.sysWriteln("stack of " + cm.getMethod());
VM.sysWriteln(" fp offset ", fpOffset);
VM.sysWriteln(" NV area offset ", nonVolatileOffset);
VM.sysWriteln(" first NV GPR ", firstNonVolatile);
Address aFP = Magic.objectAsAddress(stack).plus(fpOffset);
for (Address a = aFP.plus(nonVolatileOffset); a.GE(aFP); a = a.minus(BYTES_IN_STACKSLOT)) {
Word content = a.loadWord();
VM.sysWriteHex(a);
VM.sysWrite(" ");
VM.sysWrite(content);
VM.sysWriteln();
}
}
use of org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod in project JikesRVM by JikesRVM.
the class OptExecutionStateExtractor method restoreValuesFromOptSaveVolatile.
/* OptSaveVolatile has different stack layout from DynamicBridge
* Have to separately recover them now, but there should be unified
* later on.
*
* |----------|
* | NON |
* |Volatiles |
* | | <-- volatile offset
* |Volatiles |
* | |
* |FPR states|
* |__________| ___ FP
*/
private void restoreValuesFromOptSaveVolatile(byte[] stack, Offset osrFPoff, TempRegisters registers, int regmap, CompiledMethod cm) {
OptCompiledMethod tsfromCM = (OptCompiledMethod) cm;
boolean saveVolatile = tsfromCM.isSaveVolatile();
if (VM.VerifyAssertions) {
VM._assert(saveVolatile);
}
WordArray gprs = registers.gprs;
// enter critical section
// precall methods potientially causing dynamic compilation
int firstNonVolatile = tsfromCM.getFirstNonVolatileGPR();
int nonVolatiles = tsfromCM.getNumberOfNonvolatileGPRs();
int nonVolatileOffset = tsfromCM.getUnsignedNonVolatileOffset() + (nonVolatiles - 1) * BYTES_IN_STACKSLOT;
VM.disableGC();
// recover nonvolatile GPRs
for (int i = firstNonVolatile + nonVolatiles - 1; i >= firstNonVolatile; i--) {
gprs.set(NONVOLATILE_GPRS[i].value(), Magic.objectAsAddress(stack).loadWord(osrFPoff.minus(nonVolatileOffset)));
nonVolatileOffset -= BYTES_IN_STACKSLOT;
}
// restore with VOLATILES yet
int volatileOffset = nonVolatileOffset;
for (int i = NUM_VOLATILE_GPRS - 1; i >= 0; i--) {
gprs.set(VOLATILE_GPRS[i].value(), Magic.objectAsAddress(stack).loadWord(osrFPoff.minus(volatileOffset)));
volatileOffset -= BYTES_IN_STACKSLOT;
}
// powerPC starts from register 1
for (int i = 0; i < NUM_GPRS; i++) {
if (EncodedOSRMap.registerIsSet(regmap, i)) {
registers.objs[i] = Magic.addressAsObject(registers.gprs.get(i).toAddress());
}
}
VM.enableGC();
if (VM.TraceOnStackReplacement) {
for (GPR reg : GPR.values()) {
VM.sysWrite(reg.toString());
VM.sysWrite(" = ");
VM.sysWrite(registers.gprs.get(reg.value()).toAddress());
VM.sysWriteln();
}
}
}
use of org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod 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