use of org.jikesrvm.compilers.opt.ir.operand.MethodOperand in project JikesRVM by JikesRVM.
the class FinalMIRExpansion method expand.
/**
* @param ir the IR to expand
* @return upperbound on number of machine code instructions
* that will be generated for this IR
*/
public static int expand(IR ir) {
int instructionCount = 0;
int conditionalBranchCount = 0;
int machinecodeLength = 0;
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
MachineCodeOffsets mcOffsets = ir.MIRInfo.mcOffsets;
for (Instruction p = ir.firstInstructionInCodeOrder(); p != null; p = p.nextInstructionInCodeOrder()) {
mcOffsets.setMachineCodeOffset(p, -1);
switch(p.getOpcode()) {
case MIR_LOWTABLESWITCH_opcode:
{
BasicBlock tableBlock = p.getBasicBlock();
BasicBlock nextBlock = tableBlock.splitNodeWithLinksAt(p.prevInstructionInCodeOrder(), ir);
mcOffsets.setMachineCodeOffset(nextBlock.firstInstruction(), -1);
Register regI = MIR_LowTableSwitch.getIndex(p).getRegister();
int NumTargets = MIR_LowTableSwitch.getNumberOfTargets(p);
tableBlock.appendInstruction(MIR_Call.create0(PPC_BL, null, null, nextBlock.makeJumpTarget()));
for (int i = 0; i < NumTargets; i++) {
tableBlock.appendInstruction(MIR_DataLabel.create(PPC_DATA_LABEL, MIR_LowTableSwitch.getClearTarget(p, i)));
}
Register temp = phys.getGPR(0);
p.insertBefore(MIR_Move.create(PPC_MFSPR, A(temp), A(phys.getLR())));
p.insertBefore(MIR_Binary.create(PPC_SLWI, I(regI), I(regI), IC(2)));
p.insertBefore(MIR_LoadUpdate.create(PPC_LIntUX, I(temp), I(regI), A(temp)));
p.insertBefore(MIR_Binary.create(PPC_ADD, A(regI), A(regI), I(temp)));
p.insertBefore(MIR_Move.create(PPC_MTSPR, A(phys.getCTR()), A(regI)));
MIR_Branch.mutate(p, PPC_BCTR);
instructionCount += NumTargets + 7;
}
break;
case PPC_BCOND2_opcode:
{
RegisterOperand cond = MIR_CondBranch2.getClearValue(p);
p.insertAfter(MIR_CondBranch.create(PPC_BCOND, cond.copyU2U(), MIR_CondBranch2.getClearCond2(p), MIR_CondBranch2.getClearTarget2(p), MIR_CondBranch2.getClearBranchProfile2(p)));
MIR_CondBranch.mutate(p, PPC_BCOND, cond, MIR_CondBranch2.getClearCond1(p), MIR_CondBranch2.getClearTarget1(p), MIR_CondBranch2.getClearBranchProfile1(p));
conditionalBranchCount++;
}
break;
case PPC_BLRL_opcode:
case PPC_BCTRL_opcode:
{
// See also ConvertToLowlevelIR.java
if (VM.BuildForIMTInterfaceInvocation) {
if (MIR_Call.hasMethod(p)) {
MethodOperand mo = MIR_Call.getMethod(p);
if (mo.isInterface()) {
InterfaceMethodSignature sig = InterfaceMethodSignature.findOrCreate(mo.getMemberRef());
int signatureId = sig.getId();
Instruction s;
if (fits(signatureId, 16)) {
s = MIR_Unary.create(PPC_LDI, I(phys.getGPR(LAST_SCRATCH_GPR)), IC(signatureId));
p.insertBefore(s);
instructionCount++;
} else {
s = MIR_Unary.create(PPC_LDIS, I(phys.getGPR(LAST_SCRATCH_GPR)), IC(PPCMaskUpper16(signatureId)));
p.insertBefore(s);
s = MIR_Binary.create(PPC_ADDI, I(phys.getGPR(LAST_SCRATCH_GPR)), I(phys.getGPR(LAST_SCRATCH_GPR)), IC(PPCMaskLower16(signatureId)));
p.insertBefore(s);
instructionCount += 2;
}
}
}
}
instructionCount++;
}
break;
case LABEL_opcode:
case BBEND_opcode:
case UNINT_BEGIN_opcode:
case UNINT_END_opcode:
// These generate no code, so don't count them.
break;
case RESOLVE_opcode:
{
Register zero = phys.getGPR(0);
Register JTOC = phys.getJTOC();
Register CTR = phys.getCTR();
if (VM.VerifyAssertions)
VM._assert(p.getBytecodeIndex() >= 0 && p.position() != null);
Offset offset = Entrypoints.optResolveMethod.getOffset();
if (fits(offset, 16)) {
p.insertBefore(MIR_Load.create(PPC_LAddr, A(zero), A(JTOC), IC(PPCMaskLower16(offset))));
} else {
// not implemented
if (VM.VerifyAssertions)
VM._assert(fits(offset, 32));
p.insertBefore(MIR_Binary.create(PPC_ADDIS, A(zero), A(JTOC), IC(PPCMaskUpper16(offset))));
p.insertBefore(MIR_Load.create(PPC_LAddr, A(zero), A(zero), IC(PPCMaskLower16(offset))));
instructionCount += 1;
}
p.insertBefore(MIR_Move.create(PPC_MTSPR, A(CTR), A(zero)));
instructionCount += 3;
// Because the GC Map code holds a reference to the original
// instruction, it is important that we mutate the last instruction
// because this will be the GC point.
MIR_Call.mutate0(p, PPC_BCTRL, null, null);
break;
}
case YIELDPOINT_PROLOGUE_opcode:
{
Register TSR = phys.getTSR();
BasicBlock yieldpoint = findOrCreateYieldpointBlock(ir, RVMThread.PROLOGUE);
// Because the GC Map code holds a reference to the original
// instruction, it is important that we mutate the last instruction
// because this will be the GC point.
MIR_CondCall.mutate0(p, PPC_BCL, null, null, I(TSR), PowerPCConditionOperand.NOT_EQUAL(), yieldpoint.makeJumpTarget());
p.getBasicBlock().insertOut(yieldpoint);
conditionalBranchCount++;
}
break;
case YIELDPOINT_BACKEDGE_opcode:
{
BasicBlock yieldpoint = findOrCreateYieldpointBlock(ir, RVMThread.BACKEDGE);
Register zero = phys.getGPR(0);
Register TSR = phys.getTSR();
Register TR = phys.getTR();
Offset offset = Entrypoints.takeYieldpointField.getOffset();
if (VM.VerifyAssertions)
VM._assert(fits(offset, 16));
p.insertBefore(MIR_Load.create(PPC_LInt, I(zero), A(TR), IC(PPCMaskLower16(offset))));
p.insertBefore(MIR_Binary.create(PPC_CMPI, I(TSR), I(zero), IC(0)));
instructionCount += 2;
// Because the GC Map code holds a reference to the original
// instruction, it is important that we mutate the last instruction
// because this will be the GC point.
MIR_CondCall.mutate0(p, PPC_BCL, null, null, I(TSR), PowerPCConditionOperand.GREATER(), yieldpoint.makeJumpTarget());
p.getBasicBlock().insertOut(yieldpoint);
conditionalBranchCount++;
}
break;
case YIELDPOINT_EPILOGUE_opcode:
{
BasicBlock yieldpoint = findOrCreateYieldpointBlock(ir, RVMThread.EPILOGUE);
Register zero = phys.getGPR(0);
Register TSR = phys.getTSR();
Register TR = phys.getTR();
Offset offset = Entrypoints.takeYieldpointField.getOffset();
if (VM.VerifyAssertions)
VM._assert(fits(offset, 16));
p.insertBefore(MIR_Load.create(PPC_LInt, I(zero), A(TR), IC(PPCMaskLower16(offset))));
p.insertBefore(MIR_Binary.create(PPC_CMPI, I(TSR), I(zero), IC(0)));
instructionCount += 2;
// Because the GC Map code holds a reference to the original
// instruction, it is important that we mutate the last instruction
// because this will be the GC point.
MIR_CondCall.mutate0(p, PPC_BCL, null, null, I(TSR), PowerPCConditionOperand.NOT_EQUAL(), yieldpoint.makeJumpTarget());
p.getBasicBlock().insertOut(yieldpoint);
conditionalBranchCount++;
}
break;
case YIELDPOINT_OSR_opcode:
{
// unconditionally branch to yield point.
BasicBlock yieldpoint = findOrCreateYieldpointBlock(ir, RVMThread.OSROPT);
// Because the GC Map code holds a reference to the original
// instruction, it is important that we mutate the last instruction
// because this will be the GC point.
MIR_Call.mutate0(p, PPC_BL, null, null, yieldpoint.makeJumpTarget());
p.getBasicBlock().insertOut(yieldpoint);
}
instructionCount++;
break;
default:
if (p.operator().isConditionalBranch()) {
conditionalBranchCount++;
} else {
instructionCount++;
}
break;
}
}
// reasonably sized methods
if ((instructionCount + conditionalBranchCount) > AssemblerOpt.MAX_COND_DISPL) {
machinecodeLength = instructionCount + 2 * conditionalBranchCount;
} else {
machinecodeLength = instructionCount + conditionalBranchCount;
}
if ((machinecodeLength & ~AssemblerOpt.MAX_24_BITS) != 0) {
throw new OptimizingCompilerException("CodeGen", "method too large to compile:", AssemblerOpt.MAX_24_BITS);
}
return machinecodeLength;
}
use of org.jikesrvm.compilers.opt.ir.operand.MethodOperand in project JikesRVM by JikesRVM.
the class BasicBlock method hasAthrowInst.
/**
* Does this basic block contain an explicit athrow instruction?
*
* @return <code>true</code> if the block ends in an explicit Athrow
* instruction or <code>false</code> if it does not
*/
public final boolean hasAthrowInst() {
if (isEmpty())
return false;
Instruction s = lastRealInstruction();
if (VM.BuildForIA32 && s.operator().isAdviseESP()) {
s = s.getPrev();
}
if (Athrow.conforms(s)) {
return true;
}
MethodOperand mop = null;
if (VM.BuildForIA32 && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.conforms(s)) {
mop = org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.getMethod(s);
} else if (VM.BuildForPowerPC && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.conforms(s)) {
mop = org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.getMethod(s);
} else if (Call.conforms(s)) {
mop = Call.getMethod(s);
}
return mop != null && mop.getTarget() == Entrypoints.athrowMethod;
}
use of org.jikesrvm.compilers.opt.ir.operand.MethodOperand in project JikesRVM by JikesRVM.
the class CFGVisualization method formatCall.
protected String formatCall(Instruction inst) {
StringBuilder buf = new StringBuilder();
MethodOperand mop = Call.getMethod(inst);
if (mop != null && mop.hasTarget()) {
RVMMethod method = mop.getTarget();
buf.append(method.getDeclaringClass());
buf.append(":");
buf.append(method.getName());
buf.append(":");
buf.append(method.getDescriptor());
buf.append(":");
int params = Call.getNumberOfParams(inst);
for (int i = 1; i <= params; i++) {
buf.append(Call.getParam(inst, i - 1));
if (i < params) {
buf.append(", ");
} else {
buf.append("; ");
}
}
}
return buf.toString();
}
use of org.jikesrvm.compilers.opt.ir.operand.MethodOperand 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.ir.operand.MethodOperand 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);
}
}
Aggregations