use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method mustImplementInterface.
/**
* Expand a checkcastInterface instruction into the LIR sequence that
* implements the dynamic type check, raising an IncompataibleClassChangeError
* if the type check fails.
* Ref is known to never contain a null ptr at runtime.
*
* @param s a MUST_IMPLEMENT_INTERFACE instruction to expand
* @param ir the enclosing IR
* @return the last Instruction in the generated LIR sequence.
*/
static Instruction mustImplementInterface(Instruction s, IR ir) {
Operand ref = TypeCheck.getClearRef(s);
RVMClass LHSClass = (RVMClass) TypeCheck.getType(s).getVMType();
if (VM.VerifyAssertions)
VM._assert(LHSClass != null, "Should be resolvable...");
int interfaceIndex = LHSClass.getDoesImplementIndex();
int interfaceMask = LHSClass.getDoesImplementBitMask();
Operand guard = TypeCheck.getClearGuard(s);
BasicBlock myBlock = s.getBasicBlock();
BasicBlock failBlock = myBlock.createSubBlock(s.getBytecodeIndex(), ir, .0001f);
BasicBlock succBlock = myBlock.splitNodeAt(s, ir);
succBlock.firstInstruction().insertAfter(Move.create(REF_MOVE, TypeCheck.getClearResult(s), ref.copy()));
myBlock.insertOut(failBlock);
myBlock.insertOut(succBlock);
ir.cfg.linkInCodeOrder(myBlock, succBlock);
ir.cfg.addLastInCodeOrder(failBlock);
Instruction raiseError = Trap.create(TRAP, null, TrapCodeOperand.MustImplement());
raiseError.copyPosition(s);
failBlock.appendInstruction(raiseError);
Operand RHStib = getTIB(s, ir, ref, guard);
RegisterOperand doesImpl = InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
RegisterOperand doesImplLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
Instruction lengthCheck = IfCmp.create(INT_IFCMP, ir.regpool.makeTempValidation(), doesImplLength, IC(interfaceIndex), ConditionOperand.LESS_EQUAL(), failBlock.makeJumpTarget(), BranchProfileOperand.never());
s.insertBefore(lengthCheck);
myBlock.splitNodeWithLinksAt(lengthCheck, ir);
// required due to splitNode!
myBlock.insertOut(failBlock);
}
RegisterOperand entry = InsertLoadOffset(s, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
RegisterOperand bit = insertBinary(s, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
IfCmp.mutate(s, INT_IFCMP, ir.regpool.makeTempValidation(), bit, IC(0), ConditionOperand.EQUAL(), failBlock.makeJumpTarget(), BranchProfileOperand.never());
return s;
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method generateBranchingTypeCheck.
/**
* Generate a branching dynamic type check.
* This routine assumes that the CFG and code order are already
* correctly established.
* This routine must either remove s or mutate it.
*
* @param s The Instruction that is to be replaced by a
* branching type check
* @param ir The IR containing the instruction to be expanded.
* @param RHSobj The RegisterOperand containing the rhs object.
* @param LHStype The TypeReference to be tested against.
* @param RHStib The Operand containing the TIB of the rhs.
* @param trueBlock The BasicBlock to continue at if the typecheck
* evaluates to true
* @param falseBlock The BasicBlock to continue at if the typecheck
* evaluates to false.
* @param oldGuard A suitable guard operand (not necessarily related
* the instruction that is to be replaced).
* @param falseProb The probability that typecheck will branch to the falseBlock
* @return the opt instruction immediately before the instruction to
* continue expansion.
*/
private static Instruction generateBranchingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, BasicBlock trueBlock, BasicBlock falseBlock, RegisterOperand oldGuard, BranchProfileOperand falseProb) {
Instruction continueAt = Goto.create(GOTO, trueBlock.makeJumpTarget());
continueAt.copyPosition(s);
s.insertBefore(continueAt);
s.remove();
if (LHStype.isClassType()) {
RVMClass LHSclass = (RVMClass) LHStype.peekType();
if (LHSclass != null && LHSclass.isResolved()) {
// class or interface
if (LHSclass.isInterface()) {
// A resolved interface (case 4)
int interfaceIndex = LHSclass.getDoesImplementIndex();
int interfaceMask = LHSclass.getDoesImplementBitMask();
RegisterOperand doesImpl = InsertUnary(continueAt, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
RegisterOperand doesImplLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, doesImplLength, IC(interfaceIndex), ConditionOperand.LESS_EQUAL(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(lengthCheck);
BasicBlock oldBlock = continueAt.getBasicBlock();
oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
// required due to splitNode!
oldBlock.insertOut(falseBlock);
}
RegisterOperand entry = InsertLoadOffset(continueAt, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
RegisterOperand bit = insertBinary(continueAt, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, bit, IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
} else {
// A resolved class (cases 5 and 6 in DynamicTypeCheck)
if (LHSclass.isFinal()) {
// For a final class, we can do a PTR compare of
// rhsTIB and the TIB of the class
Operand classTIB = getTIB(continueAt, ir, LHSclass);
continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
} else {
// Do the full blown case 5 or 6 typecheck.
int LHSDepth = LHSclass.getTypeDepth();
int LHSId = LHSclass.getId();
RegisterOperand superclassIds = InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
RegisterOperand superclassIdsLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, superclassIdsLength, IC(LHSDepth), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(lengthCheck);
BasicBlock oldBlock = continueAt.getBasicBlock();
oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
// required due to splitNode!
oldBlock.insertOut(falseBlock);
}
RegisterOperand refCandidate = InsertLoadOffset(continueAt, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, refCandidate, IC(LHSId), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
} else {
// A non-resolved class or interface. Case 3 of DynamicTypeCheck
// Branch on the result of a call to
// RuntimeEntrypoints.instance
RegisterOperand result = ir.regpool.makeTempInt();
RVMMethod target = Entrypoints.instanceOfMethod;
Instruction call = Call.create2(CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
call.copyPosition(continueAt);
continueAt.insertBefore(call);
call = callHelper(call, ir);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, result.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
if (LHStype.isArrayType()) {
// Case 2 of DynamicTypeCheck: LHS is an array.
RVMArray LHSArray = (RVMArray) LHStype.peekType();
if (LHSArray != null) {
Operand classTIB = getTIB(continueAt, ir, LHSArray);
RVMType innermostElementType = LHSArray.getInnermostElementType();
if (innermostElementType.isPrimitiveType() || innermostElementType.isUnboxedType() || (innermostElementType.asClass().isResolved() && innermostElementType.asClass().isFinal())) {
// [^k of primitive or [^k of final class. Just like final classes,
// a PTR compare of rhsTIB and the TIB of the class gives the answer.
continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
// TODO: branch probability calculation is somewhat bogus for this case.
Instruction shortcircuit = IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.EQUAL(), trueBlock.makeJumpTarget(), new BranchProfileOperand());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(shortcircuit);
BasicBlock myBlock = shortcircuit.getBasicBlock();
BasicBlock mainBlock = myBlock.splitNodeWithLinksAt(shortcircuit, ir);
// must come after the splitNodeAt
myBlock.insertOut(trueBlock);
RegisterOperand rhsType = InsertUnary(continueAt, ir, GET_TYPE_FROM_TIB, TypeReference.Type, RHStib.copy());
if (innermostElementType.isJavaLangObjectType()) {
IntConstantOperand lhsDimension = IC(LHStype.getDimensionality());
RegisterOperand rhsDimension = getField(continueAt, ir, rhsType, Entrypoints.dimensionField);
Instruction dimTest = IfCmp2.create(INT_IFCMP2, oldGuard, rhsDimension, lhsDimension, ConditionOperand.GREATER(), trueBlock.makeJumpTarget(), ((BranchProfileOperand) falseProb.copy()).flip(), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), (BranchProfileOperand) falseProb.copy());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(dimTest);
// BasicBlock testBlock =
mainBlock.splitNodeWithLinksAt(dimTest, ir);
mainBlock.insertOut(trueBlock);
mainBlock.insertOut(falseBlock);
RegisterOperand rhsInnermostElementTypeDimension = getField(continueAt, ir, rhsType.copyU2U(), Entrypoints.innermostElementTypeDimensionField);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, rhsInnermostElementTypeDimension, IC(0), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
// Not a case we want to handle inline
RVMMethod target = Entrypoints.instanceOfMethod;
RegisterOperand callResult = ir.regpool.makeTempInt();
Instruction call = Call.create2(CALL, callResult, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
call.copyPosition(continueAt);
continueAt.insertBefore(call);
call = callHelper(call, ir);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, callResult.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
OptimizingCompilerException.UNREACHABLE();
return null;
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand 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.Operand 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;
}
}
use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.
the class GenerationContext method createChildContext.
/**
* Creates a child generation context from this context
* and callerBB to generate IR for callsite.
*
* @param ebag the enclosing exception handlers (null if none)
* @param callee the callee method to be inlined
* (may _not_ be equal to Call.getMethod(callSite).method)
* @param callSite the Call instruction to be inlined.
* @return the child context
*/
public GenerationContext createChildContext(ExceptionHandlerBasicBlockBag ebag, NormalMethod callee, Instruction callSite) {
// Note: In this method, use "this" explicitly to refer to parent fields in order
// to avoid confusing parent/child fields.
GenerationContext child = new GenerationContext();
child.method = callee;
if (this.options.frequencyCounters() || this.options.inverseFrequencyCounters()) {
child.branchProfiles = EdgeCounts.getBranchProfiles(callee);
}
child.parent = this;
child.original_cm = this.original_cm;
// Some state gets directly copied to the child
child.options = this.options;
child.temps = this.temps;
child._ncGuards = this._ncGuards;
child.exit = this.exit;
child.inlinePlan = this.inlinePlan;
// Now inherit state based on callSite
child.inlineSequence = new InlineSequence(child.method, callSite.position(), callSite);
child.enclosingHandlers = ebag;
child.arguments = new Operand[Call.getNumberOfParams(callSite)];
for (int i = 0; i < child.arguments.length; i++) {
// copy instead
child.arguments[i] = Call.getParam(callSite, i).copy();
// of clearing in case inlining aborts.
}
if (Call.hasResult(callSite)) {
child.resultReg = Call.getResult(callSite).copyD2D().getRegister();
// it will...
child.resultReg.setSpansBasicBlock();
}
// Initialize the child CFG, prologue, and epilogue blocks
child.cfg = new ControlFlowGraph(this.cfg.numberOfNodes());
child.prologue = new BasicBlock(PROLOGUE_BCI, child.inlineSequence, child.cfg);
child.prologue.setExceptionHandlers(ebag);
child.epilogue = new BasicBlock(EPILOGUE_BCI, child.inlineSequence, child.cfg);
child.epilogue.setExceptionHandlers(ebag);
child.cfg.addLastInCodeOrder(child.prologue);
child.cfg.addLastInCodeOrder(child.epilogue);
// Set up the local pool
child.initLocalPool();
// Insert moves from child.arguments to child's locals in prologue
TypeReference[] params = child.method.getParameterTypes();
int numParams = params.length;
int argIdx = 0;
int localNum = 0;
if (!child.method.isStatic()) {
Operand receiver = child.arguments[argIdx];
argIdx++;
RegisterOperand local = null;
if (receiver.isRegister()) {
RegisterOperand objPtr = receiver.asRegister();
if (ClassLoaderProxy.includesType(child.method.getDeclaringClass().getTypeRef(), objPtr.getType()) != YES) {
// narrow type of actual to match formal static type implied by method
// Can be precise but not assignable if enough classes aren't loaded
objPtr.clearPreciseType();
objPtr.setDeclaredType();
objPtr.setType(child.method.getDeclaringClass().getTypeRef());
}
local = child.makeLocal(localNum, objPtr);
localNum++;
// Avoid confusion in BC2IR of callee
child.arguments[0] = local;
// when objPtr is a local in the caller.
} else if (receiver.isConstant()) {
local = child.makeLocal(localNum, receiver.getType());
localNum++;
local.setPreciseType();
// Constants trivially non-null
RegisterOperand guard = child.makeNullCheckGuard(local.getRegister());
BC2IR.setGuardForRegOp(local, guard);
child.prologue.appendInstruction(Move.create(GUARD_MOVE, guard.copyRO(), new TrueGuardOperand()));
} else {
OptimizingCompilerException.UNREACHABLE("Unexpected receiver operand");
}
Instruction s = Move.create(REF_MOVE, local, receiver);
s.setSourcePosition(PROLOGUE_BCI, callSite.position());
child.prologue.appendInstruction(s);
}
for (int paramIdx = 0; paramIdx < numParams; paramIdx++, argIdx++) {
TypeReference argType = params[paramIdx];
RegisterOperand formal;
Operand actual = child.arguments[argIdx];
if (actual.isRegister()) {
RegisterOperand rActual = actual.asRegister();
if (ClassLoaderProxy.includesType(argType, rActual.getType()) != YES) {
// narrow type of actual to match formal static type implied by method
// Can be precise but not
rActual.clearPreciseType();
// assignable if enough classes aren't loaded
rActual.setDeclaredType();
rActual.setType(argType);
}
formal = child.makeLocal(localNum, rActual);
localNum++;
// Avoid confusion in BC2IR of
child.arguments[argIdx] = formal;
// callee when arg is a local in the caller.
} else {
formal = child.makeLocal(localNum, argType);
localNum++;
}
Instruction s = Move.create(IRTools.getMoveOp(argType), formal, actual);
s.setSourcePosition(PROLOGUE_BCI, callSite.position());
child.prologue.appendInstruction(s);
if (argType.isLongType() || argType.isDoubleType()) {
// longs and doubles take two local words
localNum++;
}
}
child.completePrologue(false);
child.completeEpilogue(false);
child.completeExceptionHandlers(false);
return child;
}
Aggregations