jdk/src/share/classes/java/lang/invoke/MethodType.java
changeset 13423 17843fff200d
parent 13422 72b63ee33f57
child 13610 28122b96858e
--- a/jdk/src/share/classes/java/lang/invoke/MethodType.java	Thu Jul 12 00:12:52 2012 -0700
+++ b/jdk/src/share/classes/java/lang/invoke/MethodType.java	Tue Jul 24 10:47:44 2012 -0700
@@ -33,6 +33,7 @@
 import java.util.List;
 import sun.invoke.util.BytecodeDescriptor;
 import static java.lang.invoke.MethodHandleStatics.*;
+import sun.invoke.util.VerifyType;
 
 /**
  * A method type represents the arguments and return type accepted and
@@ -108,6 +109,8 @@
     /*trusted*/ Class<?> rtype() { return rtype; }
     /*trusted*/ Class<?>[] ptypes() { return ptypes; }
 
+    void setForm(MethodTypeForm f) { form = f; }
+
     private static void checkRtype(Class<?> rtype) {
         rtype.equals(rtype);  // null check
     }
@@ -127,7 +130,7 @@
         checkSlotCount(ptypes.length + slots);
         return slots;
     }
-    private static void checkSlotCount(int count) {
+    static void checkSlotCount(int count) {
         if ((count & 0xFF) != count)
             throw newIllegalArgumentException("bad parameter count "+count);
     }
@@ -238,8 +241,7 @@
             ptypes = NO_PTYPES; trusted = true;
         }
         MethodType mt1 = new MethodType(rtype, ptypes);
-        MethodType mt0;
-        mt0 = internTable.get(mt1);
+        MethodType mt0 = internTable.get(mt1);
         if (mt0 != null)
             return mt0;
         if (!trusted)
@@ -248,10 +250,6 @@
         // promote the object to the Real Thing, and reprobe
         MethodTypeForm form = MethodTypeForm.findForm(mt1);
         mt1.form = form;
-        if (form.erasedType == mt1) {
-            // This is a principal (erased) type; show it to the JVM.
-            MethodHandleNatives.init(mt1);
-        }
         return internTable.add(mt1);
     }
     private static final MethodType[] objectOnlyTypes = new MethodType[20];
@@ -385,6 +383,32 @@
         return insertParameterTypes(parameterCount(), ptypesToInsert);
     }
 
+     /**
+     * Finds or creates a method type with modified parameter types.
+     * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+     * @param start  the position (zero-based) of the first replaced parameter type(s)
+     * @param end    the position (zero-based) after the last replaced parameter type(s)
+     * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
+     * @return the same type, except with the selected parameter(s) replaced
+     * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
+     *                                  or if {@code end} is negative or greater than {@code parameterCount()}
+     *                                  or if {@code start} is greater than {@code end}
+     * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
+     *                                  or if the resulting method type would have more than 255 parameter slots
+     * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
+     */
+    /*non-public*/ MethodType replaceParameterTypes(int start, int end, Class<?>... ptypesToInsert) {
+        if (start == end)
+            return insertParameterTypes(start, ptypesToInsert);
+        int len = ptypes.length;
+        if (!(0 <= start && start <= end && end <= len))
+            throw newIndexOutOfBoundsException("start="+start+" end="+end);
+        int ilen = ptypesToInsert.length;
+        if (ilen == 0)
+            return dropParameterTypes(start, end);
+        return dropParameterTypes(start, end).insertParameterTypes(start, ptypesToInsert);
+    }
+
     /**
      * Finds or creates a method type with some parameter types omitted.
      * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
@@ -465,6 +489,23 @@
     }
 
     /**
+     * Erases all reference types to {@code Object}, and all subword types to {@code int}.
+     * This is the reduced type polymorphism used by private methods
+     * such as {@link MethodHandle#invokeBasic invokeBasic}.
+     * @return a version of the original type with all reference and subword types replaced
+     */
+    /*non-public*/ MethodType basicType() {
+        return form.basicType();
+    }
+
+    /**
+     * @return a version of the original type with MethodHandle prepended as the first argument
+     */
+    /*non-public*/ MethodType invokerType() {
+        return insertParameterTypes(0, MethodHandle.class);
+    }
+
+    /**
      * Converts all types, both reference and primitive, to {@code Object}.
      * Convenience method for {@link #genericMethodType(int) genericMethodType}.
      * The expression {@code type.wrap().erase()} produces the same value
@@ -558,6 +599,11 @@
         return Collections.unmodifiableList(Arrays.asList(ptypes));
     }
 
+    /*non-public*/ Class<?> lastParameterType() {
+        int len = ptypes.length;
+        return len == 0 ? void.class : ptypes[len-1];
+    }
+
     /**
      * Presents the parameter types as an array (a convenience method).
      * Changes to the array will not result in changes to the type.
@@ -627,6 +673,26 @@
 
 
     /*non-public*/
+    boolean isViewableAs(MethodType newType) {
+        if (!VerifyType.isNullConversion(returnType(), newType.returnType()))
+            return false;
+        int argc = parameterCount();
+        if (argc != newType.parameterCount())
+            return false;
+        for (int i = 0; i < argc; i++) {
+            if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i)))
+                return false;
+        }
+        return true;
+    }
+    /*non-public*/
+    boolean isCastableTo(MethodType newType) {
+        int argc = parameterCount();
+        if (argc != newType.parameterCount())
+            return false;
+        return true;
+    }
+    /*non-public*/
     boolean isConvertibleTo(MethodType newType) {
         if (!canConvert(returnType(), newType.returnType()))
             return false;
@@ -809,6 +875,10 @@
         return BytecodeDescriptor.unparse(this);
     }
 
+    /*non-public*/ static String toFieldDescriptorString(Class<?> cls) {
+        return BytecodeDescriptor.unparse(cls);
+    }
+
     /// Serialization.
 
     /**
@@ -881,18 +951,17 @@
         // store them into the implementation-specific final fields.
         checkRtype(rtype);
         checkPtypes(ptypes);
-        unsafe.putObject(this, rtypeOffset, rtype);
-        unsafe.putObject(this, ptypesOffset, ptypes);
+        UNSAFE.putObject(this, rtypeOffset, rtype);
+        UNSAFE.putObject(this, ptypesOffset, ptypes);
     }
 
     // Support for resetting final fields while deserializing
-    private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
     private static final long rtypeOffset, ptypesOffset;
     static {
         try {
-            rtypeOffset = unsafe.objectFieldOffset
+            rtypeOffset = UNSAFE.objectFieldOffset
                 (MethodType.class.getDeclaredField("rtype"));
-            ptypesOffset = unsafe.objectFieldOffset
+            ptypesOffset = UNSAFE.objectFieldOffset
                 (MethodType.class.getDeclaredField("ptypes"));
         } catch (Exception ex) {
             throw new Error(ex);