use of org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand in project JikesRVM by JikesRVM.
the class BC2IR method do_NullCheck.
/**
* Generates a null-check instruction for the given operand.
* @param ref the reference to check for null
* @return {@code true} if an unconditional throw is generated, {@code false} otherwise
*/
public boolean do_NullCheck(Operand ref) {
if (gc.noNullChecks()) {
setCurrentGuard(new TrueGuardOperand());
return false;
}
if (ref.isDefinitelyNull()) {
if (DBG_CF)
db("generating definite exception: null_check of definitely null");
endOfBasicBlock = true;
rectifyStateWithNullPtrExceptionHandler();
appendInstruction(Trap.create(TRAP, gc.getTemps().makeTempValidation(), TrapCodeOperand.NullPtr()));
return true;
}
if (ref instanceof RegisterOperand) {
RegisterOperand rop = (RegisterOperand) ref;
if (hasGuard(rop)) {
Operand guard = copyGuardFromOperand(rop);
setCurrentGuard(guard);
if (DBG_ELIMNULL) {
db("null check of " + ref + " is not necessary; guarded by " + guard);
}
return false;
}
// rop is possibly null, insert the null check,
// rectify with exception handler, update the guard state.
RegisterOperand guard = gc.makeNullCheckGuard(rop.getRegister());
appendInstruction(NullCheck.create(NULL_CHECK, guard, ref.copy()));
rectifyStateWithNullPtrExceptionHandler();
setCurrentGuard(guard);
setGuardForRegOp(rop, guard);
if (DBG_ELIMNULL)
db(rop + " is guarded by " + guard);
// RegisterOperands representing the same Register.
if (rop.getRegister().isLocal()) {
// We want to learn that downstream of this nullcheck, other
// uses of this local variable will also be non-null.
// BUT, we MUST NOT just directly set the guard of the appropriate
// element of our locals array (operands in the local array
// may appear in previously generated instructions).
// Therefore we call getLocal (which internally makes a copy),
// mark the copy with the new guard
// and finally store the copy back into the local state.
int number = gc.getLocalNumberFor(rop.getRegister(), rop.getType());
if (number != -1) {
Operand loc = getLocal(number);
if (loc instanceof RegisterOperand) {
if (DBG_ELIMNULL) {
db("setting local #" + number + "(" + loc + ") to non-null");
}
setGuardForRegOp((RegisterOperand) loc, guard);
}
setLocal(number, loc);
}
}
// the current basic block.
for (int i = stack.getSize() - 1; i >= 0; --i) {
Operand sop = stack.getFromTop(i);
if (sop instanceof RegisterOperand) {
RegisterOperand sreg = (RegisterOperand) sop;
if (sreg.getRegister() == rop.getRegister()) {
if (hasGuard(sreg)) {
if (DBG_ELIMNULL) {
db(sreg + " on stack already with guard " + copyGuardFromOperand(sreg));
}
} else {
if (DBG_ELIMNULL) {
db("setting " + sreg + " on stack to be guarded by " + guard);
}
setGuardForRegOp(sreg, guard);
}
}
}
}
return false;
} else {
// cannot be null becuase it's not in a register.
if (DBG_ELIMNULL) {
db("skipped generation of a null-check instruction for non-register " + ref);
}
setCurrentGuard(new TrueGuardOperand());
return false;
}
}
use of org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method INT_2DOUBLE.
/**
* taken from: The PowerPC Compiler Writer's Guide, pp. 83
*/
protected final void INT_2DOUBLE(Instruction s, RegisterOperand def, RegisterOperand left) {
Register res = def.getRegister();
Register src = left.getRegister();
Register FP = regpool.getPhysicalRegisterSet().asPPC().getFP();
RegisterOperand temp = regpool.makeTempInt();
int p = burs.ir.stackManager.allocateSpaceForConversion();
EMIT(MIR_Unary.mutate(s, PPC_LDIS, temp, IC(0x4330)));
// TODO: valid location?
EMIT(MIR_Store.create(PPC_STW, I(temp.getRegister()), A(FP), IC(p), new TrueGuardOperand()));
Register t1 = regpool.getInteger();
EMIT(MIR_Binary.create(PPC_XORIS, I(t1), I(src), IC(0x8000)));
EMIT(MIR_Store.create(PPC_STW, I(t1), A(FP), IC(p + 4), new TrueGuardOperand()));
EMIT(MIR_Load.create(PPC_LFD, D(res), A(FP), IC(p)));
Register tempF = regpool.getDouble();
emitLFtoc(PPC_LFD, tempF, Entrypoints.I2DconstantField);
EMIT(MIR_Binary.create(PPC_FSUB, D(res), D(res), D(tempF)));
}
use of org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method IFCMP.
/**
* Generate a compare and branch sequence. Used in the expansion of trees
* where INT_IFCMP is a root
*
* @param s the ifcmp instruction
* @param guardResult the guard result of the ifcmp
* @param val1 the first value operand
* @param val2 the second value operand
* @param cond the condition operand
*/
protected final void IFCMP(Instruction s, RegisterOperand guardResult, Operand val1, Operand val2, ConditionOperand cond) {
if (VM.VerifyAssertions) {
// We only need make sure the guard information is correct when
// validating, the null check combining phase removes all guards
EMIT(CPOS(s, Move.create(GUARD_MOVE, guardResult, new TrueGuardOperand())));
}
EMIT(CPOS(s, MIR_Compare.create(IA32_CMP, val1, val2)));
EMIT(MIR_CondBranch.mutate(s, IA32_JCC, COND(cond), IfCmp.getTarget(s), IfCmp.getBranchProfile(s)));
}
use of org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand in project JikesRVM by JikesRVM.
the class GenerationContextTest method packagePrivateMakeLocalReturnsRegWithInheritedFlagsAndGuard.
@Test
public void packagePrivateMakeLocalReturnsRegWithInheritedFlagsAndGuard() throws Exception {
NormalMethod nm = TestingTools.getNormalMethod(MethodsForTests.class, "emptyInstanceMethodWithoutAnnotations");
OptOptions opts = new OptOptions();
GenerationContext gc = new GenerationContext(nm, null, null, opts, null);
int localNumber = 0;
TypeReference localType = nm.getDeclaringClass().getTypeRef();
RegisterOperand regOp = gc.makeLocal(localNumber, localType);
TrueGuardOperand guard = new TrueGuardOperand();
regOp.setGuard(guard);
regOp.setParameter();
regOp.setNonVolatile();
regOp.setExtant();
regOp.setDeclaredType();
regOp.setPreciseType();
regOp.setPositiveInt();
RegisterOperand newRegOpWithInheritance = gc.makeLocal(localNumber, regOp);
Operand scratchObject = newRegOpWithInheritance.getGuard();
assertTrue(scratchObject.isTrueGuard());
assertTrue(newRegOpWithInheritance.isParameter());
assertTrue(newRegOpWithInheritance.isNonVolatile());
assertTrue(newRegOpWithInheritance.isExtant());
assertTrue(newRegOpWithInheritance.isDeclaredType());
assertTrue(newRegOpWithInheritance.isPreciseType());
assertTrue(newRegOpWithInheritance.isPositiveInt());
}
use of org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand 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);
}
Aggregations