use of org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand 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.NullConstantOperand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method arrayStoreCheck.
/**
* Expand an object array store check into the LIR sequence that
* implements it.
*
* @param s an OBJARRAY_STORE_CHECK instruction to expand
* @param ir the enclosing IR
* @param couldBeNull is it possible that the element being stored is null?
* @return the last Instruction in the generated LIR sequence.
*/
static Instruction arrayStoreCheck(Instruction s, IR ir, boolean couldBeNull) {
RegisterOperand guardResult = StoreCheck.getGuardResult(s);
Operand arrayRef = StoreCheck.getClearRef(s);
Operand elemRef = StoreCheck.getClearVal(s);
Operand guard = StoreCheck.getClearGuard(s);
if (elemRef instanceof NullConstantOperand) {
Instruction continueAt = s.prevInstructionInCodeOrder();
s.remove();
return continueAt;
}
BasicBlock myBlock = s.getBasicBlock();
BasicBlock contBlock = myBlock.splitNodeAt(s, ir);
BasicBlock trapBlock = myBlock.createSubBlock(s.getBytecodeIndex(), ir, .0001f);
BasicBlock curBlock = myBlock;
Move.mutate(s, GUARD_MOVE, guardResult, new TrueGuardOperand());
// Set up a block with a trap instruction that we can jump to if the
// store check fails
Instruction trap = Trap.create(TRAP, null, TrapCodeOperand.StoreCheck());
trap.copyPosition(s);
trapBlock.appendInstruction(trap);
ir.cfg.addLastInCodeOrder(trapBlock);
Operand rhsGuard = guard;
if (couldBeNull) {
// if rhs is null, then the checkcast succeeds
rhsGuard = ir.regpool.makeTempValidation();
contBlock.prependInstruction(Binary.create(GUARD_COMBINE, guardResult.copyRO(), guardResult.copyRO(), rhsGuard.copy()));
curBlock.appendInstruction(IfCmp.create(REF_IFCMP, rhsGuard.asRegister(), elemRef, new NullConstantOperand(), ConditionOperand.EQUAL(), contBlock.makeJumpTarget(), new BranchProfileOperand()));
curBlock.insertOut(contBlock);
curBlock = advanceBlock(s.getBytecodeIndex(), curBlock, ir);
}
// Find out what we think the compile time type of the lhs is.
// Based on this, we can do one of several things:
// (1) If the compile time element type is a final proper class, then a
// TIB comparision of the runtime elemRef type and the
// compile time element type is definitive.
// (2) If the compile time type is known to be the declared type,
// then inject a short-circuit test to see if the
// runtime lhs type is the same as the compile-time lhs type.
// (3) If the compile time element type is a proper class other than
// java.lang.Object, then a subclass test of the runtime LHS elem type
// and the runtime elemRef type is definitive. Note: we must exclude
// java.lang.Object because if the compile time element type is
// java.lang.Object, then the runtime-element type might actually be
// an interface (ie not a proper class), and we won't be testing the right thing!
// If we think the compile time type is JavaLangObjectType then
// we lost type information due to unloaded classes causing
// imprecise meets. This should only happen once in a blue moon,
// so don't bother trying anything clever when it does.
RVMType compType = arrayRef.getType().peekType();
if (compType != null && !compType.isJavaLangObjectType()) {
// optionally (1) from above
if (compType.getDimensionality() == 1) {
RVMClass etc = (RVMClass) compType.asArray().getElementType();
if (etc.isResolved() && etc.isFinal()) {
if (VM.VerifyAssertions)
VM._assert(!etc.isInterface());
Operand rhsTIB = getTIB(curBlock.lastInstruction(), ir, elemRef.copy(), rhsGuard.copy());
Operand etTIB = getTIB(curBlock.lastInstruction(), ir, etc);
curBlock.appendInstruction(IfCmp.create(REF_IFCMP, guardResult.copyRO(), rhsTIB, etTIB, ConditionOperand.NOT_EQUAL(), trapBlock.makeJumpTarget(), BranchProfileOperand.never()));
curBlock.insertOut(trapBlock);
curBlock.insertOut(contBlock);
ir.cfg.linkInCodeOrder(curBlock, contBlock);
return curBlock.lastInstruction();
}
}
// optionally (2) from above
Operand lhsTIB = getTIB(curBlock.lastInstruction(), ir, arrayRef, guard);
if (((arrayRef instanceof RegisterOperand) && ((RegisterOperand) arrayRef).isDeclaredType()) || compType == RVMType.JavaLangObjectArrayType) {
Operand declTIB = getTIB(curBlock.lastInstruction(), ir, compType);
curBlock.appendInstruction(IfCmp.create(REF_IFCMP, guardResult.copyRO(), declTIB, lhsTIB, ConditionOperand.EQUAL(), contBlock.makeJumpTarget(), new BranchProfileOperand()));
curBlock.insertOut(contBlock);
curBlock = advanceBlock(s.getBytecodeIndex(), curBlock, ir);
}
// On our way to doing (3) from above attempt another short-circuit.
// If lhsElemTIB == rhsTIB, then we are done.
Operand rhsTIB = getTIB(curBlock.lastInstruction(), ir, elemRef.copy(), rhsGuard.copy());
RegisterOperand lhsElemTIB = InsertUnary(curBlock.lastInstruction(), ir, GET_ARRAY_ELEMENT_TIB_FROM_TIB, TypeReference.TIB, lhsTIB.copy());
curBlock.appendInstruction(IfCmp.create(REF_IFCMP, guardResult.copyRO(), rhsTIB, lhsElemTIB, ConditionOperand.EQUAL(), contBlock.makeJumpTarget(), new BranchProfileOperand()));
curBlock.insertOut(contBlock);
curBlock = advanceBlock(s.getBytecodeIndex(), curBlock, ir);
// Optionally (3) from above
if (compType.getDimensionality() == 1) {
RVMClass etc = (RVMClass) compType.asArray().getElementType();
if (etc.isResolved() && !etc.isInterface() && !etc.isJavaLangObjectType()) {
RegisterOperand lhsElemType = InsertUnary(curBlock.lastInstruction(), ir, GET_TYPE_FROM_TIB, TypeReference.Type, lhsElemTIB.copyU2U());
RegisterOperand rhsSuperclassIds = InsertUnary(curBlock.lastInstruction(), ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, rhsTIB.copy());
RegisterOperand lhsElemDepth = getField(curBlock.lastInstruction(), ir, lhsElemType, Entrypoints.depthField, TG());
RegisterOperand rhsSuperclassIdsLength = InsertGuardedUnary(curBlock.lastInstruction(), ir, ARRAYLENGTH, TypeReference.Int, rhsSuperclassIds.copyD2U(), TG());
curBlock.appendInstruction(IfCmp.create(INT_IFCMP, guardResult.copyRO(), lhsElemDepth, rhsSuperclassIdsLength, ConditionOperand.GREATER_EQUAL(), trapBlock.makeJumpTarget(), BranchProfileOperand.never()));
curBlock.insertOut(trapBlock);
curBlock = advanceBlock(s.getBytecodeIndex(), curBlock, ir);
RegisterOperand lhsElemId = getField(curBlock.lastInstruction(), ir, lhsElemType.copyD2U(), Entrypoints.idField, TG());
RegisterOperand refCandidate = ir.regpool.makeTemp(TypeReference.Short);
LocationOperand loc = new LocationOperand(TypeReference.Short);
if (LOWER_ARRAY_ACCESS) {
RegisterOperand lhsDepthOffset = insertBinary(curBlock.lastInstruction(), ir, INT_SHL, TypeReference.Int, lhsElemDepth.copyD2U(), IC(1));
lhsDepthOffset = InsertUnary(curBlock.lastInstruction(), ir, INT_2ADDRZerExt, TypeReference.Offset, lhsDepthOffset.copy());
curBlock.appendInstruction(Load.create(USHORT_LOAD, refCandidate, rhsSuperclassIds, lhsDepthOffset, loc, TG()));
} else {
curBlock.appendInstruction(ALoad.create(USHORT_ALOAD, refCandidate, rhsSuperclassIds, lhsElemDepth.copyRO(), loc, TG()));
}
curBlock.appendInstruction(IfCmp.create(INT_IFCMP, guardResult.copyRO(), refCandidate.copyD2U(), lhsElemId, ConditionOperand.NOT_EQUAL(), trapBlock.makeJumpTarget(), BranchProfileOperand.never()));
curBlock.insertOut(trapBlock);
curBlock.insertOut(contBlock);
ir.cfg.linkInCodeOrder(curBlock, contBlock);
return curBlock.lastInstruction();
}
}
}
// Call RuntimeEntrypoints.checkstore.
RVMMethod target = Entrypoints.checkstoreMethod;
Instruction call = Call.create2(CALL, null, AC(target.getOffset()), MethodOperand.STATIC(target), rhsGuard.copy(), arrayRef.copy(), elemRef.copy());
call.copyPosition(s);
curBlock.appendInstruction(call);
curBlock.insertOut(contBlock);
ir.cfg.linkInCodeOrder(curBlock, contBlock);
return callHelper(call, ir);
}
use of org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method checkcast.
/**
* Expand a checkcast instruction into the LIR sequence that implements the
* dynamic type check, raising a ClassCastException when the type check
* fails. Ref may contain a null ptr at runtime.
*
* @param s a CHECKCAST or CHECKCAST_UNRESOLVED instruction to expand
* @param ir the enclosing IR
* @return the last Instruction in the generated LIR sequence.
*/
static Instruction checkcast(Instruction s, IR ir) {
Operand ref = TypeCheck.getClearRef(s);
TypeReference LHStype = TypeCheck.getType(s).getTypeRef();
RegisterOperand guard = ir.regpool.makeTempValidation();
Instruction nullCond = IfCmp.create(REF_IFCMP, guard, ref.copy(), new NullConstantOperand(), ConditionOperand.EQUAL(), null, // KLUDGE...we haven't created the block yet!
new BranchProfileOperand());
s.insertBefore(nullCond);
BasicBlock myBlock = s.getBasicBlock();
BasicBlock failBlock = myBlock.createSubBlock(s.getBytecodeIndex(), ir, .0001f);
BasicBlock instanceOfBlock = myBlock.splitNodeAt(nullCond, ir);
BasicBlock succBlock = instanceOfBlock.splitNodeAt(s, ir);
succBlock.firstInstruction().insertAfter(Move.create(REF_MOVE, TypeCheck.getClearResult(s), ref.copy()));
// fixup KLUDGE
IfCmp.setTarget(nullCond, succBlock.makeJumpTarget());
myBlock.insertOut(instanceOfBlock);
myBlock.insertOut(succBlock);
instanceOfBlock.insertOut(failBlock);
instanceOfBlock.insertOut(succBlock);
ir.cfg.linkInCodeOrder(myBlock, instanceOfBlock);
ir.cfg.linkInCodeOrder(instanceOfBlock, succBlock);
ir.cfg.addLastInCodeOrder(failBlock);
Instruction raiseError = Trap.create(TRAP, null, TrapCodeOperand.CheckCast());
raiseError.copyPosition(s);
failBlock.appendInstruction(raiseError);
Operand RHStib = getTIB(s, ir, ref, guard.copyD2U());
return generateBranchingTypeCheck(s, ir, ref.copy(), LHStype, RHStib, succBlock, failBlock, guard.copyRO(), BranchProfileOperand.never());
}
Aggregations