Merge jdk7-b99
authorjrose
Sat, 19 Jun 2010 01:14:40 -0700
changeset 24692587c9f0b60d
parent 2467 d742045bd30b
parent 2468 3d944ecfa470
child 2470 3956cdee6712
child 2538 861213cb02c3
Merge
src/share/classes/java/dyn/MethodHandles.java
src/share/classes/sun/dyn/MethodHandleNatives.java
src/share/javavm/export/classfile_constants.h
src/share/native/common/check_code.c
test/java/dyn/MethodHandlesTest.java
     1.1 --- a/src/share/classes/java/dyn/MethodHandles.java	Fri Jun 18 15:23:57 2010 -0700
     1.2 +++ b/src/share/classes/java/dyn/MethodHandles.java	Sat Jun 19 01:14:40 2010 -0700
     1.3 @@ -411,41 +411,68 @@
     1.4  
     1.5          /**
     1.6           * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
     1.7 -         * Produce a method handle giving read access to a field.
     1.8 +         * Produce a method handle giving read access to a non-static field.
     1.9           * The type of the method handle will have a return type of the field's
    1.10           * value type.
    1.11 -         * If the field is static, the method handle will take no arguments.
    1.12 -         * Otherwise, its single argument will be the instance containing
    1.13 +         * The method handle's single argument will be the instance containing
    1.14           * the field.
    1.15           * Access checking is performed immediately on behalf of the lookup class.
    1.16           * @param name the field's name
    1.17           * @param type the field's type
    1.18 -         * @param isStatic true if and only if the field is static
    1.19           * @return a method handle which can load values from the field
    1.20           * @exception NoAccessException if access checking fails
    1.21           */
    1.22 -        public MethodHandle findGetter(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoAccessException {
    1.23 -            return makeAccessor(refc, name, type, isStatic, false);
    1.24 +        public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
    1.25 +            return makeAccessor(refc, name, type, false, false);
    1.26          }
    1.27  
    1.28          /**
    1.29           * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
    1.30 -         * Produce a method handle giving write access to a reflected field.
    1.31 +         * Produce a method handle giving write access to a non-static field.
    1.32           * The type of the method handle will have a void return type.
    1.33 -         * If the field is static, the method handle will take a single
    1.34 -         * argument, of the field's value type, the value to be stored.
    1.35 -         * Otherwise, the two arguments will be the instance containing
    1.36 +         * The method handle will take two arguments, the instance containing
    1.37           * the field, and the value to be stored.
    1.38 +         * The second argument will be of the field's value type.
    1.39           * Access checking is performed immediately on behalf of the lookup class.
    1.40           * @param name the field's name
    1.41           * @param type the field's type
    1.42 -         * @param isStatic true if and only if the field is static
    1.43 -         * @return a method handle which can store values into the reflected field
    1.44 +         * @return a method handle which can store values into the field
    1.45           * @exception NoAccessException if access checking fails
    1.46           */
    1.47 -        public MethodHandle findSetter(Class<?> refc, String name, Class<?> type,
    1.48 -                                       boolean isStatic) throws NoAccessException {
    1.49 -            return makeAccessor(refc, name, type, isStatic, true);
    1.50 +        public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
    1.51 +            return makeAccessor(refc, name, type, false, true);
    1.52 +        }
    1.53 +
    1.54 +        /**
    1.55 +         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
    1.56 +         * Produce a method handle giving read access to a static field.
    1.57 +         * The type of the method handle will have a return type of the field's
    1.58 +         * value type.
    1.59 +         * The method handle will take no arguments.
    1.60 +         * Access checking is performed immediately on behalf of the lookup class.
    1.61 +         * @param name the field's name
    1.62 +         * @param type the field's type
    1.63 +         * @return a method handle which can load values from the field
    1.64 +         * @exception NoAccessException if access checking fails
    1.65 +         */
    1.66 +        public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
    1.67 +            return makeAccessor(refc, name, type, true, false);
    1.68 +        }
    1.69 +
    1.70 +        /**
    1.71 +         * <em>PROVISIONAL API, WORK IN PROGRESS:</em>
    1.72 +         * Produce a method handle giving write access to a static field.
    1.73 +         * The type of the method handle will have a void return type.
    1.74 +         * The method handle will take a single
    1.75 +         * argument, of the field's value type, the value to be stored.
    1.76 +         * Access checking is performed immediately on behalf of the lookup class.
    1.77 +         * @param name the field's name
    1.78 +         * @param type the field's type
    1.79 +         * @return a method handle which can store values into the field
    1.80 +         * @exception NoAccessException if access checking fails
    1.81 +         */
    1.82 +        public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoAccessException {
    1.83 +            return makeAccessor(refc, name, type, true, true);
    1.84          }
    1.85  
    1.86          /**
     2.1 --- a/src/share/classes/sun/dyn/MethodHandleNatives.java	Fri Jun 18 15:23:57 2010 -0700
     2.2 +++ b/src/share/classes/sun/dyn/MethodHandleNatives.java	Sat Jun 19 01:14:40 2010 -0700
     2.3 @@ -258,6 +258,20 @@
     2.4              //T_ARRAY    = 13
     2.5              T_VOID     = 14;
     2.6              //T_ADDRESS  = 15
     2.7 +
     2.8 +        /**
     2.9 +         * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries.
    2.10 +         */
    2.11 +        static final int
    2.12 +            REF_getField                = 1,
    2.13 +            REF_getStatic               = 2,
    2.14 +            REF_putField                = 3,
    2.15 +            REF_putStatic               = 4,
    2.16 +            REF_invokeVirtual           = 5,
    2.17 +            REF_invokeStatic            = 6,
    2.18 +            REF_invokeSpecial           = 7,
    2.19 +            REF_newInvokeSpecial        = 8,
    2.20 +            REF_invokeInterface         = 9;
    2.21      }
    2.22  
    2.23      private static native int getNamedCon(int which, Object[] name);
    2.24 @@ -304,4 +318,24 @@
    2.25          return MethodTypeImpl.makeImpl(Access.TOKEN, rtype, ptypes, true);
    2.26      }
    2.27  
    2.28 +    /**
    2.29 +     * The JVM is resolving a CONSTANT_MethodHandle CP entry.  And it wants our help.
    2.30 +     * It will make an up-call to this method.  (Do not change the name or signature.)
    2.31 +     */
    2.32 +    static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
    2.33 +                                                 Class<?> defc, String name, Object type) {
    2.34 +        Lookup lookup = IMPL_LOOKUP.in(callerClass);
    2.35 +        switch (refKind) {
    2.36 +        case REF_getField:          return lookup.findGetter(       defc, name, (Class<?>)   type );
    2.37 +        case REF_getStatic:         return lookup.findStaticGetter( defc, name, (Class<?>)   type );
    2.38 +        case REF_putField:          return lookup.findSetter(       defc, name, (Class<?>)   type );
    2.39 +        case REF_putStatic:         return lookup.findStaticSetter( defc, name, (Class<?>)   type );
    2.40 +        case REF_invokeVirtual:     return lookup.findVirtual(      defc, name, (MethodType) type );
    2.41 +        case REF_invokeStatic:      return lookup.findStatic(       defc, name, (MethodType) type );
    2.42 +        case REF_invokeSpecial:     return lookup.findSpecial(      defc, name, (MethodType) type, callerClass );
    2.43 +        case REF_newInvokeSpecial:  return lookup.findConstructor(  defc,       (MethodType) type );
    2.44 +        case REF_invokeInterface:   return lookup.findVirtual(      defc, name, (MethodType) type );
    2.45 +        }
    2.46 +        throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type);
    2.47 +    }
    2.48  }
     3.1 --- a/src/share/javavm/export/classfile_constants.h	Fri Jun 18 15:23:57 2010 -0700
     3.2 +++ b/src/share/javavm/export/classfile_constants.h	Sat Jun 19 01:14:40 2010 -0700
     3.3 @@ -84,7 +84,22 @@
     3.4      JVM_CONSTANT_Fieldref               = 9,
     3.5      JVM_CONSTANT_Methodref              = 10,
     3.6      JVM_CONSTANT_InterfaceMethodref     = 11,
     3.7 -    JVM_CONSTANT_NameAndType            = 12
     3.8 +    JVM_CONSTANT_NameAndType            = 12,
     3.9 +    JVM_CONSTANT_MethodHandle           = 15,  // JSR 292
    3.10 +    JVM_CONSTANT_MethodType             = 16   // JSR 292
    3.11 +};
    3.12 +
    3.13 +/* JVM_CONSTANT_MethodHandle subtypes */
    3.14 +enum {
    3.15 +    JVM_REF_getField                = 1,
    3.16 +    JVM_REF_getStatic               = 2,
    3.17 +    JVM_REF_putField                = 3,
    3.18 +    JVM_REF_putStatic               = 4,
    3.19 +    JVM_REF_invokeVirtual           = 5,
    3.20 +    JVM_REF_invokeStatic            = 6,
    3.21 +    JVM_REF_invokeSpecial           = 7,
    3.22 +    JVM_REF_newInvokeSpecial        = 8,
    3.23 +    JVM_REF_invokeInterface         = 9
    3.24  };
    3.25  
    3.26  /* StackMapTable type item numbers */
     4.1 --- a/src/share/native/common/check_code.c	Fri Jun 18 15:23:57 2010 -0700
     4.2 +++ b/src/share/native/common/check_code.c	Sat Jun 19 01:14:40 2010 -0700
     4.3 @@ -204,6 +204,8 @@
     4.4  
     4.5  #define LDC_CLASS_MAJOR_VERSION 49
     4.6  
     4.7 +#define LDC_METHOD_HANDLE_MAJOR_VERSION 51
     4.8 +
     4.9  #define ALLOC_STACK_SIZE 16 /* big enough */
    4.10  
    4.11  typedef struct alloc_stack_type {
    4.12 @@ -1181,6 +1183,10 @@
    4.13          if (context->major_version >= LDC_CLASS_MAJOR_VERSION) {
    4.14              types |= 1 << JVM_CONSTANT_Class;
    4.15          }
    4.16 +        if (context->major_version >= LDC_METHOD_HANDLE_MAJOR_VERSION) {
    4.17 +            types |= (1 << JVM_CONSTANT_MethodHandle) |
    4.18 +                     (1 << JVM_CONSTANT_MethodType);
    4.19 +        }
    4.20          this_idata->operand.i = key;
    4.21          verify_constant_pool_type(context, key, types);
    4.22          break;
    4.23 @@ -1194,6 +1200,10 @@
    4.24          if (context->major_version >= LDC_CLASS_MAJOR_VERSION) {
    4.25              types |= 1 << JVM_CONSTANT_Class;
    4.26          }
    4.27 +        if (context->major_version >= LDC_METHOD_HANDLE_MAJOR_VERSION) {
    4.28 +            types |= (1 << JVM_CONSTANT_MethodHandle) |
    4.29 +                     (1 << JVM_CONSTANT_MethodType);
    4.30 +        }
    4.31          this_idata->operand.i = key;
    4.32          verify_constant_pool_type(context, key, types);
    4.33          break;
    4.34 @@ -2667,6 +2677,22 @@
    4.35                      full_info = make_class_info_from_name(context,
    4.36                                                            "java/lang/Class");
    4.37                      break;
    4.38 +                case JVM_CONSTANT_MethodHandle:
    4.39 +                case JVM_CONSTANT_MethodType:
    4.40 +                    if (context->major_version < LDC_METHOD_HANDLE_MAJOR_VERSION)
    4.41 +                        CCerror(context, "Internal error #3");
    4.42 +                    stack_results = "A";
    4.43 +                    switch (type_table[operand]) {
    4.44 +                    case JVM_CONSTANT_MethodType:
    4.45 +                      full_info = make_class_info_from_name(context,
    4.46 +                                                            "java/dyn/MethodType");
    4.47 +                      break;
    4.48 +                    default: //JVM_CONSTANT_MethodHandle
    4.49 +                      full_info = make_class_info_from_name(context,
    4.50 +                                                            "java/dyn/MethodHandle");
    4.51 +                      break;
    4.52 +                    }
    4.53 +                    break;
    4.54                  default:
    4.55                      CCerror(context, "Internal error #3");
    4.56                      stack_results = ""; /* Never reached: keep lint happy */
     5.1 --- a/test/java/dyn/MethodHandlesTest.java	Fri Jun 18 15:23:57 2010 -0700
     5.2 +++ b/test/java/dyn/MethodHandlesTest.java	Sat Jun 19 01:14:40 2010 -0700
     5.3 @@ -47,6 +47,10 @@
     5.4  public class MethodHandlesTest {
     5.5      // How much output?
     5.6      static int verbosity = 0;
     5.7 +    static {
     5.8 +        String vstr = System.getProperty("test.java.dyn.MethodHandlesTest.verbosity");
     5.9 +        if (vstr != null)  verbosity = Integer.parseInt(vstr);
    5.10 +    }
    5.11  
    5.12      // Set this true during development if you want to fast-forward to
    5.13      // a particular new, non-working test.  Tests which are known to
    5.14 @@ -109,7 +113,7 @@
    5.15          String vers = properties.getProperty("java.vm.version");
    5.16          String name = properties.getProperty("java.vm.name");
    5.17          String arch = properties.getProperty("os.arch");
    5.18 -        if ((arch.equals("i386")  || arch.equals("amd64") ||
    5.19 +        if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
    5.20               arch.equals("sparc") || arch.equals("sparcv9")) &&
    5.21              (name.contains("Client") || name.contains("Server"))
    5.22              ) {
    5.23 @@ -121,6 +125,7 @@
    5.24      }
    5.25  
    5.26      String testName;
    5.27 +    static int allPosTests, allNegTests;
    5.28      int posTests, negTests;
    5.29      @After
    5.30      public void printCounts() {
    5.31 @@ -128,6 +133,8 @@
    5.32              System.out.println();
    5.33              if (posTests != 0)  System.out.println("=== "+testName+": "+posTests+" positive test cases run");
    5.34              if (negTests != 0)  System.out.println("=== "+testName+": "+negTests+" negative test cases run");
    5.35 +            allPosTests += posTests;
    5.36 +            allNegTests += negTests;
    5.37              posTests = negTests = 0;
    5.38          }
    5.39      }
    5.40 @@ -153,6 +160,12 @@
    5.41  
    5.42      @AfterClass
    5.43      public static void tearDownClass() throws Exception {
    5.44 +        int posTests = allPosTests, negTests = allNegTests;
    5.45 +        if (verbosity >= 2 && (posTests | negTests) != 0) {
    5.46 +            System.out.println();
    5.47 +            if (posTests != 0)  System.out.println("=== "+posTests+" total positive test cases");
    5.48 +            if (negTests != 0)  System.out.println("=== "+negTests+" total negative test cases");
    5.49 +        }
    5.50      }
    5.51  
    5.52      static List<Object> calledLog = new ArrayList<Object>();
    5.53 @@ -811,28 +824,52 @@
    5.54          }
    5.55      }
    5.56  
    5.57 +    static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC_FIELD = 3;
    5.58 +    static boolean testModeMatches(int testMode, boolean isStatic) {
    5.59 +        switch (testMode) {
    5.60 +        case TEST_FIND_STATIC_FIELD:    return isStatic;
    5.61 +        case TEST_FIND_FIELD:           return !isStatic;
    5.62 +        default:                        return true;  // unreflect matches both
    5.63 +        }
    5.64 +    }
    5.65 +
    5.66      @Test
    5.67      public void testUnreflectGetter() throws Throwable {
    5.68 +        startTest("unreflectGetter");
    5.69 +        testGetter(TEST_UNREFLECT);
    5.70 +    }
    5.71 +    @Test
    5.72 +    public void testFindGetter() throws Throwable {
    5.73 +        startTest("findGetter");
    5.74 +        testGetter(TEST_FIND_FIELD);
    5.75 +    }
    5.76 +    @Test
    5.77 +    public void testFindStaticGetter() throws Throwable {
    5.78 +        startTest("findStaticGetter");
    5.79 +        testGetter(TEST_FIND_STATIC_FIELD);
    5.80 +    }
    5.81 +    public void testGetter(int testMode) throws Throwable {
    5.82          Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
    5.83 -        startTest("unreflectGetter");
    5.84          for (Object[] c : HasFields.CASES) {
    5.85              Field f = (Field)c[0];
    5.86              Object value = c[1];
    5.87              Class<?> type = f.getType();
    5.88 -            if (type.isPrimitive() && type != int.class)
    5.89 -                continue;  //FIXME
    5.90 -            testUnreflectGetter(lookup, f, type, value);
    5.91 +            testGetter(lookup, f, type, value, testMode);
    5.92          }
    5.93      }
    5.94 -    public void testUnreflectGetter(MethodHandles.Lookup lookup,
    5.95 -            Field f, Class<?> type, Object value) throws Throwable {
    5.96 +    public void testGetter(MethodHandles.Lookup lookup,
    5.97 +            Field f, Class<?> type, Object value, int testMode) throws Throwable {
    5.98 +        boolean isStatic = Modifier.isStatic(f.getModifiers());
    5.99 +        Class<?> fclass = f.getDeclaringClass();
   5.100 +        String   fname  = f.getName();
   5.101 +        Class<?> ftype  = f.getType();
   5.102 +        if (!testModeMatches(testMode, isStatic))  return;
   5.103          countTest(true);
   5.104 -        boolean isStatic = Modifier.isStatic(f.getModifiers());
   5.105          MethodType expType = MethodType.methodType(type, HasFields.class);
   5.106          if (isStatic)  expType = expType.dropParameterTypes(0, 1);
   5.107          MethodHandle mh = lookup.unreflectGetter(f);
   5.108          assertSame(mh.type(), expType);
   5.109 -        assertEquals(mh.toString(), f.getName());
   5.110 +        assertEquals(mh.toString(), fname);
   5.111          HasFields fields = new HasFields();
   5.112          Object sawValue;
   5.113          Class<?> rtype = type;
   5.114 @@ -862,26 +899,49 @@
   5.115  
   5.116      @Test
   5.117      public void testUnreflectSetter() throws Throwable {
   5.118 +        startTest("unreflectSetter");
   5.119 +        testSetter(TEST_UNREFLECT);
   5.120 +    }
   5.121 +    @Test
   5.122 +    public void testFindSetter() throws Throwable {
   5.123 +        startTest("findSetter");
   5.124 +        testSetter(TEST_FIND_FIELD);
   5.125 +    }
   5.126 +    @Test
   5.127 +    public void testFindStaticSetter() throws Throwable {
   5.128 +        startTest("findStaticSetter");
   5.129 +        testSetter(TEST_FIND_STATIC_FIELD);
   5.130 +    }
   5.131 +    public void testSetter(int testMode) throws Throwable {
   5.132          Lookup lookup = PRIVATE;  // FIXME: test more lookups than this one
   5.133          startTest("unreflectSetter");
   5.134          for (Object[] c : HasFields.CASES) {
   5.135              Field f = (Field)c[0];
   5.136              Object value = c[1];
   5.137              Class<?> type = f.getType();
   5.138 -            if (type.isPrimitive() && type != int.class)
   5.139 -                continue;  //FIXME
   5.140 -            testUnreflectSetter(lookup, f, type, value);
   5.141 +            testSetter(lookup, f, type, value, testMode);
   5.142          }
   5.143      }
   5.144 -    public void testUnreflectSetter(MethodHandles.Lookup lookup,
   5.145 -            Field f, Class<?> type, Object value) throws Throwable {
   5.146 +    public void testSetter(MethodHandles.Lookup lookup,
   5.147 +            Field f, Class<?> type, Object value, int testMode) throws Throwable {
   5.148 +        boolean isStatic = Modifier.isStatic(f.getModifiers());
   5.149 +        Class<?> fclass = f.getDeclaringClass();
   5.150 +        String   fname  = f.getName();
   5.151 +        Class<?> ftype  = f.getType();
   5.152 +        if (!testModeMatches(testMode, isStatic))  return;
   5.153          countTest(true);
   5.154 -        boolean isStatic = Modifier.isStatic(f.getModifiers());
   5.155          MethodType expType = MethodType.methodType(void.class, HasFields.class, type);
   5.156          if (isStatic)  expType = expType.dropParameterTypes(0, 1);
   5.157 -        MethodHandle mh = lookup.unreflectSetter(f);
   5.158 +        MethodHandle mh;
   5.159 +        if (testMode == TEST_UNREFLECT)
   5.160 +            mh = lookup.unreflectSetter(f);
   5.161 +        else if (testMode == TEST_FIND_FIELD)
   5.162 +            mh = lookup.findSetter(fclass, fname, ftype);
   5.163 +        else if (testMode == TEST_FIND_STATIC_FIELD)
   5.164 +            mh = lookup.findStaticSetter(fclass, fname, ftype);
   5.165 +        else  throw new InternalError();
   5.166          assertSame(mh.type(), expType);
   5.167 -        assertEquals(mh.toString(), f.getName());
   5.168 +        assertEquals(mh.toString(), fname);
   5.169          HasFields fields = new HasFields();
   5.170          Object sawValue;
   5.171          Class<?> vtype = type;