use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method doArrayStore.
/**
* Expand an array store.
* @param s the instruction to expand
* @param ir the containing IR
* @param op the store operator to use
* @param logwidth the log base 2 of the element type's size
*/
public static void doArrayStore(Instruction s, IR ir, Operator op, int logwidth) {
if (LOWER_ARRAY_ACCESS) {
Operand value = AStore.getClearValue(s);
Operand array = AStore.getClearArray(s);
Operand index = AStore.getClearIndex(s);
Operand offset;
LocationOperand loc = AStore.getClearLocation(s);
if (index instanceof IntConstantOperand) {
// constant propagation
offset = AC(Address.fromIntZeroExtend(((IntConstantOperand) index).value << logwidth));
} else {
if (logwidth != 0) {
offset = insertBinary(s, ir, INT_SHL, TypeReference.Int, index, IC(logwidth));
offset = InsertUnary(s, ir, INT_2ADDRZerExt, TypeReference.Offset, offset.copy());
} else {
offset = InsertUnary(s, ir, INT_2ADDRZerExt, TypeReference.Offset, index);
}
}
Store.mutate(s, op, value, array, offset, loc, AStore.getClearGuard(s));
}
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method resolveMember.
/**
* Generate the code to resolve a member (field/method) reference.
* @param s the RESOLVE_MEMBER instruction to expand
* @param ir the containing ir object
* @return the last expanded instruction
*/
private static Instruction resolveMember(Instruction s, IR ir) {
Operand memberOp = Unary.getClearVal(s);
RegisterOperand offset = Unary.getClearResult(s);
int dictId;
if (memberOp instanceof LocationOperand) {
dictId = ((LocationOperand) memberOp).getFieldRef().getId();
} else {
dictId = ((MethodOperand) memberOp).getMemberRef().getId();
}
BranchProfileOperand bp = BranchProfileOperand.never();
BasicBlock predBB = s.getBasicBlock();
BasicBlock succBB = predBB.splitNodeAt(s.prevInstructionInCodeOrder(), ir);
BasicBlock testBB = predBB.createSubBlock(s.getBytecodeIndex(), ir, 1f - bp.takenProbability);
BasicBlock resolveBB = predBB.createSubBlock(s.getBytecodeIndex(), ir, bp.takenProbability);
s.remove();
// Get the offset from the appropriate RVMClassLoader array
// and check to see if it is valid
RegisterOperand offsetTable = getStatic(testBB.lastInstruction(), ir, Entrypoints.memberOffsetsField);
testBB.appendInstruction(Load.create(INT_LOAD, offset.copyRO(), offsetTable, AC(Offset.fromIntZeroExtend(dictId << LOG_BYTES_IN_INT)), new LocationOperand(TypeReference.Int), TG()));
testBB.appendInstruction(Unary.create(INT_2ADDRSigExt, offset, offset.copy()));
testBB.appendInstruction(IfCmp.create(REF_IFCMP, ir.regpool.makeTempValidation(), offset.copy(), AC(Address.fromIntSignExtend(NEEDS_DYNAMIC_LINK)), ConditionOperand.EQUAL(), resolveBB.makeJumpTarget(), bp));
// Handle the offset being invalid
resolveBB.appendInstruction(CacheOp.mutate(s, RESOLVE, memberOp));
resolveBB.appendInstruction(testBB.makeGOTO());
// Put together the CFG links & code order
predBB.insertOut(testBB);
ir.cfg.linkInCodeOrder(predBB, testBB);
testBB.insertOut(succBB);
testBB.insertOut(resolveBB);
ir.cfg.linkInCodeOrder(testBB, succBB);
// backedge
resolveBB.insertOut(testBB);
// stick resolution code in outer space.
ir.cfg.addLastInCodeOrder(resolveBB);
return testBB.lastInstruction();
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method doArrayLoad.
/**
* Expand an array load.
* @param s the instruction to expand
* @param ir the containing IR
* @param op the load operator to use
* @param logwidth the log base 2 of the element type's size
*/
public static void doArrayLoad(Instruction s, IR ir, Operator op, int logwidth) {
if (LOWER_ARRAY_ACCESS) {
RegisterOperand result = ALoad.getClearResult(s);
Operand array = ALoad.getClearArray(s);
Operand index = ALoad.getClearIndex(s);
Operand offset;
LocationOperand loc = ALoad.getClearLocation(s);
if (index instanceof IntConstantOperand) {
// constant propagation
offset = AC(Address.fromIntZeroExtend(((IntConstantOperand) index).value << logwidth));
} else {
if (logwidth != 0) {
offset = insertBinary(s, ir, INT_SHL, TypeReference.Int, index, IC(logwidth));
offset = InsertUnary(s, ir, INT_2ADDRZerExt, TypeReference.Offset, offset.copy());
} else {
offset = InsertUnary(s, ir, INT_2ADDRZerExt, TypeReference.Offset, index);
}
}
Load.mutate(s, op, result, array, offset, loc, ALoad.getClearGuard(s));
}
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method mustImplementInterface.
/**
* Expand a checkcastInterface instruction into the LIR sequence that
* implements the dynamic type check, raising an IncompataibleClassChangeError
* if the type check fails.
* Ref is known to never contain a null ptr at runtime.
*
* @param s a MUST_IMPLEMENT_INTERFACE instruction to expand
* @param ir the enclosing IR
* @return the last Instruction in the generated LIR sequence.
*/
static Instruction mustImplementInterface(Instruction s, IR ir) {
Operand ref = TypeCheck.getClearRef(s);
RVMClass LHSClass = (RVMClass) TypeCheck.getType(s).getVMType();
if (VM.VerifyAssertions)
VM._assert(LHSClass != null, "Should be resolvable...");
int interfaceIndex = LHSClass.getDoesImplementIndex();
int interfaceMask = LHSClass.getDoesImplementBitMask();
Operand guard = TypeCheck.getClearGuard(s);
BasicBlock myBlock = s.getBasicBlock();
BasicBlock failBlock = myBlock.createSubBlock(s.getBytecodeIndex(), ir, .0001f);
BasicBlock succBlock = myBlock.splitNodeAt(s, ir);
succBlock.firstInstruction().insertAfter(Move.create(REF_MOVE, TypeCheck.getClearResult(s), ref.copy()));
myBlock.insertOut(failBlock);
myBlock.insertOut(succBlock);
ir.cfg.linkInCodeOrder(myBlock, succBlock);
ir.cfg.addLastInCodeOrder(failBlock);
Instruction raiseError = Trap.create(TRAP, null, TrapCodeOperand.MustImplement());
raiseError.copyPosition(s);
failBlock.appendInstruction(raiseError);
Operand RHStib = getTIB(s, ir, ref, guard);
RegisterOperand doesImpl = InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
RegisterOperand doesImplLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
Instruction lengthCheck = IfCmp.create(INT_IFCMP, ir.regpool.makeTempValidation(), doesImplLength, IC(interfaceIndex), ConditionOperand.LESS_EQUAL(), failBlock.makeJumpTarget(), BranchProfileOperand.never());
s.insertBefore(lengthCheck);
myBlock.splitNodeWithLinksAt(lengthCheck, ir);
// required due to splitNode!
myBlock.insertOut(failBlock);
}
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));
IfCmp.mutate(s, INT_IFCMP, ir.regpool.makeTempValidation(), bit, IC(0), ConditionOperand.EQUAL(), failBlock.makeJumpTarget(), BranchProfileOperand.never());
return s;
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method generateBranchingTypeCheck.
/**
* Generate a branching dynamic type check.
* This routine assumes that the CFG and code order are already
* correctly established.
* This routine must either remove s or mutate it.
*
* @param s The Instruction that is to be replaced by a
* branching type check
* @param ir The IR containing the instruction to be expanded.
* @param RHSobj The RegisterOperand containing the rhs object.
* @param LHStype The TypeReference to be tested against.
* @param RHStib The Operand containing the TIB of the rhs.
* @param trueBlock The BasicBlock to continue at if the typecheck
* evaluates to true
* @param falseBlock The BasicBlock to continue at if the typecheck
* evaluates to false.
* @param oldGuard A suitable guard operand (not necessarily related
* the instruction that is to be replaced).
* @param falseProb The probability that typecheck will branch to the falseBlock
* @return the opt instruction immediately before the instruction to
* continue expansion.
*/
private static Instruction generateBranchingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, BasicBlock trueBlock, BasicBlock falseBlock, RegisterOperand oldGuard, BranchProfileOperand falseProb) {
Instruction continueAt = Goto.create(GOTO, trueBlock.makeJumpTarget());
continueAt.copyPosition(s);
s.insertBefore(continueAt);
s.remove();
if (LHStype.isClassType()) {
RVMClass LHSclass = (RVMClass) LHStype.peekType();
if (LHSclass != null && LHSclass.isResolved()) {
// class or interface
if (LHSclass.isInterface()) {
// A resolved interface (case 4)
int interfaceIndex = LHSclass.getDoesImplementIndex();
int interfaceMask = LHSclass.getDoesImplementBitMask();
RegisterOperand doesImpl = InsertUnary(continueAt, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
RegisterOperand doesImplLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, doesImplLength, IC(interfaceIndex), ConditionOperand.LESS_EQUAL(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(lengthCheck);
BasicBlock oldBlock = continueAt.getBasicBlock();
oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
// required due to splitNode!
oldBlock.insertOut(falseBlock);
}
RegisterOperand entry = InsertLoadOffset(continueAt, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
RegisterOperand bit = insertBinary(continueAt, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, bit, IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
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(continueAt, ir, LHSclass);
continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
} else {
// Do the full blown case 5 or 6 typecheck.
int LHSDepth = LHSclass.getTypeDepth();
int LHSId = LHSclass.getId();
RegisterOperand superclassIds = InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
RegisterOperand superclassIdsLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, superclassIdsLength, IC(LHSDepth), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(lengthCheck);
BasicBlock oldBlock = continueAt.getBasicBlock();
oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
// required due to splitNode!
oldBlock.insertOut(falseBlock);
}
RegisterOperand refCandidate = InsertLoadOffset(continueAt, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, refCandidate, IC(LHSId), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
} else {
// A non-resolved class or interface. Case 3 of DynamicTypeCheck
// Branch on the result of a call to
// RuntimeEntrypoints.instance
RegisterOperand result = ir.regpool.makeTempInt();
RVMMethod target = Entrypoints.instanceOfMethod;
Instruction call = Call.create2(CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
call.copyPosition(continueAt);
continueAt.insertBefore(call);
call = callHelper(call, ir);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, result.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
if (LHStype.isArrayType()) {
// Case 2 of DynamicTypeCheck: LHS is an array.
RVMArray LHSArray = (RVMArray) LHStype.peekType();
if (LHSArray != null) {
Operand classTIB = getTIB(continueAt, ir, LHSArray);
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.
continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
// TODO: branch probability calculation is somewhat bogus for this case.
Instruction shortcircuit = IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.EQUAL(), trueBlock.makeJumpTarget(), new BranchProfileOperand());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(shortcircuit);
BasicBlock myBlock = shortcircuit.getBasicBlock();
BasicBlock mainBlock = myBlock.splitNodeWithLinksAt(shortcircuit, ir);
// must come after the splitNodeAt
myBlock.insertOut(trueBlock);
RegisterOperand rhsType = InsertUnary(continueAt, ir, GET_TYPE_FROM_TIB, TypeReference.Type, RHStib.copy());
if (innermostElementType.isJavaLangObjectType()) {
IntConstantOperand lhsDimension = IC(LHStype.getDimensionality());
RegisterOperand rhsDimension = getField(continueAt, ir, rhsType, Entrypoints.dimensionField);
Instruction dimTest = IfCmp2.create(INT_IFCMP2, oldGuard, rhsDimension, lhsDimension, ConditionOperand.GREATER(), trueBlock.makeJumpTarget(), ((BranchProfileOperand) falseProb.copy()).flip(), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), (BranchProfileOperand) falseProb.copy());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(dimTest);
// BasicBlock testBlock =
mainBlock.splitNodeWithLinksAt(dimTest, ir);
mainBlock.insertOut(trueBlock);
mainBlock.insertOut(falseBlock);
RegisterOperand rhsInnermostElementTypeDimension = getField(continueAt, ir, rhsType.copyU2U(), Entrypoints.innermostElementTypeDimensionField);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, rhsInnermostElementTypeDimension, IC(0), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
// Not a case we want to handle inline
RVMMethod target = Entrypoints.instanceOfMethod;
RegisterOperand callResult = ir.regpool.makeTempInt();
Instruction call = Call.create2(CALL, callResult, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
call.copyPosition(continueAt);
continueAt.insertBefore(call);
call = callHelper(call, ir);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, callResult.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
OptimizingCompilerException.UNREACHABLE();
return null;
}
Aggregations