/**
  * Find or create an interface method signature for the given method reference.
  *
  * @param ref A reference to a supposed interface method
  * @return the interface method signature
  */
 public static synchronized InterfaceMethodSignature findOrCreate(MemberReference ref) {
   InterfaceMethodSignature key =
       new InterfaceMethodSignature(ref.getName(), ref.getDescriptor(), nextId + 1);
   InterfaceMethodSignature val = dictionary.get(key);
   if (val != null) return val;
   nextId++;
   dictionary.add(key);
   return key;
 }
예제 #2
0
 /** Find the value for an annotation */
 private Object getElementValue(String name, Class<?> valueType) {
   for (AnnotationMember evp : elementValuePairs) {
     String evpFieldName = evp.getName().toString();
     if (name.equals(evpFieldName)) {
       return evp.getValue();
     }
   }
   MethodReference methRef =
       MemberReference.findOrCreate(
               type,
               Atom.findOrCreateAsciiAtom(name),
               Atom.findOrCreateAsciiAtom("()" + TypeReference.findOrCreate(valueType).getName()))
           .asMethodReference();
   try {
     return methRef.resolve().getAnnotationDefault();
   } catch (Throwable t) {
     return NO_VALUE;
   }
 }
예제 #3
0
 /**
  * Read the pair from the input stream and create object
  *
  * @param constantPool the constant pool for the class being read
  * @param input stream to read from
  * @param classLoader the class loader being used to load this annotation
  * @return a newly created annotation member
  */
 static AnnotationMember readAnnotationMember(
     TypeReference type, int[] constantPool, DataInputStream input, ClassLoader classLoader)
     throws IOException, ClassNotFoundException {
   // Read name of pair
   int elemNameIndex = input.readUnsignedShort();
   Atom name = RVMClass.getUtf(constantPool, elemNameIndex);
   MethodReference meth;
   Object value;
   if (type.isResolved()) {
     meth = type.resolve().asClass().findDeclaredMethod(name).getMemberRef().asMethodReference();
     value = RVMAnnotation.readValue(meth.getReturnType(), constantPool, input, classLoader);
   } else {
     value = RVMAnnotation.readValue(null, constantPool, input, classLoader);
     meth =
         MemberReference.findOrCreate(
                 type,
                 name,
                 Atom.findOrCreateAsciiAtom(
                     "()" + TypeReference.findOrCreate(value.getClass()).getName()))
             .asMethodReference();
   }
   return new AnnotationMember(meth, value);
 }
 /**
  * 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;
  }