use of org.jikesrvm.compilers.opt.ir.operand.TypeOperand in project JikesRVM by JikesRVM.
the class Inliner method execute.
/**
* Return a generation context that represents the
* execution of inlDec in the context <code><parent,ebag></code> for
* the call instruction callSite.
* <p> PRECONDITION: inlDec.isYes()
* <p> POSTCONDITIONS:
* Let gc be the returned generation context.
* <ul>
* <li> gc.cfg.firstInCodeOrder is the entry to the inlined context
* <li>gc.cfg.lastInCodeOrder is the exit from the inlined context
* <li> GenerationContext.transferState(parent, child) has been called.
* </ul>
*
* @param inlDec the inlining decision to execute
* @param parent the caller generation context
* @param ebag exception handler scope for the caller
* @param callSite the callsite to execute
* @return a generation context that represents the execution of the
* inline decision in the given context
*/
public static GenerationContext execute(InlineDecision inlDec, GenerationContext parent, ExceptionHandlerBasicBlockBag ebag, Instruction callSite) {
if (inlDec.needsGuard()) {
// Step 1: create the synthetic generation context we'll
// return to our caller.
GenerationContext container = GenerationContext.createSynthetic(parent, ebag);
container.getCfg().breakCodeOrder(container.getPrologue(), container.getEpilogue());
// Step 2: (a) Print a message (optional)
// (b) Generate the child GC for each target
RVMMethod[] targets = inlDec.getTargets();
byte[] guards = inlDec.getGuards();
GenerationContext[] children = new GenerationContext[targets.length];
for (int i = 0; i < targets.length; i++) {
NormalMethod callee = (NormalMethod) targets[i];
// (a)
if (parent.getOptions().PRINT_INLINE_REPORT) {
String guard = guards[i] == OptOptions.INLINE_GUARD_CLASS_TEST ? " (class test) " : " (method test) ";
VM.sysWriteln("\tGuarded inline" + guard + " " + callee + " into " + callSite.position().getMethod() + " at bytecode " + callSite.getBytecodeIndex());
}
// (b)
children[i] = parent.createChildContext(ebag, callee, callSite);
BC2IR.generateHIR(children[i]);
children[i].transferStateToParent();
}
// special purpose coding wrapping the calls to Operand.meet.
if (Call.hasResult(callSite)) {
Register reg = Call.getResult(callSite).getRegister();
container.setResult(children[0].getResult());
for (int i = 1; i < targets.length; i++) {
if (children[i].getResult() != null) {
container.setResult((container.getResult() == null) ? children[i].getResult() : Operand.meet(container.getResult(), children[i].getResult(), reg));
}
}
if (!inlDec.OSRTestFailed()) {
// Account for the non-predicted case as well...
RegisterOperand failureCaseResult = Call.getResult(callSite).copyRO();
container.setResult((container.getResult() == null) ? failureCaseResult : Operand.meet(container.getResult(), failureCaseResult, reg));
}
}
// Step 4: Create a block to contain a copy of the original call or an OSR_Yieldpoint
// to cover the case that all predictions fail.
BasicBlock testFailed = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
testFailed.setExceptionHandlers(ebag);
if (COUNT_FAILED_GUARDS && Controller.options.INSERT_DEBUGGING_COUNTERS) {
// Get a dynamic count of how many times guards fail at runtime.
// Need a name for the event to count. In this example, a
// separate counter for each method by using the method name
// as the event name. You could also have used just the string
// "Guarded inline failed" to keep only one counter.
String eventName = "Guarded inline failed: " + callSite.position().getMethod().toString();
// Create instruction that will increment the counter
// corresponding to the named event.
Instruction counterInst = AOSDatabase.debuggingCounterData.getCounterInstructionForEvent(eventName);
testFailed.appendInstruction(counterInst);
}
if (inlDec.OSRTestFailed()) {
// note where we're storing the osr barrier instruction
Instruction lastOsrBarrier = parent.getOSRBarrierFromInst(callSite);
Instruction s = BC2IR._osrHelper(lastOsrBarrier, parent);
s.copyPosition(callSite);
testFailed.appendInstruction(s);
testFailed.insertOut(parent.getExit());
} else {
Instruction call = callSite.copyWithoutLinks();
Call.getMethod(call).setIsGuardedInlineOffBranch(true);
call.copyPosition(callSite);
testFailed.appendInstruction(call);
testFailed.insertOut(container.getEpilogue());
// BC2IR.maybeInlineMethod).
if (ebag != null) {
for (Enumeration<BasicBlock> e = ebag.enumerator(); e.hasMoreElements(); ) {
BasicBlock handler = e.nextElement();
testFailed.insertOut(handler);
}
}
testFailed.setCanThrowExceptions();
testFailed.setMayThrowUncaughtException();
}
container.getCfg().linkInCodeOrder(testFailed, container.getEpilogue());
testFailed.setInfrequent();
// Step 5: Patch together all the callees by generating guard blocks
BasicBlock firstIfBlock = testFailed;
// Note: We know that receiver must be a register
// operand (and not a string constant) because we are doing a
// guarded inlining....if it was a string constant we'd have
// been able to inline without a guard.
Operand receiver = Call.getParam(callSite, 0);
MethodOperand mo = Call.getMethod(callSite);
boolean isInterface = mo.isInterface();
if (isInterface) {
if (VM.BuildForIMTInterfaceInvocation) {
RVMType interfaceType = mo.getTarget().getDeclaringClass();
TypeReference recTypeRef = receiver.getType();
RVMClass recType = (RVMClass) recTypeRef.peekType();
// Attempt to avoid inserting the check by seeing if the
// known static type of the receiver implements the interface.
boolean requiresImplementsTest = true;
if (recType != null && recType.isResolved() && !recType.isInterface()) {
byte doesImplement = ClassLoaderProxy.includesType(interfaceType.getTypeRef(), recTypeRef);
requiresImplementsTest = doesImplement != YES;
}
if (requiresImplementsTest) {
RegisterOperand checkedReceiver = parent.getTemps().makeTemp(receiver);
Instruction dtc = TypeCheck.create(MUST_IMPLEMENT_INTERFACE, checkedReceiver, receiver.copy(), new TypeOperand(interfaceType), Call.getGuard(callSite).copy());
dtc.copyPosition(callSite);
checkedReceiver.refine(interfaceType.getTypeRef());
Call.setParam(callSite, 0, checkedReceiver.copyRO());
testFailed.prependInstruction(dtc);
}
}
}
// "logical" test and to share test insertion for interfaces/virtuals.
for (int i = children.length - 1; i >= 0; i--, testFailed = firstIfBlock) {
firstIfBlock = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
firstIfBlock.setExceptionHandlers(ebag);
BasicBlock lastIfBlock = firstIfBlock;
RVMMethod target = children[i].getMethod();
Instruction tmp;
if (isInterface) {
RVMClass callDeclClass = mo.getTarget().getDeclaringClass();
if (!callDeclClass.isInterface()) {
// the entire compilation.
throw new OptimizingCompilerException("Attempted guarded inline of invoke interface when decl class of target method may not be an interface");
}
// We potentially have to generate IR to perform two tests here:
// (1) Does the receiver object implement callDeclClass?
// (2) Given that it does, is target the method that would
// be invoked for this receiver?
// It is quite common to be able to answer (1) "YES" at compile
// time, in which case we only have to generate IR to establish
// (2) at runtime.
byte doesImplement = ClassLoaderProxy.includesType(callDeclClass.getTypeRef(), target.getDeclaringClass().getTypeRef());
if (doesImplement != YES) {
// implements the interface).
if (parent.getOptions().PRINT_INLINE_REPORT) {
VM.sysWriteln("\t\tRequired additional instanceof " + callDeclClass + " test");
}
firstIfBlock = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
firstIfBlock.setExceptionHandlers(ebag);
RegisterOperand instanceOfResult = parent.getTemps().makeTempInt();
tmp = InstanceOf.create(INSTANCEOF_NOTNULL, instanceOfResult, new TypeOperand(callDeclClass), receiver.copy(), Call.getGuard(callSite));
tmp.copyPosition(callSite);
firstIfBlock.appendInstruction(tmp);
tmp = IfCmp.create(INT_IFCMP, parent.getTemps().makeTempValidation(), instanceOfResult.copyD2U(), new IntConstantOperand(0), ConditionOperand.EQUAL(), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
tmp.copyPosition(callSite);
firstIfBlock.appendInstruction(tmp);
firstIfBlock.insertOut(testFailed);
firstIfBlock.insertOut(lastIfBlock);
container.getCfg().linkInCodeOrder(firstIfBlock, lastIfBlock);
}
}
if (guards[i] == OptOptions.INLINE_GUARD_CLASS_TEST) {
tmp = InlineGuard.create(IG_CLASS_TEST, receiver.copy(), Call.getGuard(callSite).copy(), new TypeOperand(target.getDeclaringClass()), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
} else if (guards[i] == OptOptions.INLINE_GUARD_METHOD_TEST) {
// declaring class.
if (isInterface) {
RegisterOperand t = parent.getTemps().makeTempInt();
Instruction test = InstanceOf.create(INSTANCEOF_NOTNULL, t, new TypeOperand(target.getDeclaringClass().getTypeRef()), receiver.copy());
test.copyPosition(callSite);
lastIfBlock.appendInstruction(test);
Instruction cmp = IfCmp.create(INT_IFCMP, parent.getTemps().makeTempValidation(), t.copyD2U(), new IntConstantOperand(0), ConditionOperand.EQUAL(), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
cmp.copyPosition(callSite);
lastIfBlock.appendInstruction(cmp);
BasicBlock subclassTest = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
lastIfBlock.insertOut(testFailed);
lastIfBlock.insertOut(subclassTest);
container.getCfg().linkInCodeOrder(lastIfBlock, subclassTest);
lastIfBlock = subclassTest;
}
tmp = InlineGuard.create(IG_METHOD_TEST, receiver.copy(), Call.getGuard(callSite).copy(), MethodOperand.VIRTUAL(target.getMemberRef().asMethodReference(), target), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
} else {
tmp = InlineGuard.create(IG_PATCH_POINT, receiver.copy(), Call.getGuard(callSite).copy(), MethodOperand.VIRTUAL(target.getMemberRef().asMethodReference(), target), testFailed.makeJumpTarget(), inlDec.OSRTestFailed() ? BranchProfileOperand.never() : BranchProfileOperand.unlikely());
}
tmp.copyPosition(callSite);
lastIfBlock.appendInstruction(tmp);
lastIfBlock.insertOut(testFailed);
lastIfBlock.insertOut(children[i].getPrologue());
container.getCfg().linkInCodeOrder(lastIfBlock, children[i].getCfg().firstInCodeOrder());
if (children[i].getEpilogue() != null) {
children[i].getEpilogue().appendInstruction(container.getEpilogue().makeGOTO());
children[i].getEpilogue().insertOut(container.getEpilogue());
}
container.getCfg().linkInCodeOrder(children[i].getCfg().lastInCodeOrder(), testFailed);
}
// Step 6: finish by linking container.prologue & testFailed
container.getPrologue().insertOut(testFailed);
container.getCfg().linkInCodeOrder(container.getPrologue(), testFailed);
return container;
} else {
if (VM.VerifyAssertions)
VM._assert(inlDec.getNumberOfTargets() == 1);
NormalMethod callee = (NormalMethod) inlDec.getTargets()[0];
if (parent.getOptions().PRINT_INLINE_REPORT) {
VM.sysWriteln("\tInline " + callee + " into " + callSite.position().getMethod() + " at bytecode " + callSite.getBytecodeIndex());
}
GenerationContext child = parent.createChildContext(ebag, callee, callSite);
BC2IR.generateHIR(child);
child.transferStateToParent();
return child;
}
}
use of org.jikesrvm.compilers.opt.ir.operand.TypeOperand in project JikesRVM by JikesRVM.
the class ExceptionHandlerBasicBlock method mustCatchException.
/**
* Return YES/NO/MAYBE values that answer the question is it guarenteed that
* this handler block will catch an exception of type <code>cand</code>
*
* @param cand the TypeReference of the exception in question.
* @return YES, NO, MAYBE
*/
public byte mustCatchException(TypeReference cand) {
boolean seenMaybe = false;
byte t;
for (TypeOperand exceptionType : exceptionTypes) {
t = ClassLoaderProxy.includesType(exceptionType.getTypeRef(), cand);
if (t == YES)
return YES;
seenMaybe |= (t == MAYBE);
}
if (seenMaybe) {
return MAYBE;
} else {
return NO;
}
}
use of org.jikesrvm.compilers.opt.ir.operand.TypeOperand in project JikesRVM by JikesRVM.
the class GenerationContextTest method assertThatRethrowBlockIsCorrect.
private void assertThatRethrowBlockIsCorrect(InlineSequence inlineSequence, Operand lockObject, ExceptionHandlerBasicBlock rethrow) {
Enumeration<TypeOperand> exceptionTypes = rethrow.getExceptionTypes();
TypeOperand firstHandledException = exceptionTypes.nextElement();
assertThat(exceptionTypes.hasMoreElements(), is(false));
assertTrue(firstHandledException.similar(new TypeOperand(RVMType.JavaLangThrowableType)));
Enumeration<Instruction> rethrowInstructions = rethrow.forwardRealInstrEnumerator();
Instruction firstInstructionInRethrow = rethrowInstructions.nextElement();
assertThat(firstInstructionInRethrow.operator(), is(GET_CAUGHT_EXCEPTION));
assertThat(firstInstructionInRethrow.getBytecodeIndex(), is(SYNTH_CATCH_BCI));
assertTrue(firstInstructionInRethrow.position().equals(inlineSequence));
RegisterOperand catchExceptionObject = Nullary.getResult(firstInstructionInRethrow);
assertThat(catchExceptionObject.getType(), is(TypeReference.JavaLangThrowable));
Instruction secondInstructionInRethrow = rethrowInstructions.nextElement();
assertThatNoMoreInstructionsExist(rethrowInstructions);
assertThat(secondInstructionInRethrow.operator(), is(CALL));
MethodOperand methodOp = Call.getMethod(secondInstructionInRethrow);
assertTrue(methodOp.getTarget().equals(Entrypoints.unlockAndThrowMethod));
assertTrue(methodOp.isNonReturningCall());
Operand callAddress = Call.getAddress(secondInstructionInRethrow);
Address actualAddress = callAddress.asAddressConstant().value;
Address expectedAddress = Entrypoints.unlockAndThrowMethod.getOffset().toWord().toAddress();
assertTrue(actualAddress.EQ(expectedAddress));
Operand lockObjectFromRethrow = Call.getParam(secondInstructionInRethrow, 0);
assertTrue(lockObjectFromRethrow.similar(lockObject));
RegisterOperand catchOperand = Call.getParam(secondInstructionInRethrow, 1).asRegister();
assertTrue(catchOperand.sameRegisterPropertiesAs(catchExceptionObject));
assertTrue(rethrow.mayThrowUncaughtException());
assertTrue(rethrow.canThrowExceptions());
}
use of org.jikesrvm.compilers.opt.ir.operand.TypeOperand in project JikesRVM by JikesRVM.
the class ExpandRuntimeServices method perform.
/**
* Given an HIR, expand operators that are implemented as calls to
* runtime service methods. This method should be called as one of the
* first steps in lowering HIR into LIR.
*
* @param ir The HIR to expand
*/
@Override
public void perform(IR ir) {
// resync generation context -- yuck...
ir.getGc().resync();
for (Instruction inst = ir.firstInstructionInCodeOrder(); inst != null; inst = next) {
next = inst.nextInstructionInCodeOrder();
int opcode = inst.getOpcode();
switch(opcode) {
case NEW_opcode:
{
TypeOperand Type = New.getClearType(inst);
RVMClass cls = (RVMClass) Type.getVMType();
IntConstantOperand hasFinalizer = IRTools.IC(cls.hasFinalizer() ? 1 : 0);
RVMMethod callSite = inst.position().getMethod();
IntConstantOperand allocator = IRTools.IC(MemoryManager.pickAllocator(cls, callSite));
IntConstantOperand align = IRTools.IC(ObjectModel.getAlignment(cls));
IntConstantOperand offset = IRTools.IC(ObjectModel.getOffsetForAlignment(cls, false));
Operand tib = ConvertToLowLevelIR.getTIB(inst, ir, Type);
if (VM.BuildForIA32 && VM.runningVM) {
// shield BC2IR from address constants
RegisterOperand tmp = ir.regpool.makeTemp(TypeReference.TIB);
inst.insertBefore(Move.create(REF_MOVE, tmp, tib));
tib = tmp.copyRO();
}
IntConstantOperand site = IRTools.IC(MemoryManager.getAllocationSite(true));
RVMMethod target = Entrypoints.resolvedNewScalarMethod;
Call.mutate7(inst, CALL, New.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), IRTools.IC(cls.getInstanceSize()), tib, hasFinalizer, allocator, align, offset, site);
next = inst.prevInstructionInCodeOrder();
if (ir.options.H2L_INLINE_NEW) {
if (inst.getBasicBlock().getInfrequent())
container.counter1++;
container.counter2++;
if (!ir.options.FREQ_FOCUS_EFFORT || !inst.getBasicBlock().getInfrequent()) {
inline(inst, ir);
}
}
}
break;
case NEW_UNRESOLVED_opcode:
{
int typeRefId = New.getType(inst).getTypeRef().getId();
RVMMethod target = Entrypoints.unresolvedNewScalarMethod;
IntConstantOperand site = IRTools.IC(MemoryManager.getAllocationSite(true));
Call.mutate2(inst, CALL, New.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), IRTools.IC(typeRefId), site);
}
break;
case NEWARRAY_opcode:
{
TypeOperand Array = NewArray.getClearType(inst);
RVMArray array = (RVMArray) Array.getVMType();
Operand numberElements = NewArray.getClearSize(inst);
boolean inline = numberElements instanceof IntConstantOperand;
Operand width = IRTools.IC(array.getLogElementSize());
Operand headerSize = IRTools.IC(ObjectModel.computeArrayHeaderSize(array));
RVMMethod callSite = inst.position().getMethod();
IntConstantOperand allocator = IRTools.IC(MemoryManager.pickAllocator(array, callSite));
IntConstantOperand align = IRTools.IC(ObjectModel.getAlignment(array));
IntConstantOperand offset = IRTools.IC(ObjectModel.getOffsetForAlignment(array, false));
Operand tib = ConvertToLowLevelIR.getTIB(inst, ir, Array);
if (VM.BuildForIA32 && VM.runningVM) {
// shield BC2IR from address constants
RegisterOperand tmp = ir.regpool.makeTemp(TypeReference.TIB);
inst.insertBefore(Move.create(REF_MOVE, tmp, tib));
tib = tmp.copyRO();
}
IntConstantOperand site = IRTools.IC(MemoryManager.getAllocationSite(true));
RVMMethod target = Entrypoints.resolvedNewArrayMethod;
Call.mutate8(inst, CALL, NewArray.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), numberElements, width, headerSize, tib, allocator, align, offset, site);
next = inst.prevInstructionInCodeOrder();
if (inline && ir.options.H2L_INLINE_NEW) {
if (inst.getBasicBlock().getInfrequent())
container.counter1++;
container.counter2++;
if (!ir.options.FREQ_FOCUS_EFFORT || !inst.getBasicBlock().getInfrequent()) {
inline(inst, ir);
}
}
}
break;
case NEWARRAY_UNRESOLVED_opcode:
{
int typeRefId = NewArray.getType(inst).getTypeRef().getId();
Operand numberElements = NewArray.getClearSize(inst);
RVMMethod target = Entrypoints.unresolvedNewArrayMethod;
IntConstantOperand site = IRTools.IC(MemoryManager.getAllocationSite(true));
Call.mutate3(inst, CALL, NewArray.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), numberElements, IRTools.IC(typeRefId), site);
}
break;
case NEWOBJMULTIARRAY_opcode:
{
int dimensions = Multianewarray.getNumberOfDimensions(inst);
RVMMethod callSite = inst.position().getMethod();
int typeRefId = Multianewarray.getType(inst).getTypeRef().getId();
if (dimensions == 2) {
RVMMethod target = Entrypoints.optNew2DArrayMethod;
Call.mutate4(inst, CALL, Multianewarray.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), IRTools.IC(callSite.getId()), Multianewarray.getClearDimension(inst, 0), Multianewarray.getClearDimension(inst, 1), IRTools.IC(typeRefId));
} else {
// Step 1: Create an int array to hold the dimensions.
TypeOperand dimArrayType = new TypeOperand(RVMArray.IntArray);
RegisterOperand dimArray = ir.regpool.makeTemp(TypeReference.IntArray);
dimArray.setPreciseType();
next = NewArray.create(NEWARRAY, dimArray, dimArrayType, new IntConstantOperand(dimensions));
inst.insertBefore(next);
// Step 2: Assign the dimension values to dimArray
for (int i = 0; i < dimensions; i++) {
LocationOperand loc = new LocationOperand(TypeReference.Int);
inst.insertBefore(AStore.create(INT_ASTORE, Multianewarray.getClearDimension(inst, i), dimArray.copyD2U(), IRTools.IC(i), loc, IRTools.TG()));
}
// Step 3. Plant call to OptLinker.newArrayArray
RVMMethod target = Entrypoints.optNewArrayArrayMethod;
Call.mutate3(inst, CALL, Multianewarray.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), IRTools.IC(callSite.getId()), dimArray.copyD2U(), IRTools.IC(typeRefId));
}
}
break;
case ATHROW_opcode:
{
RVMMethod target = Entrypoints.athrowMethod;
MethodOperand methodOp = MethodOperand.STATIC(target);
// Record the fact that this is a non-returning call.
methodOp.setIsNonReturningCall(true);
Call.mutate1(inst, CALL, null, IRTools.AC(target.getOffset()), methodOp, Athrow.getClearValue(inst));
}
break;
case MONITORENTER_opcode:
{
Operand ref = MonitorOp.getClearRef(inst);
RVMType refType = ref.getType().peekType();
if (refType != null && !refType.getThinLockOffset().isMax()) {
RVMMethod target = Entrypoints.inlineLockMethod;
Call.mutate2(inst, CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), MonitorOp.getClearGuard(inst), ref, IRTools.AC(refType.getThinLockOffset()));
next = inst.prevInstructionInCodeOrder();
if (inst.getBasicBlock().getInfrequent())
container.counter1++;
container.counter2++;
if (!ir.options.FREQ_FOCUS_EFFORT || !inst.getBasicBlock().getInfrequent()) {
inline(inst, ir);
}
} else {
RVMMethod target = Entrypoints.lockMethod;
Call.mutate1(inst, CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), MonitorOp.getClearGuard(inst), ref);
}
}
break;
case MONITOREXIT_opcode:
{
Operand ref = MonitorOp.getClearRef(inst);
RVMType refType = ref.getType().peekType();
if (refType != null && !refType.getThinLockOffset().isMax()) {
RVMMethod target = Entrypoints.inlineUnlockMethod;
Call.mutate2(inst, CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), MonitorOp.getClearGuard(inst), ref, IRTools.AC(refType.getThinLockOffset()));
next = inst.prevInstructionInCodeOrder();
if (inst.getBasicBlock().getInfrequent())
container.counter1++;
container.counter2++;
if (!ir.options.FREQ_FOCUS_EFFORT || !inst.getBasicBlock().getInfrequent()) {
inline(inst, ir);
}
} else {
RVMMethod target = Entrypoints.unlockMethod;
Call.mutate1(inst, CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), MonitorOp.getClearGuard(inst), ref);
}
}
break;
case REF_ASTORE_opcode:
{
if (NEEDS_OBJECT_ASTORE_BARRIER) {
RVMMethod target = Entrypoints.objectArrayWriteBarrierMethod;
Instruction wb = Call.create3(CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), AStore.getClearGuard(inst), AStore.getArray(inst).copy(), AStore.getIndex(inst).copy(), AStore.getValue(inst).copy());
replaceInstructionWithBarrier(inst, wb);
if (ir.options.H2L_INLINE_WRITE_BARRIER) {
inline(wb, ir, true);
}
}
}
break;
case BYTE_ASTORE_opcode:
{
if (NEEDS_BYTE_ASTORE_BARRIER) {
primitiveArrayStoreHelper(Entrypoints.byteArrayWriteBarrierMethod, inst, ir);
}
}
break;
case DOUBLE_ASTORE_opcode:
{
if (NEEDS_DOUBLE_ASTORE_BARRIER) {
primitiveArrayStoreHelper(Entrypoints.doubleArrayWriteBarrierMethod, inst, ir);
}
}
break;
case FLOAT_ASTORE_opcode:
{
if (NEEDS_FLOAT_ASTORE_BARRIER) {
primitiveArrayStoreHelper(Entrypoints.floatArrayWriteBarrierMethod, inst, ir);
}
}
break;
case INT_ASTORE_opcode:
{
if (NEEDS_INT_ASTORE_BARRIER) {
primitiveArrayStoreHelper(Entrypoints.intArrayWriteBarrierMethod, inst, ir);
}
}
break;
case LONG_ASTORE_opcode:
{
if (NEEDS_LONG_ASTORE_BARRIER) {
primitiveArrayStoreHelper(Entrypoints.longArrayWriteBarrierMethod, inst, ir);
}
}
break;
case SHORT_ASTORE_opcode:
{
TypeReference type = AStore.getLocation(inst).getElementType();
if (NEEDS_SHORT_ASTORE_BARRIER && type.isShortType()) {
primitiveArrayStoreHelper(Entrypoints.shortArrayWriteBarrierMethod, inst, ir);
} else if (NEEDS_CHAR_ASTORE_BARRIER) {
if (VM.VerifyAssertions)
VM._assert(type.isCharType());
primitiveArrayStoreHelper(Entrypoints.charArrayWriteBarrierMethod, inst, ir);
}
}
break;
case REF_ALOAD_opcode:
{
if (NEEDS_OBJECT_ALOAD_BARRIER) {
RVMMethod target = Entrypoints.objectArrayReadBarrierMethod;
Instruction rb = Call.create2(CALL, ALoad.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), ALoad.getClearGuard(inst), ALoad.getArray(inst).copy(), ALoad.getIndex(inst).copy());
replaceInstructionWithBarrier(inst, rb);
inline(rb, ir, true);
}
}
break;
case PUTFIELD_opcode:
{
if (NEEDS_OBJECT_PUTFIELD_BARRIER) {
LocationOperand loc = PutField.getLocation(inst);
FieldReference fieldRef = loc.getFieldRef();
if (!fieldRef.getFieldContentsType().isPrimitiveType()) {
// reference PUTFIELD
RVMField field = fieldRef.peekResolvedField();
if (field == null || !field.isUntraced()) {
RVMMethod target = Entrypoints.objectFieldWriteBarrierMethod;
Instruction wb = Call.create4(CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), PutField.getClearGuard(inst), PutField.getRef(inst).copy(), PutField.getValue(inst).copy(), PutField.getOffset(inst).copy(), IRTools.IC(fieldRef.getId()));
replaceInstructionWithBarrier(inst, wb);
if (ir.options.H2L_INLINE_WRITE_BARRIER) {
inline(wb, ir, true);
}
}
} else {
// primitive PUTFIELD
if (NEEDS_BOOLEAN_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isBooleanType()) {
primitiveObjectFieldStoreHelper(Entrypoints.booleanFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_BYTE_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isByteType()) {
primitiveObjectFieldStoreHelper(Entrypoints.byteFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_CHAR_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isCharType()) {
primitiveObjectFieldStoreHelper(Entrypoints.charFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_DOUBLE_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isDoubleType()) {
primitiveObjectFieldStoreHelper(Entrypoints.doubleFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_FLOAT_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isFloatType()) {
primitiveObjectFieldStoreHelper(Entrypoints.floatFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_INT_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isIntType()) {
primitiveObjectFieldStoreHelper(Entrypoints.intFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_LONG_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isLongType()) {
primitiveObjectFieldStoreHelper(Entrypoints.longFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_SHORT_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isShortType()) {
primitiveObjectFieldStoreHelper(Entrypoints.shortFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_WORD_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isWordType()) {
primitiveObjectFieldStoreHelper(Entrypoints.wordFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_ADDRESS_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isAddressType()) {
primitiveObjectFieldStoreHelper(Entrypoints.addressFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_EXTENT_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isExtentType()) {
primitiveObjectFieldStoreHelper(Entrypoints.extentFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_OFFSET_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isOffsetType()) {
primitiveObjectFieldStoreHelper(Entrypoints.offsetFieldWriteBarrierMethod, inst, ir, fieldRef);
}
}
}
}
break;
case GETFIELD_opcode:
{
if (NEEDS_OBJECT_GETFIELD_BARRIER) {
LocationOperand loc = GetField.getLocation(inst);
FieldReference fieldRef = loc.getFieldRef();
if (GetField.getResult(inst).getType().isReferenceType()) {
RVMField field = fieldRef.peekResolvedField();
if (field == null || !field.isUntraced()) {
RVMMethod target = Entrypoints.objectFieldReadBarrierMethod;
Instruction rb = Call.create3(CALL, GetField.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), GetField.getClearGuard(inst), GetField.getRef(inst).copy(), GetField.getOffset(inst).copy(), IRTools.IC(fieldRef.getId()));
replaceInstructionWithBarrier(inst, rb);
inline(rb, ir, true);
}
}
}
}
break;
case PUTSTATIC_opcode:
{
if (NEEDS_OBJECT_PUTSTATIC_BARRIER) {
LocationOperand loc = PutStatic.getLocation(inst);
FieldReference field = loc.getFieldRef();
if (!field.getFieldContentsType().isPrimitiveType()) {
RVMMethod target = Entrypoints.objectStaticWriteBarrierMethod;
Instruction wb = Call.create3(CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), PutStatic.getValue(inst).copy(), PutStatic.getOffset(inst).copy(), IRTools.IC(field.getId()));
replaceInstructionWithBarrier(inst, wb);
if (ir.options.H2L_INLINE_WRITE_BARRIER) {
inline(wb, ir, true);
}
}
}
}
break;
case GETSTATIC_opcode:
{
if (NEEDS_OBJECT_GETSTATIC_BARRIER) {
LocationOperand loc = GetStatic.getLocation(inst);
FieldReference field = loc.getFieldRef();
if (!field.getFieldContentsType().isPrimitiveType()) {
RVMMethod target = Entrypoints.objectStaticReadBarrierMethod;
Instruction rb = Call.create2(CALL, GetStatic.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), GetStatic.getOffset(inst).copy(), IRTools.IC(field.getId()));
replaceInstructionWithBarrier(inst, rb);
inline(rb, ir, true);
}
}
}
break;
default:
break;
}
}
// If we actually inlined anything, clean up the mess
if (didSomething) {
if (branchOpts == null) {
branchOpts = new BranchOptimizations(-1, true, true);
}
branchOpts.perform(ir, true);
if (_os == null) {
_os = new Simple(1, false, false, false, false);
}
_os.perform(ir);
}
// signal that we do not intend to use the gc in other phases anymore.
ir.getGc().close();
}
use of org.jikesrvm.compilers.opt.ir.operand.TypeOperand in project JikesRVM by JikesRVM.
the class GenerationContext method completeExceptionHandlers.
/**
* If the method is synchronized then we wrap it in a
* synthetic exception handler that unlocks & rethrows
* PRECONDITION: cfg, arguments & temps have been setup/initialized.
*
* @param isOutermost is this the outermost context (i.e. not an inlined context)
*/
private void completeExceptionHandlers(boolean isOutermost) {
if (method.isSynchronized() && !options.ESCAPE_INVOKEE_THREAD_LOCAL) {
ExceptionHandlerBasicBlock rethrow = new ExceptionHandlerBasicBlock(SYNTH_CATCH_BCI, inlineSequence, new TypeOperand(RVMType.JavaLangThrowableType), cfg);
rethrow.setExceptionHandlers(enclosingHandlers);
RegisterOperand ceo = temps.makeTemp(TypeReference.JavaLangThrowable);
Instruction s = Nullary.create(GET_CAUGHT_EXCEPTION, ceo);
appendInstruction(rethrow, s, SYNTH_CATCH_BCI);
Operand lockObject = getLockObject();
RVMMethod target = Entrypoints.unlockAndThrowMethod;
MethodOperand methodOp = MethodOperand.STATIC(target);
// Used to keep cfg correct
methodOp.setIsNonReturningCall(true);
s = Call.create2(CALL, null, new AddressConstantOperand(target.getOffset()), methodOp, lockObject, ceo.copyD2U());
appendInstruction(rethrow, s, RUNTIME_SERVICES_BCI);
cfg.insertBeforeInCodeOrder(epilogue, rethrow);
// (if enclosed by another catch of Throwable...)
if (enclosingHandlers != null) {
for (Enumeration<BasicBlock> e = enclosingHandlers.enumerator(); e.hasMoreElements(); ) {
BasicBlock eh = e.nextElement();
rethrow.insertOut(eh);
}
}
rethrow.setCanThrowExceptions();
rethrow.setMayThrowUncaughtException();
rethrow.insertOut(exit);
// save a reference to this block so we can discard it if unused.
unlockAndRethrow = rethrow;
ExceptionHandlerBasicBlock[] sh = new ExceptionHandlerBasicBlock[1];
sh[0] = rethrow;
enclosingHandlers = new ExceptionHandlerBasicBlockBag(sh, enclosingHandlers);
generatedExceptionHandlers = true;
}
}
Aggregations