use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method GET_EXCEPTION_OBJECT.
/**
* Emit code to get a caught exception object into a register
*/
protected final void GET_EXCEPTION_OBJECT(Instruction s) {
burs.ir.stackManager.forceFrameAllocation();
int offset = burs.ir.stackManager.allocateSpaceForCaughtException();
Register FP = regpool.getPhysicalRegisterSet().asPPC().getFP();
LocationOperand loc = new LocationOperand(-offset);
EMIT(MIR_Load.mutate(s, PPC_LAddr, Nullary.getClearResult(s), A(FP), IC(offset), loc, TG()));
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class ComplexLIR2MIRExpansion method float_2long.
private static Instruction float_2long(Instruction s, IR ir) {
Instruction nextInstr = s.nextInstructionInCodeOrder();
while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) {
nextInstr = nextInstr.nextInstructionInCodeOrder();
}
if (VM.BuildFor32Addr) {
// we need 6 basic blocks (in code order)
// 1: the current block that does a test to see if this is a regular f2l or
// branches to the maxint/NaN case
// 2: a block to perform a regular f2l
// 3: a block to test for NaN
// 4: a block to perform give maxint
// 5: a block to perform NaN
// 6: the next basic block
BasicBlock testBB = s.getBasicBlock();
BasicBlock nextBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, nextBB);
BasicBlock nanBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, nanBB);
BasicBlock maxintBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, maxintBB);
BasicBlock nanTestBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, nanTestBB);
BasicBlock f2lBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, f2lBB);
// Move the maxlongFloat value and the value into x87 registers and compare and
// branch if they are <= or unordered.
RegisterOperand resultHi = Unary.getResult(s).copyRO();
resultHi.setType(TypeReference.Int);
RegisterOperand resultLo = new RegisterOperand(ir.regpool.getSecondReg(resultHi.getRegister()), TypeReference.Int);
RegisterOperand value = Unary.getVal(s).asRegister().copyRO();
RegisterOperand cw = ir.regpool.makeTempInt();
MemoryOperand maxlong = BURS_Helpers.loadFromJTOC(ir, Entrypoints.maxlongFloatField.getOffset(), (byte) 4);
RegisterOperand st0 = new RegisterOperand(phys(ir).getST0(), TypeReference.Float);
RegisterOperand st1 = new RegisterOperand(phys(ir).getST1(), TypeReference.Float);
int offset = -ir.stackManager.allocateSpaceForConversion();
StackLocationOperand slLo = new StackLocationOperand(true, offset, 4);
StackLocationOperand slHi = new StackLocationOperand(true, offset + 4, 4);
StackLocationOperand sl = new StackLocationOperand(true, offset, 8);
MemoryOperand scratchLo = new MemoryOperand(ir.regpool.makeTROp(), null, (byte) 0, Entrypoints.scratchStorageField.getOffset(), (byte) 4, new LocationOperand(Entrypoints.scratchStorageField), null);
MemoryOperand scratchHi = new MemoryOperand(ir.regpool.makeTROp(), null, (byte) 0, Entrypoints.scratchStorageField.getOffset().plus(4), (byte) 4, new LocationOperand(Entrypoints.scratchStorageField), null);
s.insertBefore(CPOS(s, MIR_Move.create(IA32_MOVSS, slLo, value)));
s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0, slLo.copy())));
s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0.copyRO(), maxlong)));
MIR_Compare.mutate(s, IA32_FUCOMIP, st0.copyRO(), st1);
testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.LLE(), nanTestBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
testBB.insertOut(f2lBB);
testBB.insertOut(nanTestBB);
// Convert float to long knowing that if the value is < min long the Intel
// unspecified result is min long
// TODO: this would be a lot simpler and faster with SSE3's FISTTP instruction
f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FNSTCW, scratchLo.copy())));
f2lBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_MOVZX__W, cw, scratchLo.copy())));
f2lBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_OR, cw.copyRO(), IC(0xC00))));
f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, scratchHi, cw.copyRO())));
f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchHi.copy())));
f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FISTP, sl, st0.copyRO())));
f2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchLo.copy())));
f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo, slLo.copy())));
f2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi, slHi)));
f2lBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
f2lBB.insertOut(nextBB);
// Did the compare find a NaN or a maximum integer?
nanTestBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FSTP, st0.copyRO(), st0.copyRO())));
nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.PE(), nanBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
nanTestBB.insertOut(nanBB);
nanTestBB.insertOut(maxintBB);
// Value was >= max long
maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo.copyRO(), IC((int) Long.MAX_VALUE))));
maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi.copyRO(), IC((int) (Long.MAX_VALUE >>> 32)))));
maxintBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
maxintBB.insertOut(nextBB);
// In case of NaN result is 0
nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo.copyRO(), IC(0))));
nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi.copyRO(), IC(0))));
nanBB.insertOut(nextBB);
} else {
// we need 4 basic blocks (in code order)
// 1: the current block which includes a test for NaN
// 2: a block to perform regular f2l
// 3: a block to handle NaN (which gives a result of 0)
// 4: the next basic block
BasicBlock testBB = s.getBasicBlock();
BasicBlock nextBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, nextBB);
BasicBlock nanBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, nanBB);
BasicBlock f2lBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, f2lBB);
RegisterOperand result = Unary.getResult(s).copyRO();
RegisterOperand value = Unary.getVal(s).asRegister().copyRO();
RegisterOperand adjustment = ir.regpool.makeTempInt();
testBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, adjustment.copy(), IC(0))));
MemoryOperand maxlong = BURS_Helpers.loadFromJTOC(ir, Entrypoints.maxlongFloatField.getOffset(), (byte) 4);
MIR_Compare.mutate(s, IA32_UCOMISS, value.copy(), maxlong);
testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.PE(), nanBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
testBB.insertOut(f2lBB);
testBB.insertOut(nanBB);
f2lBB.appendInstruction(CPOS(s, MIR_Set.create(IA32_SET__B, adjustment.copy(), IA32ConditionOperand.LGE())));
f2lBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_CVTTSS2SI, result.copy(), value.copy())));
f2lBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, result.copy(), adjustment.copy())));
f2lBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
f2lBB.insertOut(nextBB);
// In case of NaN result is 0.
nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, result.copyRO(), LC(0))));
nanBB.insertOut(nextBB);
}
return nextInstr;
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class NormalizeConstants method perform.
/**
* Only thing we do for IA32 is to restrict the usage of
* String, Float, and Double constants. The rules are prepared
* to deal with everything else.
*
* @param ir IR to normalize
*/
public static void perform(IR ir) {
for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) {
// Get 'large' constants into a form the the BURS rules are
// prepared to deal with.
// Constants can't appear as defs, so only scan the uses.
//
int numUses = s.getNumberOfUses();
if (numUses > 0) {
int numDefs = s.getNumberOfDefs();
for (int idx = numDefs; idx < numUses + numDefs; idx++) {
Operand use = s.getOperand(idx);
if (use != null) {
if (use instanceof ObjectConstantOperand) {
ObjectConstantOperand oc = (ObjectConstantOperand) use;
if (oc.isMovableObjectConstant()) {
RegisterOperand rop = ir.regpool.makeTemp(use.getType());
Operand jtoc = ir.regpool.makeJTOCOp();
Offset offset = oc.offset;
if (offset.isZero()) {
if (use instanceof StringConstantOperand) {
throw new OptimizingCompilerException("String constant w/o valid JTOC offset");
} else if (use instanceof ClassConstantOperand) {
throw new OptimizingCompilerException("Class constant w/o valid JTOC offset");
}
offset = Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(oc.value));
}
LocationOperand loc = new LocationOperand(offset);
s.insertBefore(Load.create(IA32_REF_LOAD, rop, jtoc, wordOperandForReference(offset.toWord()), loc));
s.putOperand(idx, rop.copyD2U());
} else {
// Ensure object is in JTOC to keep it alive
Statics.findOrCreateObjectLiteral(oc.value);
s.putOperand(idx, wordOperandForReference(Magic.objectAsAddress(oc.value).toWord()));
}
} else if (use instanceof DoubleConstantOperand) {
RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Double);
Operand jtoc = ir.regpool.makeJTOCOp();
DoubleConstantOperand dc = (DoubleConstantOperand) use.copy();
if (dc.offset.isZero()) {
dc.offset = Offset.fromIntSignExtend(Statics.findOrCreateLongSizeLiteral(Double.doubleToLongBits(dc.value)));
}
s.insertBefore(Binary.create(MATERIALIZE_FP_CONSTANT, rop, jtoc, dc));
s.putOperand(idx, rop.copyD2U());
} else if (use instanceof FloatConstantOperand) {
RegisterOperand rop = ir.regpool.makeTemp(TypeReference.Float);
Operand jtoc = ir.regpool.makeJTOCOp();
FloatConstantOperand fc = (FloatConstantOperand) use.copy();
if (fc.offset.isZero()) {
fc.offset = Offset.fromIntSignExtend(Statics.findOrCreateIntSizeLiteral(Float.floatToIntBits(fc.value)));
}
s.insertBefore(Binary.create(MATERIALIZE_FP_CONSTANT, rop, jtoc, fc));
s.putOperand(idx, rop.copyD2U());
} else if (use instanceof NullConstantOperand) {
s.putOperand(idx, wordOperandForReference(Word.zero()));
} else if (use instanceof AddressConstantOperand) {
s.putOperand(idx, wordOperandForReference(((AddressConstantOperand) use).value.toWord()));
} else if (use instanceof TIBConstantOperand) {
RegisterOperand rop = ir.regpool.makeTemp(TypeReference.TIB);
Operand jtoc = ir.regpool.makeJTOCOp();
Offset offset = ((TIBConstantOperand) use).value.getTibOffset();
LocationOperand loc = new LocationOperand(offset);
s.insertBefore(Load.create(IA32_REF_LOAD, rop, jtoc, wordOperandForReference(offset.toWord()), loc));
s.putOperand(idx, rop.copyD2U());
} else if (use instanceof CodeConstantOperand) {
RegisterOperand rop = ir.regpool.makeTemp(TypeReference.CodeArray);
Operand jtoc = ir.regpool.makeJTOCOp();
Offset offset = ((CodeConstantOperand) use).value.findOrCreateJtocOffset();
LocationOperand loc = new LocationOperand(offset);
s.insertBefore(Load.create(IA32_REF_LOAD, rop, jtoc, wordOperandForReference(offset.toWord()), loc));
s.putOperand(idx, rop.copyD2U());
}
}
}
}
}
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method convert.
/**
* Converts the given HIR to LIR.
*
* @param ir IR to convert
* @param options the options for the conversion
*/
static void convert(IR ir, OptOptions options) {
boolean didArrayStoreCheck = false;
for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) {
switch(s.getOpcode()) {
case GETSTATIC_opcode:
{
LocationOperand loc = GetStatic.getClearLocation(s);
RegisterOperand result = GetStatic.getClearResult(s);
Operand address = ir.regpool.makeJTOCOp();
Operand offset = GetStatic.getClearOffset(s);
Load.mutate(s, IRTools.getLoadOp(loc.getFieldRef(), true), result, address, offset, loc);
}
break;
case PUTSTATIC_opcode:
{
LocationOperand loc = PutStatic.getClearLocation(s);
Operand value = PutStatic.getClearValue(s);
Operand address = ir.regpool.makeJTOCOp();
Operand offset = PutStatic.getClearOffset(s);
Store.mutate(s, IRTools.getStoreOp(loc.getFieldRef(), true), value, address, offset, loc);
}
break;
case PUTFIELD_opcode:
{
LocationOperand loc = PutField.getClearLocation(s);
Operand value = PutField.getClearValue(s);
Operand address = PutField.getClearRef(s);
Operand offset = PutField.getClearOffset(s);
Store.mutate(s, IRTools.getStoreOp(loc.getFieldRef(), false), value, address, offset, loc, PutField.getClearGuard(s));
}
break;
case GETFIELD_opcode:
{
LocationOperand loc = GetField.getClearLocation(s);
RegisterOperand result = GetField.getClearResult(s);
Operand address = GetField.getClearRef(s);
Operand offset = GetField.getClearOffset(s);
Load.mutate(s, IRTools.getLoadOp(loc.getFieldRef(), false), result, address, offset, loc, GetField.getClearGuard(s));
}
break;
case INT_ALOAD_opcode:
doArrayLoad(s, ir, INT_LOAD, 2);
break;
case LONG_ALOAD_opcode:
doArrayLoad(s, ir, LONG_LOAD, 3);
break;
case FLOAT_ALOAD_opcode:
doArrayLoad(s, ir, FLOAT_LOAD, 2);
break;
case DOUBLE_ALOAD_opcode:
doArrayLoad(s, ir, DOUBLE_LOAD, 3);
break;
case REF_ALOAD_opcode:
doArrayLoad(s, ir, REF_LOAD, LOG_BYTES_IN_ADDRESS);
break;
case BYTE_ALOAD_opcode:
doArrayLoad(s, ir, BYTE_LOAD, 0);
break;
case UBYTE_ALOAD_opcode:
doArrayLoad(s, ir, UBYTE_LOAD, 0);
break;
case USHORT_ALOAD_opcode:
doArrayLoad(s, ir, USHORT_LOAD, 1);
break;
case SHORT_ALOAD_opcode:
doArrayLoad(s, ir, SHORT_LOAD, 1);
break;
case INT_ASTORE_opcode:
doArrayStore(s, ir, INT_STORE, 2);
break;
case LONG_ASTORE_opcode:
doArrayStore(s, ir, LONG_STORE, 3);
break;
case FLOAT_ASTORE_opcode:
doArrayStore(s, ir, FLOAT_STORE, 2);
break;
case DOUBLE_ASTORE_opcode:
doArrayStore(s, ir, DOUBLE_STORE, 3);
break;
case REF_ASTORE_opcode:
doArrayStore(s, ir, REF_STORE, LOG_BYTES_IN_ADDRESS);
break;
case BYTE_ASTORE_opcode:
doArrayStore(s, ir, BYTE_STORE, 0);
break;
case SHORT_ASTORE_opcode:
doArrayStore(s, ir, SHORT_STORE, 1);
break;
case CALL_opcode:
s = callHelper(s, ir);
break;
case SYSCALL_opcode:
// a sequence of loads off the BootRecord to find the appropriate field.
if (Call.getMethod(s) != null) {
expandSysCallTarget(s, ir);
}
break;
case TABLESWITCH_opcode:
s = tableswitch(s, ir);
break;
case LOOKUPSWITCH_opcode:
s = lookup(s, ir);
break;
case OBJARRAY_STORE_CHECK_opcode:
s = DynamicTypeCheckExpansion.arrayStoreCheck(s, ir, true);
didArrayStoreCheck = true;
break;
case OBJARRAY_STORE_CHECK_NOTNULL_opcode:
s = DynamicTypeCheckExpansion.arrayStoreCheck(s, ir, false);
didArrayStoreCheck = true;
break;
case CHECKCAST_opcode:
case CHECKCAST_UNRESOLVED_opcode:
s = DynamicTypeCheckExpansion.checkcast(s, ir);
break;
case CHECKCAST_NOTNULL_opcode:
s = DynamicTypeCheckExpansion.checkcastNotNull(s, ir);
break;
case MUST_IMPLEMENT_INTERFACE_opcode:
s = DynamicTypeCheckExpansion.mustImplementInterface(s, ir);
break;
case IG_CLASS_TEST_opcode:
IfCmp.mutate(s, REF_IFCMP, ir.regpool.makeTempValidation(), getTIB(s, ir, InlineGuard.getClearValue(s), InlineGuard.getClearGuard(s)), getTIB(s, ir, InlineGuard.getGoal(s).asType()), ConditionOperand.NOT_EQUAL(), InlineGuard.getClearTarget(s), InlineGuard.getClearBranchProfile(s));
break;
case IG_METHOD_TEST_opcode:
{
MethodOperand methOp = InlineGuard.getClearGoal(s).asMethod();
Operand t1 = getTIB(s, ir, InlineGuard.getClearValue(s), InlineGuard.getClearGuard(s));
Operand t2 = getTIB(s, ir, methOp.getTarget().getDeclaringClass());
IfCmp.mutate(s, REF_IFCMP, ir.regpool.makeTempValidation(), getInstanceMethod(s, ir, t1, methOp.getTarget()), getInstanceMethod(s, ir, t2, methOp.getTarget()), ConditionOperand.NOT_EQUAL(), InlineGuard.getClearTarget(s), InlineGuard.getClearBranchProfile(s));
break;
}
case INSTANCEOF_opcode:
case INSTANCEOF_UNRESOLVED_opcode:
s = DynamicTypeCheckExpansion.instanceOf(s, ir);
break;
case INSTANCEOF_NOTNULL_opcode:
s = DynamicTypeCheckExpansion.instanceOfNotNull(s, ir);
break;
case INT_ZERO_CHECK_opcode:
{
TrapIf.mutate(s, TRAP_IF, ZeroCheck.getClearGuardResult(s), ZeroCheck.getClearValue(s), IC(0), ConditionOperand.EQUAL(), TrapCodeOperand.DivByZero());
}
break;
case LONG_ZERO_CHECK_opcode:
{
TrapIf.mutate(s, TRAP_IF, ZeroCheck.getClearGuardResult(s), ZeroCheck.getClearValue(s), LC(0), ConditionOperand.EQUAL(), TrapCodeOperand.DivByZero());
}
break;
case BOUNDS_CHECK_opcode:
{
// get array_length from array_ref
RegisterOperand array_length = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, BoundsCheck.getClearRef(s), BoundsCheck.getClearGuard(s));
// In UN-signed comparison, a negative index will look like a very
// large positive number, greater than array length.
// Thus length LLT index is false iff 0 <= index <= length
TrapIf.mutate(s, TRAP_IF, BoundsCheck.getClearGuardResult(s), array_length.copyD2U(), BoundsCheck.getClearIndex(s), ConditionOperand.LOWER_EQUAL(), TrapCodeOperand.ArrayBounds());
}
break;
case RESOLVE_MEMBER_opcode:
s = resolveMember(s, ir);
break;
default:
break;
}
}
// Eliminate possible redundant trap block from array store checks
if (didArrayStoreCheck) {
branchOpts.perform(ir, true);
}
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method generateValueProducingTypeCheck.
/**
* Generate a value-producing dynamic type check.
* This routine assumes that the CFG and code order are
* already correctly established.
* This routine must either remove s or mutuate it.
*
* @param s The Instruction that is to be replaced by
* a value producing type check
* @param ir The IR containing the instruction to be expanded.
* @param RHSobj The RegisterOperand containing the rhs object.
* @param LHStype The RVMType to be tested against.
* @param RHStib The Operand containing the TIB of the rhs.
* @param result The RegisterOperand that the result of dynamic
* type check is to be stored in.
* @return the opt instruction immediately before the
* instruction to continue expansion.
*/
private static Instruction generateValueProducingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, RegisterOperand result) {
// Is LHStype a class?
if (LHStype.isClassType()) {
RVMClass LHSclass = (RVMClass) LHStype.peekType();
if (LHSclass != null && LHSclass.isResolved()) {
// resolved class or interface
if (LHSclass.isInterface()) {
// A resolved interface (case 4)
int interfaceIndex = LHSclass.getDoesImplementIndex();
int interfaceMask = LHSclass.getDoesImplementBitMask();
RegisterOperand doesImpl = InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
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));
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, result, bit, AC(Address.zero()), ConditionOperand.NOT_EQUAL(), new BranchProfileOperand()));
if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
RegisterOperand doesImplLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copy(), TG());
RegisterOperand boundscheck = ir.regpool.makeTempInt();
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, boundscheck, doesImplLength, AC(Address.fromIntSignExtend(interfaceIndex)), ConditionOperand.GREATER(), new BranchProfileOperand()));
s.insertBefore(Binary.create(INT_AND, result.copyD2D(), result.copyD2U(), boundscheck.copyD2U()));
}
Instruction continueAt = s.prevInstructionInCodeOrder();
s.remove();
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(s, ir, LHSclass);
BooleanCmp.mutate(s, BOOLEAN_CMP_ADDR, result, RHStib, classTIB, ConditionOperand.EQUAL(), new BranchProfileOperand());
return s.prevInstructionInCodeOrder();
} else {
// Do the full blown case 5 or 6 typecheck.
int LHSDepth = LHSclass.getTypeDepth();
int LHSId = LHSclass.getId();
RegisterOperand superclassIds = InsertUnary(s, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
RegisterOperand refCandidate = InsertLoadOffset(s, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, result, refCandidate, AC(Address.fromIntZeroExtend(LHSId)), ConditionOperand.EQUAL(), new BranchProfileOperand()));
if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
RegisterOperand superclassIdsLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
RegisterOperand boundscheck = ir.regpool.makeTempInt();
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, boundscheck, superclassIdsLength, AC(Address.fromIntSignExtend(LHSDepth)), ConditionOperand.GREATER(), new BranchProfileOperand()));
s.insertBefore(Binary.create(INT_AND, result.copyD2D(), result.copyD2U(), boundscheck.copyD2U()));
}
Instruction continueAt = s.prevInstructionInCodeOrder();
s.remove();
return continueAt;
}
}
} else {
// A non-resolved class or interface.
// We expect these to be extremely uncommon in opt code in AOS.
// Mutate s into a call to RuntimeEntrypoints.instanceOf
RVMMethod target = Entrypoints.instanceOfMethod;
Call.mutate2(s, CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
return callHelper(s, ir);
}
}
if (LHStype.isArrayType()) {
// Case 2 of DynamicTypeCheck: LHS is an array.
RVMArray LHSArray = (RVMArray) LHStype.peekType();
if (LHSArray != null) {
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.
Operand classTIB = getTIB(s, ir, LHSArray);
BooleanCmp.mutate(s, BOOLEAN_CMP_ADDR, result, RHStib, classTIB, ConditionOperand.EQUAL(), new BranchProfileOperand());
return s;
}
}
// and do the real work there.
return convertToBranchingTypeCheck(s, ir, RHSobj, LHStype, RHStib, result);
}
OptimizingCompilerException.UNREACHABLE();
return null;
}
Aggregations