/** Are two annotations equal? */ private boolean annotationEquals(Annotation a, Annotation b) { if (a == b) { return true; } else if (a.getClass() != b.getClass()) { return false; } else { RVMClass annotationInterface = type.resolve().asClass(); RVMMethod[] annotationMethods = annotationInterface.getDeclaredMethods(); AnnotationFactory afB = (AnnotationFactory) Proxy.getInvocationHandler(b); try { for (RVMMethod method : annotationMethods) { String name = method.getName().toUnicodeString(); Object objA = getElementValue(name, method.getReturnType().resolve().getClassForType()); Object objB = afB.getValue(name, method.getReturnType().resolve().getClassForType()); if (!objA.getClass().isArray()) { if (!objA.equals(objB)) { return false; } } else { if (!Arrays.equals((Object[]) objA, (Object[]) objB)) { return false; } } } } catch (java.io.UTFDataFormatException e) { throw new Error(e); } return true; } }
/** Is a finalizer method extended from Object: {@code protected void finalize()} */ @Pure public static boolean isFinalizer(final RVMMethod method) { if (!method.isProtected()) return false; // is the method name "finalize" byte[] name = method.getName().getBytes(); if (name.length != 8) return false; // is the desc "()V"? byte[] desc = method.getDescriptor().getBytes(); if (desc.length != 3) return false; if (name[0] != 'f' || name[1] != 'i' || name[2] != 'n' || name[3] != 'a' || name[4] != 'l' || name[5] != 'i' || name[6] != 'z' || name[7] != 'e' || desc[8] != '(' || desc[9] != ')' || desc[10] != 'V') return false; return true; }
private boolean match(RVMMethod method) { if (excludePattern == null) return true; RVMClass cls = method.getDeclaringClass(); String clsName = cls.toString(); if (clsName.compareTo("org.jikesrvm.compilers.opt.runtimesupport.OptSaveVolatile") == 0) return true; String methodName = method.getName().toString(); String fullName = clsName + "." + methodName; return (fullName.indexOf(excludePattern)) < 0; }
public Method[] getDeclaredMethods() throws SecurityException { checkMemberAccess(Member.DECLARED); if (!type.isClassType()) return new Method[0]; RVMMethod[] methods = type.asClass().getDeclaredMethods(); ArrayList<Method> coll = new ArrayList<Method>(methods.length); for (RVMMethod meth : methods) { if (!meth.isClassInitializer() && !meth.isObjectInitializer()) { coll.add(JikesRVMSupport.createMethod(meth)); } } return coll.toArray(new Method[coll.size()]); }
@Pure private RVMMethod getDefaultConstructor() { if (this.defaultConstructor == null) { RVMMethod defaultConstructor = null; RVMMethod[] methods = type.asClass().getConstructorMethods(); for (RVMMethod method : methods) { if (method.getParameterTypes().length == 0) { defaultConstructor = method; break; } } this.defaultConstructor = defaultConstructor; } return this.defaultConstructor; }
public Constructor<?>[] getConstructors() throws SecurityException { checkMemberAccess(Member.PUBLIC); if (!type.isClassType()) return new Constructor[0]; RVMMethod[] methods = type.asClass().getConstructorMethods(); ArrayList<Constructor<T>> coll = new ArrayList<Constructor<T>>(methods.length); for (RVMMethod method : methods) { if (method.isPublic()) { @SuppressWarnings("unchecked") Constructor<T> x = (Constructor<T>) JikesRVMSupport.createConstructor(method); coll.add(x); } } return coll.toArray(new Constructor[coll.size()]); }
/* generate yieldpoint without checking threadSwith request */ private static void expandUnconditionalYieldpoint(Instruction s, IR ir, RVMMethod meth) { // split the basic block after the yieldpoint, create a new // block at the end of the IR to hold the yieldpoint, // remove the yieldpoint (to prepare to out it in the new block at the end) BasicBlock thisBlock = s.getBasicBlock(); BasicBlock nextBlock = thisBlock.splitNodeWithLinksAt(s, ir); BasicBlock yieldpoint = thisBlock.createSubBlock(s.getBytecodeIndex(), ir); thisBlock.insertOut(yieldpoint); yieldpoint.insertOut(nextBlock); ir.cfg.addLastInCodeOrder(yieldpoint); s.remove(); // change thread switch instruction into call to thread switch routine // NOTE: must make s the call instruction: it is the GC point! // must also inform the GCMap that s has been moved!!! Offset offset = meth.getOffset(); LocationOperand loc = new LocationOperand(offset); Operand guard = TG(); Operand target = MemoryOperand.D(Magic.getTocPointer().plus(offset), (byte) 4, loc, guard); MIR_Call.mutate0(s, CALL_SAVE_VOLATILE, null, null, target, MethodOperand.STATIC(meth)); yieldpoint.appendInstruction(s); ir.MIRInfo.gcIRMap.moveToEnd(s); yieldpoint.appendInstruction(MIR_Branch.create(IA32_JMP, nextBlock.makeJumpTarget())); // make a jump to yield block thisBlock.appendInstruction(MIR_Branch.create(IA32_JMP, yieldpoint.makeJumpTarget())); }
/** * Create a copy of the method that occurs in the annotation interface. The method body will * contain a read of the field at the constant pool index specified. * * @param annotationClass the class this method belongs to * @param constantPool for the class * @param memRef the member reference corresponding to this method * @param interfaceMethod the interface method that will copied to produce the annotation method * @param constantPoolIndex the index of the field that will be returned by this method * @return the created method */ static RVMMethod createAnnotationMethod( TypeReference annotationClass, int[] constantPool, MemberReference memRef, RVMMethod interfaceMethod, int constantPoolIndex) { byte[] bytecodes = new byte[] { (byte) JBC_aload_0, (byte) JBC_getfield, (byte) (constantPoolIndex >>> 8), (byte) constantPoolIndex, // Xreturn (byte) typeRefToReturnBytecode(interfaceMethod.getReturnType()) }; return new NormalMethod( annotationClass, memRef, (short) (ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC), null, (short) 1, (short) 2, bytecodes, null, null, null, constantPool, null, null, null, null); }
Class<?>[] getExceptionTypes() { TypeReference[] exceptionTypes = method.getExceptionTypes(); if (exceptionTypes == null) { return new Class[0]; } else { return VMCommonLibrarySupport.typesToClasses(exceptionTypes); } }
// For use by JikesRVMSupport VMMethod(RVMMethod m) { method = m; if (Reflection.cacheInvokerInJavaLangReflect) { invoker = m.getInvoker(); } else { invoker = null; } }
public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED); if (!type.isClassType()) throwNoSuchMethodException(name, parameterTypes); if (name == null) { throwNoSuchMethodException(name, parameterTypes); } Atom aName = Atom.findOrCreateUnicodeAtom(name); if (aName == RVMClassLoader.StandardClassInitializerMethodName || aName == RVMClassLoader.StandardObjectInitializerMethodName) { // <init> and <clinit> are not methods. throwNoSuchMethodException(name, parameterTypes); } RVMMethod[] methods = type.asClass().getDeclaredMethods(); RVMMethod answer = null; for (RVMMethod meth : methods) { if (meth.getName() == aName && parametersMatch(meth.getParameterTypes(), parameterTypes)) { if (answer == null) { answer = meth; } else { RVMMethod m2 = meth; if (answer.getReturnType().resolve().isAssignableFrom(m2.getReturnType().resolve())) { answer = m2; } } } } if (answer == null) { throwNoSuchMethodException(name, parameterTypes); } return JikesRVMSupport.createMethod(answer); }
public Method[] getMethods() throws SecurityException { checkMemberAccess(Member.PUBLIC); RVMMethod[] static_methods = type.getStaticMethods(); RVMMethod[] virtual_methods = type.getVirtualMethods(); ArrayList<Method> coll = new ArrayList<Method>(static_methods.length + virtual_methods.length); for (RVMMethod meth : static_methods) { if (meth.isPublic()) { coll.add(JikesRVMSupport.createMethod(meth)); } } for (RVMMethod meth : virtual_methods) { if (meth.isPublic()) { coll.add(JikesRVMSupport.createMethod(meth)); } } return coll.toArray(new Method[coll.size()]); }
/** * Is this a special exception-raising method that must be invisible in stack traces? * * <p>In some configurations, the optimizing compiler may insert calls to special exception * raising methods in RuntimeEntrypoints if it recognizes that code throws unconditional * exceptions. Those calls must not appear in the stack trace. * * @param m a method * @return {@code true} when the given me is a special exception-raising method that must be * invisible in stack traces, {@code false} otherwise */ public static final boolean isInvisibleRaiseMethod(RVMMethod m) { if (!m.isRuntimeServiceMethod()) { return false; } NormalMethod nm = (NormalMethod) m; return nm == raiseAbstractMethodError || nm == raiseArithmeticException || nm == raiseArithmeticException || nm == raiseNullPointerException || nm == raiseIllegalAccessError; }
/** Hash code for annotation value */ private int annotationHashCode() { RVMClass annotationInterface = type.resolve().asClass(); RVMMethod[] annotationMethods = annotationInterface.getDeclaredMethods(); String typeString = type.toString(); int result = typeString.substring(1, typeString.length() - 1).hashCode(); try { for (RVMMethod method : annotationMethods) { String name = method.getName().toUnicodeString(); Object value = getElementValue(name, method.getReturnType().resolve().getClassForType()); int part_result = name.hashCode() * 127; if (value.getClass().isArray()) { if (value instanceof Object[]) { part_result ^= Arrays.hashCode((Object[]) value); } else if (value instanceof boolean[]) { part_result ^= Arrays.hashCode((boolean[]) value); } else if (value instanceof byte[]) { part_result ^= Arrays.hashCode((byte[]) value); } else if (value instanceof char[]) { part_result ^= Arrays.hashCode((char[]) value); } else if (value instanceof short[]) { part_result ^= Arrays.hashCode((short[]) value); } else if (value instanceof int[]) { part_result ^= Arrays.hashCode((int[]) value); } else if (value instanceof long[]) { part_result ^= Arrays.hashCode((long[]) value); } else if (value instanceof float[]) { part_result ^= Arrays.hashCode((float[]) value); } else if (value instanceof double[]) { part_result ^= Arrays.hashCode((double[]) value); } } else { part_result ^= value.hashCode(); } result += part_result; } } catch (java.io.UTFDataFormatException e) { throw new Error(e); } return result; }
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED); if (!type.isClassType()) throwNoSuchMethodException("<init>", parameterTypes); RVMMethod answer = null; if (parameterTypes == null || parameterTypes.length == 0) { answer = getDefaultConstructor(); } else { RVMMethod[] methods = type.asClass().getConstructorMethods(); for (RVMMethod method : methods) { if (parametersMatch(method.getParameterTypes(), parameterTypes)) { answer = method; break; } } } if (answer == null) { throwNoSuchMethodException("<init>", parameterTypes); } return JikesRVMSupport.createConstructor(answer); }
@Inline( value = Inline.When.ArgumentsAreConstant, arguments = {0}) public T newInstance() throws IllegalAccessException, InstantiationException, ExceptionInInitializerError, SecurityException { // Basic checks checkMemberAccess(Member.PUBLIC); if (!type.isClassType()) throw new InstantiationException(); RVMClass cls = type.asClass(); if (cls.isAbstract() || cls.isInterface()) throw new InstantiationException(); // Ensure that the class is initialized if (!cls.isInitialized()) { RuntimeEntrypoints.initializeClassForDynamicLink(cls); } // Find the defaultConstructor RVMMethod defaultConstructor = getDefaultConstructor(); if (defaultConstructor == null) throw new InstantiationException(); // Check that caller is allowed to access it if (!defaultConstructor.isPublic()) { RVMClass accessingClass = RVMClass.getClassFromStackFrame(1); VMCommonLibrarySupport.checkAccess(defaultConstructor, accessingClass); } // Allocate an uninitialized instance; @SuppressWarnings("unchecked") // yes, we're giving an anonymous object a type. T obj = (T) RuntimeEntrypoints.resolvedNewScalar(cls); // Run the default constructor on the it. Reflection.invoke(defaultConstructor, null, obj, null, true); return obj; }
@Pure private RVMMethod getMethodInternal2(Atom aName, Class<?>... parameterTypes) { RVMMethod answer = null; RVMMethod[] methods = type.asClass().getVirtualMethods(); for (RVMMethod meth : methods) { if (meth.getName() == aName && meth.isPublic() && parametersMatch(meth.getParameterTypes(), parameterTypes)) { if (answer == null) { answer = meth; } else { RVMMethod m2 = meth; if (answer.getReturnType().resolve().isAssignableFrom(m2.getReturnType().resolve())) { answer = m2; } } } } return answer; }
private static void expandYieldpoint( Instruction s, IR ir, RVMMethod meth, IA32ConditionOperand ypCond) { // split the basic block after the yieldpoint, create a new // block at the end of the IR to hold the yieldpoint, // remove the yieldpoint (to prepare to out it in the new block at the end) BasicBlock thisBlock = s.getBasicBlock(); BasicBlock nextBlock = thisBlock.splitNodeWithLinksAt(s, ir); BasicBlock yieldpoint = thisBlock.createSubBlock(s.getBytecodeIndex(), ir, 0); thisBlock.insertOut(yieldpoint); yieldpoint.insertOut(nextBlock); ir.cfg.addLastInCodeOrder(yieldpoint); s.remove(); // change thread switch instruction into call to thread switch routine // NOTE: must make s the call instruction: it is the GC point! // must also inform the GCMap that s has been moved!!! Offset offset = meth.getOffset(); LocationOperand loc = new LocationOperand(offset); Operand guard = TG(); Operand target; if (JTOC_REGISTER == null) { target = MemoryOperand.D(Magic.getTocPointer().plus(offset), (byte) 4, loc, guard); } else { target = MemoryOperand.BD(ir.regpool.makeTocOp().asRegister(), offset, (byte) 8, loc, guard); } MIR_Call.mutate0(s, CALL_SAVE_VOLATILE, null, null, target, MethodOperand.STATIC(meth)); yieldpoint.appendInstruction(s); ir.MIRInfo.gcIRMap.moveToEnd(s); yieldpoint.appendInstruction(MIR_Branch.create(IA32_JMP, nextBlock.makeJumpTarget())); // Check to see if threadSwitch requested Offset tsr = Entrypoints.takeYieldpointField.getOffset(); MemoryOperand M = MemoryOperand.BD(ir.regpool.makeTROp(), tsr, (byte) 4, null, null); thisBlock.appendInstruction(MIR_Compare.create(IA32_CMP, M, IC(0))); thisBlock.appendInstruction( MIR_CondBranch.create( IA32_JCC, ypCond, yieldpoint.makeJumpTarget(), BranchProfileOperand.never())); }
@Pure private RVMMethod getMethodInternal1(Atom aName, Class<?>... parameterTypes) { RVMMethod answer = null; for (RVMClass current = type.asClass(); current != null && answer == null; current = current.getSuperClass()) { RVMMethod[] methods = current.getDeclaredMethods(); for (RVMMethod meth : methods) { if (meth.getName() == aName && meth.isPublic() && parametersMatch(meth.getParameterTypes(), parameterTypes)) { if (answer == null) { answer = meth; } else { RVMMethod m2 = meth; if (answer.getReturnType().resolve().isAssignableFrom(m2.getReturnType().resolve())) { answer = m2; } } } } } return answer; }
Object getDefaultValue() { return method.getAnnotationDefault(); }
Annotation[][] getParameterAnnotations() { return method.getDeclaredParameterAnnotations(); }
public Class<?> getDeclaringClass() { return method.getDeclaringClass().getClassForType(); }
int getModifiersInternal() { return method.getModifiers(); }
public String getName() { return method.getName().toString(); }
Class<?>[] getParameterTypes() { return VMCommonLibrarySupport.typesToClasses(method.getParameterTypes()); }
Class<?> getReturnType() { return method.getReturnType().resolve().getClassForType(); }
Annotation[] getDeclaredAnnotations() { return method.getDeclaredAnnotations(); }
<T extends Annotation> T getAnnotation(Class<T> annotationClass) { return method.getAnnotation(annotationClass); }
String getSignature() { return method.getSignature().toString(); }