use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method genParameterRegisterLoad.
/**
* Copy parameters from operand stack into registers.
* Assumption: parameters are layed out on the stack in order
* with SP pointing to the last parameter.
* Also, this method is called before the generation of an explicit method call.
* @param method is the method to be called.
* @param hasThisParam is the method virtual?
*/
protected void genParameterRegisterLoad(MethodReference method, boolean hasThisParam) {
int max = NUM_PARAMETER_GPRS + NUM_PARAMETER_FPRS;
// quit looking when all registers are full
if (max == 0)
return;
// number of general purpose registers filled
int gpr = 0;
// number of floating point registers filled
int fpr = 0;
// next GPR to get a parameter
GPR T = T0;
int params = method.getParameterWords() + (hasThisParam ? 1 : 0);
// stack offset of first parameter word
Offset offset = Offset.fromIntSignExtend((params - 1) << LG_WORDSIZE);
if (hasThisParam) {
if (gpr < NUM_PARAMETER_GPRS) {
stackMoveHelper(T, offset);
// at most 2 parameters can be passed in general purpose registers
T = T1;
gpr++;
max--;
}
offset = offset.minus(WORDSIZE);
}
for (TypeReference type : method.getParameterTypes()) {
// quit looking when all registers are full
if (max == 0)
return;
TypeReference t = type;
if (t.isLongType()) {
if (gpr < NUM_PARAMETER_GPRS) {
if (WORDSIZE == 4) {
// lo register := hi mem (== hi order word)
stackMoveHelper(T, offset);
// at most 2 parameters can be passed in general purpose registers
T = T1;
gpr++;
max--;
if (gpr < NUM_PARAMETER_GPRS) {
// hi register := lo mem (== lo order word)
stackMoveHelper(T, offset.minus(WORDSIZE));
gpr++;
max--;
}
} else {
// initially offset will point at junk word, move down and over
stackMoveHelper(T, offset.minus(WORDSIZE));
// at most 2 parameters can be passed in general purpose registers
T = T1;
gpr++;
max--;
}
}
offset = offset.minus(2 * WORDSIZE);
} else if (t.isFloatType()) {
if (fpr < NUM_PARAMETER_FPRS) {
if (SSE2_FULL) {
asm.emitMOVSS_Reg_RegDisp(XMM.lookup(fpr), SP, offset);
} else {
asm.emitFLD_Reg_RegDisp(FP0, SP, offset);
}
fpr++;
max--;
}
offset = offset.minus(WORDSIZE);
} else if (t.isDoubleType()) {
if (fpr < NUM_PARAMETER_FPRS) {
if (SSE2_FULL) {
asm.emitMOVSD_Reg_RegDisp(XMM.lookup(fpr), SP, offset.minus(WORDSIZE));
} else {
asm.emitFLD_Reg_RegDisp_Quad(FP0, SP, offset.minus(WORDSIZE));
}
fpr++;
max--;
}
offset = offset.minus(2 * WORDSIZE);
} else if (t.isReferenceType() || t.isWordLikeType()) {
if (gpr < NUM_PARAMETER_GPRS) {
stackMoveHelper(T, offset);
// at most 2 parameters can be passed in general purpose registers
T = T1;
gpr++;
max--;
}
offset = offset.minus(WORDSIZE);
} else {
// t is object, int, short, char, byte, or boolean
if (gpr < NUM_PARAMETER_GPRS) {
if (offset.isZero()) {
asm.emitMOV_Reg_RegInd(T, SP);
} else {
asm.emitMOV_Reg_RegDisp(T, SP, offset);
}
// at most 2 parameters can be passed in general purpose registers
T = T1;
gpr++;
max--;
}
offset = offset.minus(WORDSIZE);
}
}
if (VM.VerifyAssertions)
VM._assert(offset.EQ(Offset.fromIntSignExtend(-WORDSIZE)));
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emit_resolved_getfield.
@Override
protected void emit_resolved_getfield(FieldReference fieldRef) {
TypeReference fieldType = fieldRef.getFieldContentsType();
RVMField field = fieldRef.peekResolvedField();
Offset fieldOffset = field.getOffset();
if (field.isReferenceType()) {
// 32/64bit reference load
if (NEEDS_OBJECT_GETFIELD_BARRIER && !field.isUntraced()) {
Barriers.compileGetfieldBarrierImm(asm, fieldOffset, fieldRef.getId());
} else {
// T0 is object reference
asm.emitPOP_Reg(T0);
// place field value on stack
asm.emitPUSH_RegDisp(T0, fieldOffset);
}
} else if (fieldType.isBooleanType()) {
// 8bit unsigned load
// S0 is object reference
asm.emitPOP_Reg(S0);
// T0 is field value
asm.emitMOVZX_Reg_RegDisp_Byte(T0, S0, fieldOffset);
// place value on stack
asm.emitPUSH_Reg(T0);
} else if (fieldType.isByteType()) {
// 8bit signed load
// S0 is object reference
asm.emitPOP_Reg(S0);
// T0 is field value
asm.emitMOVSX_Reg_RegDisp_Byte(T0, S0, fieldOffset);
// place value on stack
asm.emitPUSH_Reg(T0);
} else if (fieldType.isShortType()) {
// 16bit signed load
// S0 is object reference
asm.emitPOP_Reg(S0);
// T0 is field value
asm.emitMOVSX_Reg_RegDisp_Word(T0, S0, fieldOffset);
// place value on stack
asm.emitPUSH_Reg(T0);
} else if (fieldType.isCharType()) {
// 16bit unsigned load
// S0 is object reference
asm.emitPOP_Reg(S0);
// T0 is field value
asm.emitMOVZX_Reg_RegDisp_Word(T0, S0, fieldOffset);
// place value on stack
asm.emitPUSH_Reg(T0);
} else if (fieldType.isIntType() || fieldType.isFloatType() || (VM.BuildFor32Addr && fieldType.isWordLikeType())) {
// 32bit load
// S0 is object reference
asm.emitPOP_Reg(S0);
if (VM.BuildFor32Addr) {
// place value on stack
asm.emitPUSH_RegDisp(S0, fieldOffset);
} else {
// T0 is field value
asm.emitMOV_Reg_RegDisp(T0, S0, fieldOffset);
// place value on stack
asm.emitPUSH_Reg(T0);
}
} else {
// 64bit load
if (VM.VerifyAssertions) {
VM._assert(fieldType.isLongType() || fieldType.isDoubleType() || (VM.BuildFor64Addr && fieldType.isWordLikeType()));
}
// T0 is object reference
asm.emitPOP_Reg(T0);
if (VM.BuildFor32Addr && field.isVolatile()) {
// as a slightly optimized Intel memory copy using the FPU
if (SSE2_BASE) {
// XMM0 is field value
asm.emitMOVQ_Reg_RegDisp(XMM0, T0, fieldOffset);
// adjust stack down to hold 64bit value
adjustStack(-2 * WORDSIZE, true);
// replace reference with value on stack
asm.emitMOVQ_RegInd_Reg(SP, XMM0);
} else {
// FP0 is field value
asm.emitFLD_Reg_RegDisp_Quad(FP0, T0, fieldOffset);
// adjust stack down to hold 64bit value
adjustStack(-2 * WORDSIZE, true);
// replace reference with value on stack
asm.emitFSTP_RegInd_Reg_Quad(SP, FP0);
}
} else if (VM.BuildFor32Addr && !field.isVolatile()) {
// place high half on stack
asm.emitPUSH_RegDisp(T0, fieldOffset.plus(ONE_SLOT));
// place low half on stack
asm.emitPUSH_RegDisp(T0, fieldOffset);
} else {
if (!fieldType.isWordLikeType()) {
// add empty slot
adjustStack(-WORDSIZE, true);
}
// place value on stack
asm.emitPUSH_RegDisp(T0, fieldOffset);
}
}
}
use of org.jikesrvm.classloader.TypeReference in project JikesRVM by JikesRVM.
the class InlineTools method inlinedSizeEstimate.
/**
* Given the currently available information at the call site,
* what's our best guess on the inlined size of the callee?
* @param callee the method to be inlined
* @param state the compilation state decribing the call site where it
* is to be inlined
* @return an inlined size estimate (number of machine code instructions)
*/
public static int inlinedSizeEstimate(NormalMethod callee, CompilationState state) {
int sizeEstimate = callee.inlinedSizeEstimate();
// Adjust size estimate downward to account for optimizations
// that are typically enabled by constant parameters.
Instruction callInstr = state.getCallInstruction();
int numArgs = Call.getNumberOfParams(callInstr);
// no reduction.
double reductionFactor = 1.0;
OptOptions opts = state.getOptions();
for (int i = 0; i < numArgs; i++) {
Operand op = Call.getParam(callInstr, i);
if (op instanceof RegisterOperand) {
RegisterOperand rop = (RegisterOperand) op;
TypeReference type = rop.getType();
if (type.isReferenceType()) {
if (type.isArrayType()) {
// Reductions only come from optimization of dynamic type checks; all virtual methods on arrays are defined on Object.
if (rop.isPreciseType()) {
reductionFactor -= opts.INLINE_PRECISE_REG_ARRAY_ARG_BONUS;
} else if (rop.isDeclaredType() && callee.hasArrayWrite() && type.getArrayElementType().isReferenceType()) {
// potential to optimize checkstore portion of aastore bytecode on parameter
reductionFactor -= opts.INLINE_DECLARED_AASTORED_ARRAY_ARG_BONUS;
}
} else {
// Reductions come from optimization of dynamic type checks and improved inlining of virtual/interface calls
if (rop.isPreciseType()) {
reductionFactor -= opts.INLINE_PRECISE_REG_CLASS_ARG_BONUS;
} else if (rop.isExtant()) {
reductionFactor -= opts.INLINE_EXTANT_REG_CLASS_ARG_BONUS;
}
}
}
} else if (op.isIntConstant()) {
reductionFactor -= opts.INLINE_INT_CONST_ARG_BONUS;
} else if (op.isNullConstant()) {
reductionFactor -= opts.INLINE_NULL_CONST_ARG_BONUS;
} else if (op.isObjectConstant()) {
reductionFactor -= opts.INLINE_OBJECT_CONST_ARG_BONUS;
}
}
reductionFactor = Math.max(reductionFactor, 1.0 - opts.INLINE_MAX_ARG_BONUS);
if (opts.INLINE_CALL_DEPTH_COST != 0.00) {
double depthCost = Math.pow(1.0 + opts.INLINE_CALL_DEPTH_COST, state.getInlineDepth() + 1);
return (int) (sizeEstimate * reductionFactor * depthCost);
} else {
return (int) (sizeEstimate * reductionFactor);
}
}
use of org.jikesrvm.classloader.TypeReference 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.classloader.TypeReference in project JikesRVM by JikesRVM.
the class ObjectReplacer method scalarReplace.
/**
* Replace a given use of a object with its scalar equivalent
*
* @param use the use to replace
* @param scalars an array of scalar register operands to replace
* the object's fields with
* @param fields the object's fields
* @param visited the registers that were already seen
*/
private void scalarReplace(RegisterOperand use, RegisterOperand[] scalars, ArrayList<RVMField> fields, Set<Register> visited) {
Instruction inst = use.instruction;
try {
switch(inst.getOpcode()) {
case PUTFIELD_opcode:
{
FieldReference fr = PutField.getLocation(inst).getFieldRef();
if (VM.VerifyAssertions)
VM._assert(fr.isResolved());
RVMField f = fr.peekResolvedField();
int index = fields.indexOf(f);
TypeReference type = scalars[index].getType();
Operator moveOp = IRTools.getMoveOp(type);
Instruction i = Move.create(moveOp, scalars[index].copyRO(), PutField.getClearValue(inst));
inst.insertBefore(i);
DefUse.removeInstructionAndUpdateDU(inst);
DefUse.updateDUForNewInstruction(i);
}
break;
case GETFIELD_opcode:
{
FieldReference fr = GetField.getLocation(inst).getFieldRef();
if (VM.VerifyAssertions)
VM._assert(fr.isResolved());
RVMField f = fr.peekResolvedField();
int index = fields.indexOf(f);
TypeReference type = scalars[index].getType();
Operator moveOp = IRTools.getMoveOp(type);
Instruction i = Move.create(moveOp, GetField.getClearResult(inst), scalars[index].copyRO());
inst.insertBefore(i);
DefUse.removeInstructionAndUpdateDU(inst);
DefUse.updateDUForNewInstruction(i);
}
break;
case MONITORENTER_opcode:
inst.insertBefore(Empty.create(READ_CEILING));
DefUse.removeInstructionAndUpdateDU(inst);
break;
case MONITOREXIT_opcode:
inst.insertBefore(Empty.create(WRITE_FLOOR));
DefUse.removeInstructionAndUpdateDU(inst);
break;
case CALL_opcode:
case NULL_CHECK_opcode:
// (SJF) TODO: Why wasn't this caught by BC2IR for
// java.lang.Double.<init> (Ljava/lang/String;)V ?
DefUse.removeInstructionAndUpdateDU(inst);
break;
case CHECKCAST_opcode:
case CHECKCAST_NOTNULL_opcode:
case CHECKCAST_UNRESOLVED_opcode:
{
// We cannot handle removing the checkcast if the result of the
// checkcast test is unknown
TypeReference lhsType = TypeCheck.getType(inst).getTypeRef();
if (ClassLoaderProxy.includesType(lhsType, klass.getTypeRef()) == YES) {
if (visited == null) {
visited = new HashSet<Register>();
}
Register copy = TypeCheck.getResult(inst).getRegister();
if (!visited.contains(copy)) {
visited.add(copy);
transform2(copy, inst, scalars, fields, visited);
// NB will remove inst
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
} else {
Instruction i2 = Trap.create(TRAP, null, TrapCodeOperand.CheckCast());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
}
break;
case INSTANCEOF_opcode:
case INSTANCEOF_NOTNULL_opcode:
case INSTANCEOF_UNRESOLVED_opcode:
{
// We cannot handle removing the instanceof if the result of the
// instanceof test is unknown
TypeReference lhsType = InstanceOf.getType(inst).getTypeRef();
Instruction i2;
if (ClassLoaderProxy.includesType(lhsType, klass.getTypeRef()) == YES) {
i2 = Move.create(INT_MOVE, InstanceOf.getClearResult(inst), IC(1));
} else {
i2 = Move.create(INT_MOVE, InstanceOf.getClearResult(inst), IC(0));
}
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case GET_OBJ_TIB_opcode:
{
Instruction i2 = Move.create(REF_MOVE, GuardedUnary.getClearResult(inst), new TIBConstantOperand(klass));
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case REF_MOVE_opcode:
{
if (visited == null) {
visited = new HashSet<Register>();
}
Register copy = Move.getResult(use.instruction).getRegister();
if (!visited.contains(copy)) {
visited.add(copy);
transform2(copy, inst, scalars, fields, visited);
// NB will remove inst
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
}
break;
default:
throw new OptimizingCompilerException("ObjectReplacer: unexpected use " + inst);
}
} catch (Exception e) {
OptimizingCompilerException oe = new OptimizingCompilerException("Error handling use (" + use + ") of: " + inst);
oe.initCause(e);
throw oe;
}
}
Aggregations