changeset 437:d925ea8227c0

meth-aclone.patch: point fix for bug reported by Remi
author jrose
date Wed, 17 Oct 2012 21:02:38 -0700
parents 9193ecd53c82
children 51b63e67f83e
files meth-aclone-8001105.patch
diffstat 1 files changed, 120 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meth-aclone-8001105.patch	Wed Oct 17 21:02:38 2012 -0700
@@ -0,0 +1,120 @@
+8001105: findVirtual of Object[].clone produces internal error
+http://mail.openjdk.java.net/pipermail/mlvm-dev/2012-October/005035.html
+
+diff --git a/src/share/classes/java/lang/invoke/MethodHandles.java b/src/share/classes/java/lang/invoke/MethodHandles.java
+--- a/src/share/classes/java/lang/invoke/MethodHandles.java
++++ b/src/share/classes/java/lang/invoke/MethodHandles.java
+@@ -1126,6 +1126,13 @@
+             int allowedModes = this.allowedModes;
+             if (allowedModes == TRUSTED)  return;
+             int mods = m.getModifiers();
++            if (Modifier.isProtected(mods) &&
++                    refKind == REF_invokeVirtual &&
++                    m.getDeclaringClass() == Object.class &&
++                    m.getName().equals("clone") &&
++                    refc.isArray())
++                // The JVM does this hack also, to make int[].clone be public.
++                mods ^= Modifier.PROTECTED | Modifier.PUBLIC;
+             if (Modifier.isFinal(mods) &&
+                     MethodHandleNatives.refKindIsSetter(refKind))
+                 throw m.makeAccessException("unexpected set of a final field", this);
+diff --git a/test/java/lang/invoke/MethodHandlesTest.java b/test/java/lang/invoke/MethodHandlesTest.java
+--- a/test/java/lang/invoke/MethodHandlesTest.java
++++ b/test/java/lang/invoke/MethodHandlesTest.java
+@@ -140,7 +140,7 @@
+         Object actual   = calledLog.get(calledLog.size() - 1);
+         if (expected.equals(actual) && verbosity < 9)  return;
+         System.out.println("assertCalled "+name+":");
+-        System.out.println("expected:   "+expected);
++        System.out.println("expected:   "+deepToString(expected));
+         System.out.println("actual:     "+actual);
+         System.out.println("ex. types:  "+getClasses(expected));
+         System.out.println("act. types: "+getClasses(actual));
+@@ -148,7 +148,25 @@
+     }
+     static void printCalled(MethodHandle target, String name, Object... args) {
+         if (verbosity >= 3)
+-            System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
++            System.out.println("calling MH="+target+" to "+name+deepToString(args));
++    }
++    static String deepToString(Object x) {
++        if (x == null)  return "null";
++        if (x instanceof Collection)
++            x = ((Collection)x).toArray();
++        if (x instanceof Object[]) {
++            Object[] ax = (Object[]) x;
++            ax = Arrays.copyOf(ax, ax.length, Object[].class);
++            for (int i = 0; i < ax.length; i++)
++                ax[i] = deepToString(ax[i]);
++            x = Arrays.deepToString(ax);
++        }
++        if (x.getClass().isArray())
++            try {
++                x = Arrays.class.getMethod("toString", x.getClass()).invoke(null, x);
++            } catch (ReflectiveOperationException ex) { throw new Error(ex); }
++        assert(!(x instanceof Object[]));
++        return x.toString();
+     }
+ 
+     static Object castToWrapper(Object value, Class<?> dst) {
+@@ -230,6 +248,12 @@
+                     { param = c; break; }
+             }
+         }
++        if (param.isArray()) {
++            Class<?> ctype = param.getComponentType();
++            Object arg = Array.newInstance(ctype, 2);
++            Array.set(arg, 0, randomArg(ctype));
++            return arg;
++        }
+         if (param.isInterface() && param.isAssignableFrom(List.class))
+             return Arrays.asList("#"+nextArg());
+         if (param.isInterface() || param.isAssignableFrom(String.class))
+@@ -582,6 +606,13 @@
+         testFindVirtual(SubExample.class,         Example.class, void.class, "Sub/pkg_v0");
+         testFindVirtual(Example.class,         IntExample.class, void.class, "v0");
+         testFindVirtual(IntExample.Impl.class, IntExample.class, void.class, "Int/v0");
++
++        // test some ad hoc system methods
++        testFindVirtual(false, PUBLIC, Object.class, Object.class, "clone");
++        testFindVirtual(true, PUBLIC, Object[].class, Object.class, "clone");
++        testFindVirtual(true, PUBLIC, int[].class, Object.class, "clone");
++        for (Class<?> cls : new Class<?>[]{ boolean[].class, long[].class, float[].class, char[].class })
++            testFindVirtual(true, PUBLIC, cls, Object.class, "clone");
+     }
+ 
+     void testFindVirtual(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+@@ -596,6 +627,9 @@
+     void testFindVirtual(Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+         testFindVirtual(true, lookup, rcvc, defc, ret, name, params);
+     }
++    void testFindVirtual(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
++        testFindVirtual(positive, lookup, defc, defc, ret, name, params);
++    }
+     void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+         countTest(positive);
+         String methodName = name.substring(1 + name.indexOf('/'));  // foo/bar => foo
+@@ -635,8 +669,21 @@
+         Object[] argsWithSelf = randomArgs(paramsWithSelf);
+         if (selfc.isAssignableFrom(rcvc) && rcvc != selfc)  argsWithSelf[0] = randomArg(rcvc);
+         printCalled(target, name, argsWithSelf);
+-        target.invokeWithArguments(argsWithSelf);
+-        assertCalled(name, argsWithSelf);
++        Object res = target.invokeWithArguments(argsWithSelf);
++        if (Example.class.isAssignableFrom(defc) || IntExample.class.isAssignableFrom(defc)) {
++            assertCalled(name, argsWithSelf);
++        } else if (name.equals("clone")) {
++            // Ad hoc method call outside Example.  For Object[].clone.
++            printCalled(target, name, argsWithSelf);
++            assertEquals(MethodType.methodType(Object.class, rcvc), target.type());
++            Object orig = argsWithSelf[0];
++            assertEquals(orig.getClass(), res.getClass());
++            if (res instanceof Object[])
++                assertArrayEquals((Object[])res, (Object[])argsWithSelf[0]);
++            assert(Arrays.deepEquals(new Object[]{res}, new Object[]{argsWithSelf[0]}));
++        } else {
++            assert(false) : Arrays.asList(positive, lookup, rcvc, defc, ret, name, deepToString(params));
++        }
+         if (verbosity >= 1)
+             System.out.print(':');
+     }