use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class VMInstrumentationImpl method getObjectSize.
static long getObjectSize(Object objectToSize) {
Class<?> cl = objectToSize.getClass();
RVMType vmType = java.lang.JikesRVMSupport.getTypeForClass(cl);
if (cl.isArray()) {
RVMArray vmArray = (RVMArray) vmType;
int nelements = java.lang.reflect.Array.getLength(objectToSize);
return vmArray.getInstanceSize(nelements);
} else {
RVMClass vmClass = (RVMClass) vmType;
return vmClass.getInstanceSize();
}
}
use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class InterfaceHierarchy method allImplementors.
/**
* @return the set of all classes known to implement the interface
* @param I the implemented interface
*/
private static ImmutableEntryHashSetRVM<RVMClass> allImplementors(RVMClass I) {
// get the set of classes registered as implementing I
ImmutableEntryHashSetRVM<RVMClass> result = findOrCreateSet(I);
// need to do this kludge to avoid recursive concurrent modification
for (RVMClass subClass : I.getSubClasses()) {
result.addAll(allImplementors(subClass));
}
// also add any sub-classes of these classes.
// need to cache additions to avoid modifying the set while iterating
ImmutableEntryHashSetRVM<RVMClass> toAdd = new ImmutableEntryHashSetRVM<RVMClass>(5);
for (RVMClass c : result) {
toAdd.addAll(allSubClasses(c));
}
result.addAll(toAdd);
return result;
}
use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method callHelper.
/**
* Helper method for call expansion.
* @param v the call instruction
* @param ir the containing IR
* @return the last expanded instruction
*/
static Instruction callHelper(Instruction v, IR ir) {
if (!Call.hasMethod(v)) {
if (VM.VerifyAssertions)
VM._assert(Call.getAddress(v) instanceof RegisterOperand);
// nothing to do....very low level call to address already in the register.
return v;
}
MethodOperand methOp = Call.getMethod(v);
// Handle recursive invocations.
if (methOp.hasPreciseTarget() && methOp.getTarget() == ir.method) {
Call.setAddress(v, new BranchOperand(ir.firstInstructionInCodeOrder()));
return v;
}
// has been marked as a specialized call.
if (VM.runningVM) {
SpecializedMethod spMethod = methOp.spMethod;
if (spMethod != null) {
int smid = spMethod.getSpecializedMethodIndex();
Call.setAddress(v, getSpecialMethod(v, ir, smid));
return v;
}
}
// Used mainly (only?) by OSR
if (methOp.hasDesignatedTarget()) {
Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, methOp.jtocOffset));
return v;
}
if (methOp.isStatic()) {
if (VM.VerifyAssertions)
VM._assert(Call.hasAddress(v));
Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, Call.getClearAddress(v)));
} else if (methOp.isVirtual()) {
if (VM.VerifyAssertions)
VM._assert(Call.hasAddress(v));
if (ir.options.H2L_CALL_VIA_JTOC && methOp.hasPreciseTarget()) {
// Call to precise type can go via JTOC
RVMMethod target = methOp.getTarget();
Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, target.findOrCreateJtocOffset()));
} else {
Operand tib = getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy());
Call.setAddress(v, InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, tib, Call.getClearAddress(v), null, TG()));
}
} else if (methOp.isSpecial()) {
RVMMethod target = methOp.getTarget();
if (target == null || target.isObjectInitializer() || target.isStatic()) {
// target == null => we are calling an unresolved <init> method.
Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, Call.getClearAddress(v)));
} else {
if (ir.options.H2L_CALL_VIA_JTOC) {
Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, target.findOrCreateJtocOffset()));
} else {
// invoking a virtual method; do it via TIB of target's declaring class.
Operand tib = getTIB(v, ir, target.getDeclaringClass());
Call.setAddress(v, InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, tib, Call.getClearAddress(v), null, TG()));
}
}
} else {
if (VM.VerifyAssertions)
VM._assert(methOp.isInterface());
if (VM.VerifyAssertions)
VM._assert(!Call.hasAddress(v));
if (VM.BuildForIMTInterfaceInvocation) {
// SEE ALSO: FinalMIRExpansion (for hidden parameter)
Operand RHStib = getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy());
InterfaceMethodSignature sig = InterfaceMethodSignature.findOrCreate(methOp.getMemberRef());
Offset offset = sig.getIMTOffset();
RegisterOperand address = null;
RegisterOperand IMT = InsertLoadOffset(v, ir, REF_LOAD, TypeReference.IMT, RHStib.copy(), Offset.fromIntZeroExtend(TIB_INTERFACE_DISPATCH_TABLE_INDEX << LOG_BYTES_IN_ADDRESS));
address = InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, IMT.copyD2U(), offset);
Call.setAddress(v, address);
} else {
int itableIndex = -1;
if (VM.BuildForITableInterfaceInvocation && methOp.hasTarget()) {
RVMClass I = methOp.getTarget().getDeclaringClass();
// search ITable variant
itableIndex = InterfaceInvocation.getITableIndex(I, methOp.getMemberRef().getName(), methOp.getMemberRef().getDescriptor());
}
if (itableIndex == -1) {
// itable index is not known at compile-time.
// call "invokeinterface" to resolve the object and method id
// into a method address
RegisterOperand realAddrReg = ir.regpool.makeTemp(TypeReference.CodeArray);
RVMMethod target = Entrypoints.invokeInterfaceMethod;
Instruction vp = Call.create2(CALL, realAddrReg, AC(target.getOffset()), MethodOperand.STATIC(target), Call.getParam(v, 0).asRegister().copyU2U(), IC(methOp.getMemberRef().getId()));
vp.setSourcePosition(RUNTIME_SERVICES_BCI, v.position());
v.insertBefore(vp);
callHelper(vp, ir);
Call.setAddress(v, realAddrReg.copyD2U());
return v;
} else {
// itable index is known at compile-time.
// call "findITable" to resolve object + interface id into
// itable address
RegisterOperand iTable = ir.regpool.makeTemp(TypeReference.ITable);
Operand RHStib = getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy());
RVMMethod target = Entrypoints.findItableMethod;
Instruction fi = Call.create2(CALL, iTable, AC(target.getOffset()), MethodOperand.STATIC(target), RHStib, IC(methOp.getTarget().getDeclaringClass().getInterfaceId()));
fi.setSourcePosition(RUNTIME_SERVICES_BCI, v.position());
v.insertBefore(fi);
callHelper(fi, ir);
RegisterOperand address = InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, iTable.copyD2U(), Offset.fromIntZeroExtend(itableIndex << LOG_BYTES_IN_ADDRESS));
Call.setAddress(v, address);
return v;
}
}
}
return v;
}
use of org.jikesrvm.classloader.RVMClass in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method generateValueProducingTypeCheck.
/**
* Generate a value-producing dynamic type check.
* This routine assumes that the CFG and code order are
* already correctly established.
* This routine must either remove s or mutuate it.
*
* @param s The Instruction that is to be replaced by
* a value producing type check
* @param ir The IR containing the instruction to be expanded.
* @param RHSobj The RegisterOperand containing the rhs object.
* @param LHStype The RVMType to be tested against.
* @param RHStib The Operand containing the TIB of the rhs.
* @param result The RegisterOperand that the result of dynamic
* type check is to be stored in.
* @return the opt instruction immediately before the
* instruction to continue expansion.
*/
private static Instruction generateValueProducingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, RegisterOperand result) {
// Is LHStype a class?
if (LHStype.isClassType()) {
RVMClass LHSclass = (RVMClass) LHStype.peekType();
if (LHSclass != null && LHSclass.isResolved()) {
// resolved class or interface
if (LHSclass.isInterface()) {
// A resolved interface (case 4)
int interfaceIndex = LHSclass.getDoesImplementIndex();
int interfaceMask = LHSclass.getDoesImplementBitMask();
RegisterOperand doesImpl = InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
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));
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, result, bit, AC(Address.zero()), ConditionOperand.NOT_EQUAL(), new BranchProfileOperand()));
if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
RegisterOperand doesImplLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copy(), TG());
RegisterOperand boundscheck = ir.regpool.makeTempInt();
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, boundscheck, doesImplLength, AC(Address.fromIntSignExtend(interfaceIndex)), ConditionOperand.GREATER(), new BranchProfileOperand()));
s.insertBefore(Binary.create(INT_AND, result.copyD2D(), result.copyD2U(), boundscheck.copyD2U()));
}
Instruction continueAt = s.prevInstructionInCodeOrder();
s.remove();
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(s, ir, LHSclass);
BooleanCmp.mutate(s, BOOLEAN_CMP_ADDR, result, RHStib, classTIB, ConditionOperand.EQUAL(), new BranchProfileOperand());
return s.prevInstructionInCodeOrder();
} else {
// Do the full blown case 5 or 6 typecheck.
int LHSDepth = LHSclass.getTypeDepth();
int LHSId = LHSclass.getId();
RegisterOperand superclassIds = InsertUnary(s, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
RegisterOperand refCandidate = InsertLoadOffset(s, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, result, refCandidate, AC(Address.fromIntZeroExtend(LHSId)), ConditionOperand.EQUAL(), new BranchProfileOperand()));
if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
RegisterOperand superclassIdsLength = InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
RegisterOperand boundscheck = ir.regpool.makeTempInt();
// save to use the cheaper ADDR version of BOOLEAN_CMP
s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR, boundscheck, superclassIdsLength, AC(Address.fromIntSignExtend(LHSDepth)), ConditionOperand.GREATER(), new BranchProfileOperand()));
s.insertBefore(Binary.create(INT_AND, result.copyD2D(), result.copyD2U(), boundscheck.copyD2U()));
}
Instruction continueAt = s.prevInstructionInCodeOrder();
s.remove();
return continueAt;
}
}
} else {
// A non-resolved class or interface.
// We expect these to be extremely uncommon in opt code in AOS.
// Mutate s into a call to RuntimeEntrypoints.instanceOf
RVMMethod target = Entrypoints.instanceOfMethod;
Call.mutate2(s, CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
return callHelper(s, ir);
}
}
if (LHStype.isArrayType()) {
// Case 2 of DynamicTypeCheck: LHS is an array.
RVMArray LHSArray = (RVMArray) LHStype.peekType();
if (LHSArray != null) {
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.
Operand classTIB = getTIB(s, ir, LHSArray);
BooleanCmp.mutate(s, BOOLEAN_CMP_ADDR, result, RHStib, classTIB, ConditionOperand.EQUAL(), new BranchProfileOperand());
return s;
}
}
// and do the real work there.
return convertToBranchingTypeCheck(s, ir, RHSobj, LHStype, RHStib, result);
}
OptimizingCompilerException.UNREACHABLE();
return null;
}
use of org.jikesrvm.classloader.RVMClass 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