protected final RVMType getRVMTypeForClassWithAppCL(String className) { Atom descriptor = Atom.findOrCreateAsciiAtom(className.replace('.', '/')).descriptorFromClassName(); TypeReference tRef = TypeReference.findOrCreate(ApplicationClassLoader.getSystemClassLoader(), descriptor); return tRef.peekType(); }
private static Class<?> forNameInternal( String className, boolean initialize, ClassLoader classLoader) throws ClassNotFoundException, LinkageError, ExceptionInInitializerError { try { if (className.startsWith("[")) { if (!validArrayDescriptor(className)) { throw new ClassNotFoundException(className); } } Atom descriptor = Atom.findOrCreateAsciiAtom(className.replace('.', '/')).descriptorFromClassName(); TypeReference tRef = TypeReference.findOrCreate(classLoader, descriptor); RVMType ans = tRef.resolve(); Callbacks.notifyForName(ans); if (initialize && !ans.isInitialized()) { ans.resolve(); ans.instantiate(); ans.initialize(); } return ans.getClassForType(); } catch (NoClassDefFoundError ncdfe) { Throwable cause2 = ncdfe.getCause(); ClassNotFoundException cnf; // If we get a NCDFE that was caused by a CNFE, throw the original CNFE. if (cause2 instanceof ClassNotFoundException) cnf = (ClassNotFoundException) cause2; else cnf = new ClassNotFoundException(className, ncdfe); throw cnf; } }
public Class<?> getEnclosingClass() { if (type.isClassType()) { TypeReference enclosingClass = type.asClass().getEnclosingClass(); if (enclosingClass != null) { return enclosingClass.resolve().getClassForType(); } else { return null; } } else { return null; } }
/** What would be the appropriate return bytecode for the given type reference? */ private static int typeRefToReturnBytecode(TypeReference tr) { if (!tr.isPrimitiveType()) { return JBC_areturn; } else { Primitive pt = (Primitive) tr.peekType(); if ((pt == RVMType.BooleanType) || (pt == RVMType.ByteType) || (pt == RVMType.ShortType) || (pt == RVMType.CharType) || (pt == RVMType.IntType)) { return JBC_ireturn; } else if (pt == RVMType.LongType) { return JBC_lreturn; } else if (pt == RVMType.FloatType) { return JBC_freturn; } else if (pt == RVMType.DoubleType) { return JBC_dreturn; } else { if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED); return -1; } } }
public Class<?>[] getClasses() throws SecurityException { checkMemberAccess(Member.PUBLIC); if (!type.isClassType()) return new Class[0]; ArrayList<Class<?>> publicClasses = new ArrayList<Class<?>>(); for (Class<?> c = this; c != null; c = c.getSuperclass()) { c.checkMemberAccess(Member.PUBLIC); TypeReference[] declaredClasses = c.type.asClass().getDeclaredClasses(); if (declaredClasses != null) { for (TypeReference declaredClass : declaredClasses) { if (declaredClass != null) { RVMClass dc = declaredClass.resolve().asClass(); if (dc.isPublic()) { publicClasses.add(dc.getClassForType()); } } } } } Class<?>[] result = new Class[publicClasses.size()]; result = publicClasses.toArray(result); return result; }
public SpecializedScanMethod(int id, TypeReference specializedTrace) { super(id); this.specializedSignature = new TypeReference[] {TypeReference.JavaLangObject, specializedTrace}; if (!VM.BuildWithBaseBootImageCompiler) { /* Compile our specialized methods when we are opt compiling */ RVMClass myClass = specializedScanMethodType.peekType().asClass(); for (int i = 0; i < PATTERNS; i++) { RVMMethod method = myClass.findStaticMethod(templateMethodName(i), specializedMethodDescriptor); specializedMethods[i] = compileSpecializedMethod(method, specializedSignature); } } }
/** * A method that scan objects and is specialized to a specific MMTk TransitiveClosure type. * * <p>In general as there may not be a 1-1 mapping between objects and the specialized methods this * class is responsible for performing the mapping. * * <p>Specialized methods must have a static 'invoke' method that matches the given signature and * return type. */ @Uninterruptible public final class SpecializedScanMethod extends SpecializedMethod implements SizeConstants, JavaHeaderConstants { /** Use specialized scanning ? */ public static final boolean ENABLED = true; /** This method's signature: the object to be scanned and the trace to use */ private static final TypeReference[] signature = new TypeReference[] { TypeReference.JavaLangObject, TypeReference.findOrCreate(TransitiveClosure.class) }; /** The return type of this method: void */ private static final TypeReference returnType = TypeReference.Void; /** Our type reference */ private static final TypeReference specializedScanMethodType = TypeReference.findOrCreate(SpecializedScanMethod.class); /** Objects with no references or primitive arrays */ private static final int NULL_PATTERN = 0; /** Number of patterns we will specialize */ private static final int SPECIALIZED_PATTERNS = 64; /** Reference arrays */ private static final int REFARRAY_PATTERN = 64; /** Fallback to a slower path that is not specialized */ private static final int FALLBACK_PATTERN = 65; /** The total number of patterns */ private static final int PATTERNS = 66; /** Maximum field offset we can deal with */ private static final int MAX_SPECIALIZED_OFFSET = 6 << LOG_BYTES_IN_ADDRESS; /** We keep the specialized methods for key object reference patterns here. */ private final CompiledMethod[] specializedMethods = new CompiledMethod[PATTERNS]; /** The specialized signature of the method */ private final TypeReference[] specializedSignature; public SpecializedScanMethod(int id, TypeReference specializedTrace) { super(id); this.specializedSignature = new TypeReference[] {TypeReference.JavaLangObject, specializedTrace}; if (!VM.BuildWithBaseBootImageCompiler) { /* Compile our specialized methods when we are opt compiling */ RVMClass myClass = specializedScanMethodType.peekType().asClass(); for (int i = 0; i < PATTERNS; i++) { RVMMethod method = myClass.findStaticMethod(templateMethodName(i), specializedMethodDescriptor); specializedMethods[i] = compileSpecializedMethod(method, specializedSignature); } } } /** Get the pattern index for a given type */ @Interruptible private static int getPattern(RVMType type) { /* Handle array types */ if (type.isArrayType()) { if (type.asArray().getElementType().isReferenceType()) { return REFARRAY_PATTERN; } return NULL_PATTERN; } /* Build a bitmap if the object is compact enough and is not a reference array */ int[] offsets = type.asClass().getReferenceOffsets(); if (offsets.length == 0) { return NULL_PATTERN; } if ((offsets.length << LOG_BYTES_IN_ADDRESS) > SPECIALIZED_PATTERNS) { return FALLBACK_PATTERN; } int base = FIELD_ZERO_OFFSET.toInt(); int pattern = 0; for (int i = 0; i < offsets.length; i++) { int reference = (offsets[i] - base); if (reference > MAX_SPECIALIZED_OFFSET) { return FALLBACK_PATTERN; } pattern |= 1 << (reference >> LOG_BYTES_IN_ADDRESS); } if (pattern < 0 || pattern > 63) { pattern = FALLBACK_PATTERN; } return pattern; } /** * Return the specialized method for the given type. * * <p>TODO: Lazily compile specialized methods? */ @Interruptible public synchronized CodeArray specializeMethod(RVMType type) { /* Work out which pattern this type uses */ int pattern = getPattern(type); if (VM.BuildWithBaseBootImageCompiler) { /* There is no point specializing if we aren't opt compiling */ return null; } /* Ensure we have a compiled method cached. */ if (VM.VerifyAssertions) VM._assert(specializedMethods[pattern] != null); /* Return the code entry array */ return specializedMethods[pattern].getEntryCodeArray(); } /** @return the method signature of the specialized method's invoke. */ public TypeReference[] getSignature() { return signature; } /** @return the return type of the specialized method's invoke */ public TypeReference getReturnType() { return returnType; } /** * This method peforms the scanning of a given object. * * <p>This is the method that (may) be hijacked by the compiler to call the specialized method. * * <p>It is safe for a compiler to ignore the potential gains and just use this method directly. * * @param id The specialized method id * @param object The object to scan * @param trace The trace to scan */ @SpecializedMethodInvoke @NoInline public static void invoke(int id, Object object, TransitiveClosure trace) { /* By default we call a non-specialized fallback */ fallback(object, trace); } /** Fallback */ public static void fallback(Object object, TransitiveClosure trace) { ObjectReference objectRef = ObjectReference.fromObject(object); RVMType type = ObjectModel.getObjectType(objectRef.toObject()); if (type.isClassType()) { RVMClass klass = type.asClass(); int[] offsets = klass.getReferenceOffsets(); for (int i = 0; i < offsets.length; i++) { trace.processEdge(objectRef, objectRef.toAddress().plus(offsets[i])); } } else if (type.isArrayType() && type.asArray().getElementType().isReferenceType()) { for (int i = 0; i < ObjectModel.getArrayLength(objectRef.toObject()); i++) { trace.processEdge(objectRef, objectRef.toAddress().plus(i << LOG_BYTES_IN_ADDRESS)); } } } /** All Scalars */ public static void scalar(Object object, TransitiveClosure trace) { Address base = Magic.objectAsAddress(object); int[] offsets = ObjectModel.getObjectType(object).asClass().getReferenceOffsets(); for (int i = 0; i < offsets.length; i++) { trace.processEdge(ObjectReference.fromObject(object), base.plus(offsets[i])); } } /** Reference Arrays */ public static void referenceArray(Object object, TransitiveClosure trace) { Address base = Magic.objectAsAddress(object); int length = ObjectModel.getArrayLength(object); for (int i = 0; i < length; i++) { trace.processEdge(ObjectReference.fromObject(object), base.plus(i << LOG_BYTES_IN_ADDRESS)); } } /** No Reference fields / Primitive Arrays */ public static void noReferences(Object object, TransitiveClosure trace) {} /** All patterns bottom out here */ @Inline public static void pattern(int pattern, Object object, TransitiveClosure trace) { Address base = Magic.objectAsAddress(object).plus(FIELD_ZERO_OFFSET); if ((pattern & 1) != 0) { trace.processEdge(ObjectReference.fromObject(object), base.plus(0)); } if ((pattern & 2) != 0) { trace.processEdge(ObjectReference.fromObject(object), base.plus(1 << LOG_BYTES_IN_ADDRESS)); } if ((pattern & 4) != 0) { trace.processEdge(ObjectReference.fromObject(object), base.plus(2 << LOG_BYTES_IN_ADDRESS)); } if ((pattern & 8) != 0) { trace.processEdge(ObjectReference.fromObject(object), base.plus(3 << LOG_BYTES_IN_ADDRESS)); } if ((pattern & 16) != 0) { trace.processEdge(ObjectReference.fromObject(object), base.plus(4 << LOG_BYTES_IN_ADDRESS)); } if ((pattern & 32) != 0) { trace.processEdge(ObjectReference.fromObject(object), base.plus(5 << LOG_BYTES_IN_ADDRESS)); } } /** * Find the template method name for a given pattern. * * @param pattern The pattern to look for * @return The method name that will be used. */ private Atom templateMethodName(int pattern) { switch (pattern) { case 1: return Names.scalarRNNNNN; case 2: return Names.scalarNRNNNN; case 3: return Names.scalarRRNNNN; case 4: return Names.scalarNNRNNN; case 5: return Names.scalarRNRNNN; case 6: return Names.scalarNRRNNN; case 7: return Names.scalarRRRNNN; case 8: return Names.scalarNNNRNN; case 9: return Names.scalarRNNRNN; case 10: return Names.scalarNRNRNN; case 11: return Names.scalarRRNRNN; case 12: return Names.scalarNNRRNN; case 13: return Names.scalarRNRRNN; case 14: return Names.scalarNRRRNN; case 15: return Names.scalarRRRRNN; case 16: return Names.scalarNNNNRN; case 17: return Names.scalarRNNNRN; case 18: return Names.scalarNRNNRN; case 19: return Names.scalarRRNNRN; case 20: return Names.scalarNNRNRN; case 21: return Names.scalarRNRNRN; case 22: return Names.scalarNRRNRN; case 23: return Names.scalarRRRNRN; case 24: return Names.scalarNNNRRN; case 25: return Names.scalarRNNRRN; case 26: return Names.scalarNRNRRN; case 27: return Names.scalarRRNRRN; case 28: return Names.scalarNNRRRN; case 29: return Names.scalarRNRRRN; case 30: return Names.scalarNRRRRN; case 31: return Names.scalarRRRRRN; case 32: return Names.scalarNNNNNR; case 33: return Names.scalarRNNNNR; case 34: return Names.scalarNRNNNR; case 35: return Names.scalarRRNNNR; case 36: return Names.scalarNNRNNR; case 37: return Names.scalarRNRNNR; case 38: return Names.scalarNRRNNR; case 39: return Names.scalarRRRNNR; case 40: return Names.scalarNNNRNR; case 41: return Names.scalarRNNRNR; case 42: return Names.scalarNRNRNR; case 43: return Names.scalarRRNRNR; case 44: return Names.scalarNNRRNR; case 45: return Names.scalarRNRRNR; case 46: return Names.scalarNRRRNR; case 47: return Names.scalarRRRRNR; case 48: return Names.scalarNNNNRR; case 49: return Names.scalarRNNNRR; case 50: return Names.scalarNRNNRR; case 51: return Names.scalarRRNNRR; case 52: return Names.scalarNNRNRR; case 53: return Names.scalarRNRNRR; case 54: return Names.scalarNRRNRR; case 55: return Names.scalarRRRNRR; case 56: return Names.scalarNNNRRR; case 57: return Names.scalarRNNRRR; case 58: return Names.scalarNRNRRR; case 59: return Names.scalarRRNRRR; case 60: return Names.scalarNNRRRR; case 61: return Names.scalarRNRRRR; case 62: return Names.scalarNRRRRR; case 63: return Names.scalarRRRRRR; case NULL_PATTERN: return Names.noReferences; case REFARRAY_PATTERN: return Names.referenceArray; case FALLBACK_PATTERN: default: return Names.scalar; } } /** The generic descriptor for the specialized methods */ private static final Atom specializedMethodDescriptor = Atom.findOrCreateAsciiAtom("(Ljava/lang/Object;Lorg/mmtk/plan/TransitiveClosure;)V"); /** The atoms for the names of the specialized methods */ private static final class Names { static final Atom fallback = Atom.findOrCreateAsciiAtom("fallback"); static final Atom referenceArray = Atom.findOrCreateAsciiAtom("referenceArray"); static final Atom scalar = Atom.findOrCreateAsciiAtom("scalar"); static final Atom noReferences = Atom.findOrCreateAsciiAtom("noReferences"); static final Atom scalarRNNNNN = Atom.findOrCreateAsciiAtom("scalarRNNNNN"); static final Atom scalarNRNNNN = Atom.findOrCreateAsciiAtom("scalarNRNNNN"); static final Atom scalarRRNNNN = Atom.findOrCreateAsciiAtom("scalarRRNNNN"); static final Atom scalarNNRNNN = Atom.findOrCreateAsciiAtom("scalarNNRNNN"); static final Atom scalarRNRNNN = Atom.findOrCreateAsciiAtom("scalarRNRNNN"); static final Atom scalarNRRNNN = Atom.findOrCreateAsciiAtom("scalarNRRNNN"); static final Atom scalarRRRNNN = Atom.findOrCreateAsciiAtom("scalarRRRNNN"); static final Atom scalarNNNRNN = Atom.findOrCreateAsciiAtom("scalarNNNRNN"); static final Atom scalarRNNRNN = Atom.findOrCreateAsciiAtom("scalarRNNRNN"); static final Atom scalarNRNRNN = Atom.findOrCreateAsciiAtom("scalarNRNRNN"); static final Atom scalarRRNRNN = Atom.findOrCreateAsciiAtom("scalarRRNRNN"); static final Atom scalarNNRRNN = Atom.findOrCreateAsciiAtom("scalarNNRRNN"); static final Atom scalarRNRRNN = Atom.findOrCreateAsciiAtom("scalarRNRRNN"); static final Atom scalarNRRRNN = Atom.findOrCreateAsciiAtom("scalarNRRRNN"); static final Atom scalarRRRRNN = Atom.findOrCreateAsciiAtom("scalarRRRRNN"); static final Atom scalarNNNNRN = Atom.findOrCreateAsciiAtom("scalarNNNNRN"); static final Atom scalarRNNNRN = Atom.findOrCreateAsciiAtom("scalarRNNNRN"); static final Atom scalarNRNNRN = Atom.findOrCreateAsciiAtom("scalarNRNNRN"); static final Atom scalarRRNNRN = Atom.findOrCreateAsciiAtom("scalarRRNNRN"); static final Atom scalarNNRNRN = Atom.findOrCreateAsciiAtom("scalarNNRNRN"); static final Atom scalarRNRNRN = Atom.findOrCreateAsciiAtom("scalarRNRNRN"); static final Atom scalarNRRNRN = Atom.findOrCreateAsciiAtom("scalarNRRNRN"); static final Atom scalarRRRNRN = Atom.findOrCreateAsciiAtom("scalarRRRNRN"); static final Atom scalarNNNRRN = Atom.findOrCreateAsciiAtom("scalarNNNRRN"); static final Atom scalarRNNRRN = Atom.findOrCreateAsciiAtom("scalarRNNRRN"); static final Atom scalarNRNRRN = Atom.findOrCreateAsciiAtom("scalarNRNRRN"); static final Atom scalarRRNRRN = Atom.findOrCreateAsciiAtom("scalarRRNRRN"); static final Atom scalarNNRRRN = Atom.findOrCreateAsciiAtom("scalarNNRRRN"); static final Atom scalarRNRRRN = Atom.findOrCreateAsciiAtom("scalarRNRRRN"); static final Atom scalarNRRRRN = Atom.findOrCreateAsciiAtom("scalarNRRRRN"); static final Atom scalarRRRRRN = Atom.findOrCreateAsciiAtom("scalarRRRRRN"); static final Atom scalarNNNNNR = Atom.findOrCreateAsciiAtom("scalarNNNNNR"); static final Atom scalarRNNNNR = Atom.findOrCreateAsciiAtom("scalarRNNNNR"); static final Atom scalarNRNNNR = Atom.findOrCreateAsciiAtom("scalarNRNNNR"); static final Atom scalarRRNNNR = Atom.findOrCreateAsciiAtom("scalarRRNNNR"); static final Atom scalarNNRNNR = Atom.findOrCreateAsciiAtom("scalarNNRNNR"); static final Atom scalarRNRNNR = Atom.findOrCreateAsciiAtom("scalarRNRNNR"); static final Atom scalarNRRNNR = Atom.findOrCreateAsciiAtom("scalarNRRNNR"); static final Atom scalarRRRNNR = Atom.findOrCreateAsciiAtom("scalarRRRNNR"); static final Atom scalarNNNRNR = Atom.findOrCreateAsciiAtom("scalarNNNRNR"); static final Atom scalarRNNRNR = Atom.findOrCreateAsciiAtom("scalarRNNRNR"); static final Atom scalarNRNRNR = Atom.findOrCreateAsciiAtom("scalarNRNRNR"); static final Atom scalarRRNRNR = Atom.findOrCreateAsciiAtom("scalarRRNRNR"); static final Atom scalarNNRRNR = Atom.findOrCreateAsciiAtom("scalarNNRRNR"); static final Atom scalarRNRRNR = Atom.findOrCreateAsciiAtom("scalarRNRRNR"); static final Atom scalarNRRRNR = Atom.findOrCreateAsciiAtom("scalarNRRRNR"); static final Atom scalarRRRRNR = Atom.findOrCreateAsciiAtom("scalarRRRRNR"); static final Atom scalarNNNNRR = Atom.findOrCreateAsciiAtom("scalarNNNNRR"); static final Atom scalarRNNNRR = Atom.findOrCreateAsciiAtom("scalarRNNNRR"); static final Atom scalarNRNNRR = Atom.findOrCreateAsciiAtom("scalarNRNNRR"); static final Atom scalarRRNNRR = Atom.findOrCreateAsciiAtom("scalarRRNNRR"); static final Atom scalarNNRNRR = Atom.findOrCreateAsciiAtom("scalarNNRNRR"); static final Atom scalarRNRNRR = Atom.findOrCreateAsciiAtom("scalarRNRNRR"); static final Atom scalarNRRNRR = Atom.findOrCreateAsciiAtom("scalarNRRNRR"); static final Atom scalarRRRNRR = Atom.findOrCreateAsciiAtom("scalarRRRNRR"); static final Atom scalarNNNRRR = Atom.findOrCreateAsciiAtom("scalarNNNRRR"); static final Atom scalarRNNRRR = Atom.findOrCreateAsciiAtom("scalarRNNRRR"); static final Atom scalarNRNRRR = Atom.findOrCreateAsciiAtom("scalarNRNRRR"); static final Atom scalarRRNRRR = Atom.findOrCreateAsciiAtom("scalarRRNRRR"); static final Atom scalarNNRRRR = Atom.findOrCreateAsciiAtom("scalarNNRRRR"); static final Atom scalarRNRRRR = Atom.findOrCreateAsciiAtom("scalarRNRRRR"); static final Atom scalarNRRRRR = Atom.findOrCreateAsciiAtom("scalarNRRRRR"); static final Atom scalarRRRRRR = Atom.findOrCreateAsciiAtom("scalarRRRRRR"); } // CHECKSTYLE:OFF public static void scalarRNNNNN(Object object, TransitiveClosure trace) { pattern(1, object, trace); } public static void scalarNRNNNN(Object object, TransitiveClosure trace) { pattern(2, object, trace); } public static void scalarRRNNNN(Object object, TransitiveClosure trace) { pattern(3, object, trace); } public static void scalarNNRNNN(Object object, TransitiveClosure trace) { pattern(4, object, trace); } public static void scalarRNRNNN(Object object, TransitiveClosure trace) { pattern(5, object, trace); } public static void scalarNRRNNN(Object object, TransitiveClosure trace) { pattern(6, object, trace); } public static void scalarRRRNNN(Object object, TransitiveClosure trace) { pattern(7, object, trace); } public static void scalarNNNRNN(Object object, TransitiveClosure trace) { pattern(8, object, trace); } public static void scalarRNNRNN(Object object, TransitiveClosure trace) { pattern(9, object, trace); } public static void scalarNRNRNN(Object object, TransitiveClosure trace) { pattern(10, object, trace); } public static void scalarRRNRNN(Object object, TransitiveClosure trace) { pattern(11, object, trace); } public static void scalarNNRRNN(Object object, TransitiveClosure trace) { pattern(12, object, trace); } public static void scalarRNRRNN(Object object, TransitiveClosure trace) { pattern(13, object, trace); } public static void scalarNRRRNN(Object object, TransitiveClosure trace) { pattern(14, object, trace); } public static void scalarRRRRNN(Object object, TransitiveClosure trace) { pattern(15, object, trace); } public static void scalarNNNNRN(Object object, TransitiveClosure trace) { pattern(16, object, trace); } public static void scalarRNNNRN(Object object, TransitiveClosure trace) { pattern(17, object, trace); } public static void scalarNRNNRN(Object object, TransitiveClosure trace) { pattern(18, object, trace); } public static void scalarRRNNRN(Object object, TransitiveClosure trace) { pattern(19, object, trace); } public static void scalarNNRNRN(Object object, TransitiveClosure trace) { pattern(20, object, trace); } public static void scalarRNRNRN(Object object, TransitiveClosure trace) { pattern(21, object, trace); } public static void scalarNRRNRN(Object object, TransitiveClosure trace) { pattern(22, object, trace); } public static void scalarRRRNRN(Object object, TransitiveClosure trace) { pattern(23, object, trace); } public static void scalarNNNRRN(Object object, TransitiveClosure trace) { pattern(24, object, trace); } public static void scalarRNNRRN(Object object, TransitiveClosure trace) { pattern(25, object, trace); } public static void scalarNRNRRN(Object object, TransitiveClosure trace) { pattern(26, object, trace); } public static void scalarRRNRRN(Object object, TransitiveClosure trace) { pattern(27, object, trace); } public static void scalarNNRRRN(Object object, TransitiveClosure trace) { pattern(28, object, trace); } public static void scalarRNRRRN(Object object, TransitiveClosure trace) { pattern(29, object, trace); } public static void scalarNRRRRN(Object object, TransitiveClosure trace) { pattern(30, object, trace); } public static void scalarRRRRRN(Object object, TransitiveClosure trace) { pattern(31, object, trace); } public static void scalarNNNNNR(Object object, TransitiveClosure trace) { pattern(32, object, trace); } public static void scalarRNNNNR(Object object, TransitiveClosure trace) { pattern(33, object, trace); } public static void scalarNRNNNR(Object object, TransitiveClosure trace) { pattern(34, object, trace); } public static void scalarRRNNNR(Object object, TransitiveClosure trace) { pattern(35, object, trace); } public static void scalarNNRNNR(Object object, TransitiveClosure trace) { pattern(36, object, trace); } public static void scalarRNRNNR(Object object, TransitiveClosure trace) { pattern(37, object, trace); } public static void scalarNRRNNR(Object object, TransitiveClosure trace) { pattern(38, object, trace); } public static void scalarRRRNNR(Object object, TransitiveClosure trace) { pattern(39, object, trace); } public static void scalarNNNRNR(Object object, TransitiveClosure trace) { pattern(40, object, trace); } public static void scalarRNNRNR(Object object, TransitiveClosure trace) { pattern(41, object, trace); } public static void scalarNRNRNR(Object object, TransitiveClosure trace) { pattern(42, object, trace); } public static void scalarRRNRNR(Object object, TransitiveClosure trace) { pattern(43, object, trace); } public static void scalarNNRRNR(Object object, TransitiveClosure trace) { pattern(44, object, trace); } public static void scalarRNRRNR(Object object, TransitiveClosure trace) { pattern(45, object, trace); } public static void scalarNRRRNR(Object object, TransitiveClosure trace) { pattern(46, object, trace); } public static void scalarRRRRNR(Object object, TransitiveClosure trace) { pattern(47, object, trace); } public static void scalarNNNNRR(Object object, TransitiveClosure trace) { pattern(48, object, trace); } public static void scalarRNNNRR(Object object, TransitiveClosure trace) { pattern(49, object, trace); } public static void scalarNRNNRR(Object object, TransitiveClosure trace) { pattern(50, object, trace); } public static void scalarRRNNRR(Object object, TransitiveClosure trace) { pattern(51, object, trace); } public static void scalarNNRNRR(Object object, TransitiveClosure trace) { pattern(52, object, trace); } public static void scalarRNRNRR(Object object, TransitiveClosure trace) { pattern(53, object, trace); } public static void scalarNRRNRR(Object object, TransitiveClosure trace) { pattern(54, object, trace); } public static void scalarRRRNRR(Object object, TransitiveClosure trace) { pattern(55, object, trace); } public static void scalarNNNRRR(Object object, TransitiveClosure trace) { pattern(56, object, trace); } public static void scalarRNNRRR(Object object, TransitiveClosure trace) { pattern(57, object, trace); } public static void scalarNRNRRR(Object object, TransitiveClosure trace) { pattern(58, object, trace); } public static void scalarRRNRRR(Object object, TransitiveClosure trace) { pattern(59, object, trace); } public static void scalarNNRRRR(Object object, TransitiveClosure trace) { pattern(60, object, trace); } public static void scalarRNRRRR(Object object, TransitiveClosure trace) { pattern(61, object, trace); } public static void scalarNRRRRR(Object object, TransitiveClosure trace) { pattern(62, object, trace); } public static void scalarRRRRRR(Object object, TransitiveClosure trace) { pattern(63, object, trace); } // CHECKSTYLE:ON }
/** * Create a method for reflectively invoking this method * * @param reflectionClass the class this method will belong to * @param constantPool for the class * @param memRef the member reference corresponding to this method * @return the created method */ RVMMethod createReflectionMethod( TypeReference reflectionClass, int[] constantPool, MethodReference memRef) { TypeReference[] parameters = getParameterTypes(); int numParams = parameters.length; byte[] bytecodes; boolean interfaceCall = false; int curBC = 0; if (!isStatic()) { if (!getDeclaringClass().isInterface()) { // virtual call bytecodes = new byte[8 * numParams + 8]; } else { // interface call bytecodes = new byte[8 * numParams + 10]; interfaceCall = true; } bytecodes[curBC] = JBC_aload_1; curBC++; } else { // static call bytecodes = new byte[8 * numParams + 7]; } for (int i = 0; i < numParams; i++) { if (parameters[i].isVoidType()) { bytecodes[curBC] = bytecodes[curBC + 1] = bytecodes[curBC + 2] = bytecodes[curBC + 3] = bytecodes[curBC + 4] = bytecodes[curBC + 5] = bytecodes[curBC + 6] = bytecodes[curBC + 7] = (byte) JBC_nop; continue; } bytecodes[curBC] = (byte) JBC_aload_2; bytecodes[curBC + 1] = (byte) JBC_sipush; bytecodes[curBC + 2] = (byte) (i >>> 8); bytecodes[curBC + 3] = (byte) i; bytecodes[curBC + 4] = (byte) JBC_aaload; if (!parameters[i].isPrimitiveType()) { bytecodes[curBC + 5] = (byte) JBC_checkcast; if (VM.VerifyAssertions) VM._assert(parameters[i].getId() != 0); constantPool[i + 1] = ClassFileReader.packCPEntry(CP_CLASS, parameters[i].getId()); bytecodes[curBC + 6] = (byte) ((i + 1) >>> 8); bytecodes[curBC + 7] = (byte) (i + 1); } else if (parameters[i].isWordLikeType()) { bytecodes[curBC + 5] = bytecodes[curBC + 6] = bytecodes[curBC + 7] = (byte) JBC_nop; } else { bytecodes[curBC + 5] = (byte) JBC_invokestatic; MemberReference unboxMethod; if (parameters[i].isBooleanType()) { unboxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("unboxAsBoolean"), Atom.findOrCreateUnicodeAtom("(Ljava/lang/Object;)Z")); } else if (parameters[i].isByteType()) { unboxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("unboxAsByte"), Atom.findOrCreateUnicodeAtom("(Ljava/lang/Object;)B")); } else if (parameters[i].isShortType()) { unboxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("unboxAsShort"), Atom.findOrCreateUnicodeAtom("(Ljava/lang/Object;)S")); } else if (parameters[i].isCharType()) { unboxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("unboxAsChar"), Atom.findOrCreateUnicodeAtom("(Ljava/lang/Object;)C")); } else if (parameters[i].isIntType()) { unboxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("unboxAsInt"), Atom.findOrCreateUnicodeAtom("(Ljava/lang/Object;)I")); } else if (parameters[i].isLongType()) { unboxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("unboxAsLong"), Atom.findOrCreateUnicodeAtom("(Ljava/lang/Object;)J")); } else if (parameters[i].isFloatType()) { unboxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("unboxAsFloat"), Atom.findOrCreateUnicodeAtom("(Ljava/lang/Object;)F")); } else { if (VM.VerifyAssertions) VM._assert(parameters[i].isDoubleType()); unboxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("unboxAsDouble"), Atom.findOrCreateUnicodeAtom("(Ljava/lang/Object;)D")); } constantPool[i + 1] = ClassFileReader.packCPEntry(CP_MEMBER, unboxMethod.getId()); bytecodes[curBC + 6] = (byte) ((i + 1) >>> 8); bytecodes[curBC + 7] = (byte) (i + 1); } curBC += 8; } if (isStatic()) { bytecodes[curBC] = (byte) JBC_invokestatic; } else if (isObjectInitializer() || isPrivate()) { bytecodes[curBC] = (byte) JBC_invokespecial; } else if (interfaceCall) { bytecodes[curBC] = (byte) JBC_invokeinterface; } else { bytecodes[curBC] = (byte) JBC_invokevirtual; } constantPool[numParams + 1] = ClassFileReader.packCPEntry(CP_MEMBER, getId()); bytecodes[curBC + 1] = (byte) ((numParams + 1) >>> 8); bytecodes[curBC + 2] = (byte) (numParams + 1); if (interfaceCall) { // invokeinterface bytecodes are historically longer than others curBC += 2; } TypeReference returnType = getReturnType(); if (!returnType.isPrimitiveType() || returnType.isWordLikeType()) { bytecodes[curBC + 3] = (byte) JBC_nop; bytecodes[curBC + 4] = (byte) JBC_nop; bytecodes[curBC + 5] = (byte) JBC_nop; } else if (returnType.isVoidType()) { bytecodes[curBC + 3] = (byte) JBC_aconst_null; bytecodes[curBC + 4] = (byte) JBC_nop; bytecodes[curBC + 5] = (byte) JBC_nop; } else { MemberReference boxMethod; if (returnType.isBooleanType()) { boxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("boxAsBoolean"), Atom.findOrCreateUnicodeAtom("(Z)Ljava/lang/Object;")); } else if (returnType.isByteType()) { boxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("boxAsByte"), Atom.findOrCreateUnicodeAtom("(B)Ljava/lang/Object;")); } else if (returnType.isShortType()) { boxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("boxAsShort"), Atom.findOrCreateUnicodeAtom("(S)Ljava/lang/Object;")); } else if (returnType.isCharType()) { boxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("boxAsChar"), Atom.findOrCreateUnicodeAtom("(C)Ljava/lang/Object;")); } else if (returnType.isIntType()) { boxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("boxAsInt"), Atom.findOrCreateUnicodeAtom("(I)Ljava/lang/Object;")); } else if (returnType.isLongType()) { boxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("boxAsLong"), Atom.findOrCreateUnicodeAtom("(J)Ljava/lang/Object;")); } else if (returnType.isFloatType()) { boxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("boxAsFloat"), Atom.findOrCreateUnicodeAtom("(F)Ljava/lang/Object;")); } else { if (VM.VerifyAssertions) VM._assert(returnType.isDoubleType()); boxMethod = MethodReference.findOrCreate( baseReflectionClass, Atom.findOrCreateUnicodeAtom("boxAsDouble"), Atom.findOrCreateUnicodeAtom("(D)Ljava/lang/Object;")); } constantPool[numParams + 2] = ClassFileReader.packCPEntry(CP_MEMBER, boxMethod.getId()); bytecodes[curBC + 3] = (byte) JBC_invokestatic; bytecodes[curBC + 4] = (byte) ((numParams + 2) >>> 8); bytecodes[curBC + 5] = (byte) (numParams + 2); } bytecodes[curBC + 6] = (byte) JBC_areturn; return new NormalMethod( reflectionClass, memRef, (short) (ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC), null, (short) 3, (short) (getParameterWords() + 2), bytecodes, null, null, null, constantPool, null, null, null, null); }
/** * Called from {@link ClassFileReader#readClass(TypeReference,DataInputStream)} to create an * instance of a RVMMethod by reading the relevant data from the argument bytecode stream. * * @param declaringClass the TypeReference of the class being loaded * @param constantPool the constantPool of the RVMClass object that's being constructed * @param memRef the canonical memberReference for this member. * @param modifiers modifiers associated with this member. * @param input the DataInputStream to read the method's attributes from */ static RVMMethod readMethod( TypeReference declaringClass, int[] constantPool, MemberReference memRef, short modifiers, DataInputStream input) throws IOException { short tmp_localWords = 0; short tmp_operandWords = 0; byte[] tmp_bytecodes = null; ExceptionHandlerMap tmp_exceptionHandlerMap = null; TypeReference[] tmp_exceptionTypes = null; int[] tmp_lineNumberMap = null; LocalVariableTable tmp_localVariableTable = null; Atom tmp_signature = null; RVMAnnotation[] annotations = null; RVMAnnotation[][] parameterAnnotations = null; Object tmp_annotationDefault = null; // Read the attributes for (int i = 0, n = input.readUnsignedShort(); i < n; i++) { Atom attName = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); int attLength = input.readInt(); // Only bother to interpret non-boring Method attributes if (attName == RVMClassLoader.codeAttributeName) { tmp_operandWords = input.readShort(); tmp_localWords = input.readShort(); tmp_bytecodes = new byte[input.readInt()]; input.readFully(tmp_bytecodes); tmp_exceptionHandlerMap = ExceptionHandlerMap.readExceptionHandlerMap(input, constantPool); // Read the attributes portion of the code attribute for (int j = 0, n2 = input.readUnsignedShort(); j < n2; j++) { attName = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); attLength = input.readInt(); if (attName == RVMClassLoader.lineNumberTableAttributeName) { int cnt = input.readUnsignedShort(); if (cnt != 0) { tmp_lineNumberMap = new int[cnt]; for (int k = 0; k < cnt; k++) { int startPC = input.readUnsignedShort(); int lineNumber = input.readUnsignedShort(); tmp_lineNumberMap[k] = (lineNumber << BITS_IN_SHORT) | startPC; } } } else if (attName == RVMClassLoader.localVariableTableAttributeName) { tmp_localVariableTable = LocalVariableTable.readLocalVariableTable(input, constantPool); } else { // All other entries in the attribute portion of the code attribute are boring. int skippedAmount = input.skipBytes(attLength); if (skippedAmount != attLength) { throw new IOException("Unexpected short skip"); } } } } else if (attName == RVMClassLoader.exceptionsAttributeName) { int cnt = input.readUnsignedShort(); if (cnt != 0) { tmp_exceptionTypes = new TypeReference[cnt]; for (int j = 0, m = tmp_exceptionTypes.length; j < m; ++j) { tmp_exceptionTypes[j] = ClassFileReader.getTypeRef(constantPool, input.readUnsignedShort()); } } } else if (attName == RVMClassLoader.syntheticAttributeName) { modifiers |= ACC_SYNTHETIC; } else if (attName == RVMClassLoader.signatureAttributeName) { tmp_signature = ClassFileReader.getUtf(constantPool, input.readUnsignedShort()); } else if (attName == RVMClassLoader.runtimeVisibleAnnotationsAttributeName) { annotations = AnnotatedElement.readAnnotations(constantPool, input, declaringClass.getClassLoader()); } else if (attName == RVMClassLoader.runtimeVisibleParameterAnnotationsAttributeName) { int numParameters = input.readByte() & 0xFF; parameterAnnotations = new RVMAnnotation[numParameters][]; for (int a = 0; a < numParameters; ++a) { parameterAnnotations[a] = AnnotatedElement.readAnnotations( constantPool, input, declaringClass.getClassLoader()); } } else if (attName == RVMClassLoader.annotationDefaultAttributeName) { try { tmp_annotationDefault = RVMAnnotation.readValue( memRef.asMethodReference().getReturnType(), constantPool, input, declaringClass.getClassLoader()); } catch (ClassNotFoundException e) { throw new Error(e); } } else { // all other method attributes are boring int skippedAmount = input.skipBytes(attLength); if (skippedAmount != attLength) { throw new IOException("Unexpected short skip"); } } } RVMMethod method; if ((modifiers & ACC_NATIVE) != 0) { method = new NativeMethod( declaringClass, memRef, modifiers, tmp_exceptionTypes, tmp_signature, annotations, parameterAnnotations, tmp_annotationDefault); } else if ((modifiers & ACC_ABSTRACT) != 0) { method = new AbstractMethod( declaringClass, memRef, modifiers, tmp_exceptionTypes, tmp_signature, annotations, parameterAnnotations, tmp_annotationDefault); } else { method = new NormalMethod( declaringClass, memRef, modifiers, tmp_exceptionTypes, tmp_localWords, tmp_operandWords, tmp_bytecodes, tmp_exceptionHandlerMap, tmp_lineNumberMap, tmp_localVariableTable, constantPool, tmp_signature, annotations, parameterAnnotations, tmp_annotationDefault); } return method; }
/** * Do a quick pass over the IR, and return types that are candidates for redundant load * elimination. Algorithm: return those types T where 1) there's a load L(i) of type T 2) there's * another load or store M(j) of type T, M!=L and V(i) == V(j) * * <p>The result contains objects of type RVMField and TypeReference, whose narrowest common * ancestor is Object. */ @SuppressWarnings("unchecked") public static HashSet<Object> getCandidates(IR ir) { GlobalValueNumberState valueNumbers = ir.HIRInfo.valueNumbers; // which types have we seen loads for? HashSet<Object> seenLoad = new HashSet<Object>(10); // which static fields have we seen stores for? HashSet<RVMField> seenStore = new HashSet<RVMField>(10); HashSet<Object> resultSet = new HashSet<Object>(10); HashSet<FieldReference> forbidden = new HashSet<FieldReference>(10); // for each type T, indices(T) gives the set of value number (pairs) // that identify the indices seen in memory accesses to type T. HashMap indices = new HashMap(10); for (Enumeration be = ir.getBasicBlocks(); be.hasMoreElements(); ) { BasicBlock bb = (BasicBlock) be.nextElement(); if (!ir.options.FREQ_FOCUS_EFFORT || !bb.getInfrequent()) { for (InstructionEnumeration e = bb.forwardInstrEnumerator(); e.hasMoreElements(); ) { Instruction s = e.next(); switch (s.operator().opcode) { case GETFIELD_opcode: { Operand ref = GetField.getRef(s); FieldReference fr = GetField.getLocation(s).getFieldRef(); RVMField f = fr.peekResolvedField(); if (f == null) { forbidden.add(fr); } else { HashSet<Integer> numbers = findOrCreateIndexSet(indices, f); int v = valueNumbers.getValueNumber(ref); Integer V = v; if (numbers.contains(V)) { resultSet.add(f); } else { numbers.add(V); } seenLoad.add(f); } } break; case PUTFIELD_opcode: { Operand ref = PutField.getRef(s); FieldReference fr = PutField.getLocation(s).getFieldRef(); RVMField f = fr.peekResolvedField(); if (f == null) { forbidden.add(fr); } else { HashSet<Integer> numbers = findOrCreateIndexSet(indices, f); int v = valueNumbers.getValueNumber(ref); Integer V = v; if (numbers.contains(V)) { if (seenLoad.contains(f)) { resultSet.add(f); } } else { numbers.add(V); } } } break; case GETSTATIC_opcode: { FieldReference fr = GetStatic.getLocation(s).getFieldRef(); RVMField f = fr.peekResolvedField(); if (f == null) { forbidden.add(fr); } else { if (seenLoad.contains(f) || seenStore.contains(f)) { resultSet.add(f); } seenLoad.add(f); } } break; case PUTSTATIC_opcode: { FieldReference fr = PutStatic.getLocation(s).getFieldRef(); RVMField f = fr.peekResolvedField(); if (f == null) { forbidden.add(fr); } else { if (seenLoad.contains(f)) { resultSet.add(f); } seenStore.add(f); } } break; case INT_ALOAD_opcode: case LONG_ALOAD_opcode: case FLOAT_ALOAD_opcode: case DOUBLE_ALOAD_opcode: case REF_ALOAD_opcode: case BYTE_ALOAD_opcode: case UBYTE_ALOAD_opcode: case USHORT_ALOAD_opcode: case SHORT_ALOAD_opcode: { Operand ref = ALoad.getArray(s); TypeReference type = ref.getType(); if (type.isArrayType()) { if (!type.getArrayElementType().isPrimitiveType()) { type = TypeReference.JavaLangObjectArray; } } Operand index = ALoad.getIndex(s); HashSet<ValueNumberPair> numbers = findOrCreateIndexSet(indices, type); int v1 = valueNumbers.getValueNumber(ref); int v2 = valueNumbers.getValueNumber(index); ValueNumberPair V = new ValueNumberPair(v1, v2); if (numbers.contains(V)) { resultSet.add(type); } else { numbers.add(V); } seenLoad.add(type); } break; case INT_ASTORE_opcode: case LONG_ASTORE_opcode: case FLOAT_ASTORE_opcode: case DOUBLE_ASTORE_opcode: case REF_ASTORE_opcode: case BYTE_ASTORE_opcode: case SHORT_ASTORE_opcode: { Operand ref = AStore.getArray(s); TypeReference type = ref.getType(); if (type.isArrayType()) { if (!type.getArrayElementType().isPrimitiveType()) { type = TypeReference.JavaLangObjectArray; } } Operand index = AStore.getIndex(s); HashSet<ValueNumberPair> numbers = findOrCreateIndexSet(indices, type); int v1 = valueNumbers.getValueNumber(ref); int v2 = valueNumbers.getValueNumber(index); ValueNumberPair V = new ValueNumberPair(v1, v2); if (numbers.contains(V)) { if (seenLoad.contains(type)) { resultSet.add(type); } } else { numbers.add(V); } } break; default: break; } } } } // If we have found an unresolved field reference, then conservatively // remove all fields that it might refer to from the resultSet. for (final FieldReference fieldReference : forbidden) { for (Iterator i2 = resultSet.iterator(); i2.hasNext(); ) { Object it = i2.next(); if (it instanceof RVMField) { final RVMField field = (RVMField) it; if (!fieldReference.definitelyDifferent(field.getMemberRef().asFieldReference())) { i2.remove(); } } } } return resultSet; }
public Class<?> getDeclaringClass() { if (!type.isClassType()) return null; TypeReference dc = type.asClass().getDeclaringClass(); if (dc == null) return null; return dc.resolve().getClassForType(); }