OpenJDK / portola / portola
changeset 9783:3c2fee00c063
Merge
author | trims |
---|---|
date | Fri, 03 Jun 2011 20:13:50 -0700 |
parents | 967402e4be8b 973c21557e1a |
children | 5445a3b7d06b |
files | |
diffstat | 9 files changed, 196 insertions(+), 39 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Jun 02 13:38:28 2011 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Fri Jun 03 20:13:50 2011 -0700 @@ -26,6 +26,8 @@ package java.lang.invoke; import sun.invoke.util.VerifyType; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -336,18 +338,20 @@ void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); } // cast (V) is OK here, since we wrap convertArguments around the MH. - static Object staticBase(MemberName field) { + static Object staticBase(final MemberName field) { if (!field.isStatic()) return null; - Class c = field.getDeclaringClass(); - java.lang.reflect.Field f; - try { - // FIXME: Should not have to create 'f' to get this value. - f = c.getDeclaredField(field.getName()); - // Note: Previous line might invalidly throw SecurityException (7042829) - return unsafe.staticFieldBase(f); - } catch (NoSuchFieldException ee) { - throw uncaughtException(ee); - } + return AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + try { + Class c = field.getDeclaringClass(); + // FIXME: Should not have to create 'f' to get this value. + java.lang.reflect.Field f = c.getDeclaredField(field.getName()); + return unsafe.staticFieldBase(f); + } catch (NoSuchFieldException ee) { + throw uncaughtException(ee); + } + } + }); } int getStaticI() { return unsafe.getInt(base, offset); }
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java Thu Jun 02 13:38:28 2011 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java Fri Jun 03 20:13:50 2011 -0700 @@ -359,6 +359,12 @@ required = Object[].class; // should have been an array code = 192; // checkcast break; + case 191: // athrow + // JVM is asking us to wrap an exception which happened during resolving + if (required == BootstrapMethodError.class) { + throw new BootstrapMethodError((Throwable) actual); + } + break; } // disregard the identity of the actual object, if it is not a class: if (message == null) { @@ -389,18 +395,7 @@ Class<?> defc, String name, Object type) { try { Lookup lookup = IMPL_LOOKUP.in(callerClass); - switch (refKind) { - case REF_getField: return lookup.findGetter( defc, name, (Class<?>) type ); - case REF_getStatic: return lookup.findStaticGetter( defc, name, (Class<?>) type ); - case REF_putField: return lookup.findSetter( defc, name, (Class<?>) type ); - case REF_putStatic: return lookup.findStaticSetter( defc, name, (Class<?>) type ); - case REF_invokeVirtual: return lookup.findVirtual( defc, name, (MethodType) type ); - case REF_invokeStatic: return lookup.findStatic( defc, name, (MethodType) type ); - case REF_invokeSpecial: return lookup.findSpecial( defc, name, (MethodType) type, callerClass ); - case REF_newInvokeSpecial: return lookup.findConstructor( defc, (MethodType) type ); - case REF_invokeInterface: return lookup.findVirtual( defc, name, (MethodType) type ); - } - throw new InternalError("bad MethodHandle constant "+name+" : "+type); + return lookup.linkMethodHandleConstant(refKind, defc, name, type); } catch (ReflectiveOperationException ex) { Error err = new IncompatibleClassChangeError(); err.initCause(ex);
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java Thu Jun 02 13:38:28 2011 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java Fri Jun 03 20:13:50 2011 -0700 @@ -25,6 +25,9 @@ package java.lang.invoke; +import java.security.AccessController; +import java.security.PrivilegedAction; + /** * This class consists exclusively of static names internal to the * method handle implementation. @@ -35,7 +38,17 @@ private MethodHandleStatics() { } // do not instantiate - static final boolean DEBUG_METHOD_HANDLE_NAMES = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES"); + static final boolean DEBUG_METHOD_HANDLE_NAMES; + static { + final Object[] values = { false }; + AccessController.doPrivileged(new PrivilegedAction<Void>() { + public Void run() { + values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES"); + return null; + } + }); + DEBUG_METHOD_HANDLE_NAMES = (Boolean) values[0]; + } /*non-public*/ static String getNameString(MethodHandle target, MethodType type) { if (type == null)
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Thu Jun 02 13:38:28 2011 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Fri Jun 03 20:13:50 2011 -0700 @@ -35,6 +35,7 @@ import java.util.Arrays; import sun.reflect.Reflection; import static java.lang.invoke.MethodHandleStatics.*; +import static java.lang.invoke.MethodHandleNatives.Constants.*; /** * This class consists exclusively of static methods that operate on or return @@ -579,9 +580,18 @@ MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(refc, name, type, true); checkSecurityManager(refc, method); // stack walk magic: do not refactor + return accessStatic(refc, method); + } + private + MethodHandle accessStatic(Class<?> refc, MemberName method) throws IllegalAccessException { checkMethod(refc, method, true); return MethodHandleImpl.findMethod(method, false, lookupClassOrNull()); } + private + MethodHandle resolveStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { + MemberName method = resolveOrFail(refc, name, type, true); + return accessStatic(refc, method); + } /** * Produces a method handle for a virtual method. @@ -624,6 +634,13 @@ public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { MemberName method = resolveOrFail(refc, name, type, false); checkSecurityManager(refc, method); // stack walk magic: do not refactor + return accessVirtual(refc, method); + } + private MethodHandle resolveVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { + MemberName method = resolveOrFail(refc, name, type, false); + return accessVirtual(refc, method); + } + private MethodHandle accessVirtual(Class<?> refc, MemberName method) throws IllegalAccessException { checkMethod(refc, method, false); MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull()); return restrictProtectedReceiver(method, mh); @@ -658,13 +675,21 @@ public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { String name = "<init>"; MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull()); + checkSecurityManager(refc, ctor); // stack walk magic: do not refactor + return accessConstructor(refc, ctor); + } + private MethodHandle accessConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException { assert(ctor.isConstructor()); - checkSecurityManager(refc, ctor); // stack walk magic: do not refactor checkAccess(refc, ctor); MethodHandle rawMH = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull()); MethodHandle allocMH = MethodHandleImpl.makeAllocator(rawMH); return fixVarargs(allocMH, rawMH); } + private MethodHandle resolveConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException { + String name = "<init>"; + MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull()); + return accessConstructor(refc, ctor); + } /** Return a version of MH which matches matchMH w.r.t. isVarargsCollector. */ private static MethodHandle fixVarargs(MethodHandle mh, MethodHandle matchMH) { @@ -720,10 +745,20 @@ checkSpecialCaller(specialCaller); MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller); checkSecurityManager(refc, method); // stack walk magic: do not refactor + return accessSpecial(refc, method, specialCaller); + } + private MethodHandle accessSpecial(Class<?> refc, MemberName method, + Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException { checkMethod(refc, method, false); MethodHandle mh = MethodHandleImpl.findMethod(method, false, specialCaller); return restrictReceiver(method, mh, specialCaller); } + private MethodHandle resolveSpecial(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException { + Class<?> specialCaller = lookupClass(); + checkSpecialCaller(specialCaller); + MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller); + return accessSpecial(refc, method, specialCaller); + } /** * Produces a method handle giving read access to a non-static field. @@ -747,6 +782,10 @@ checkSecurityManager(refc, field); // stack walk magic: do not refactor return makeAccessor(refc, field, false, false, 0); } + private MethodHandle resolveGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { + MemberName field = resolveOrFail(refc, name, type, false); + return makeAccessor(refc, field, false, false, 0); + } /** * Produces a method handle giving write access to a non-static field. @@ -770,6 +809,10 @@ checkSecurityManager(refc, field); // stack walk magic: do not refactor return makeAccessor(refc, field, false, true, 0); } + private MethodHandle resolveSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { + MemberName field = resolveOrFail(refc, name, type, false); + return makeAccessor(refc, field, false, true, 0); + } /** * Produces a method handle giving read access to a static field. @@ -792,6 +835,10 @@ checkSecurityManager(refc, field); // stack walk magic: do not refactor return makeAccessor(refc, field, false, false, 1); } + private MethodHandle resolveStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { + MemberName field = resolveOrFail(refc, name, type, true); + return makeAccessor(refc, field, false, false, 1); + } /** * Produces a method handle giving write access to a static field. @@ -814,6 +861,10 @@ checkSecurityManager(refc, field); // stack walk magic: do not refactor return makeAccessor(refc, field, false, true, 1); } + private MethodHandle resolveStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException { + MemberName field = resolveOrFail(refc, name, type, true); + return makeAccessor(refc, field, false, true, 1); + } /** * Produces an early-bound method handle for a non-static method. @@ -1179,6 +1230,25 @@ MethodHandle mh = MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull()); return restrictProtectedReceiver(field, mh); } + + /** Hook called from the JVM (via MethodHandleNatives) to link MH constants: + */ + /*non-public*/ + MethodHandle linkMethodHandleConstant(int refKind, Class<?> defc, String name, Object type) throws ReflectiveOperationException { + switch (refKind) { + case REF_getField: return resolveGetter( defc, name, (Class<?>) type ); + case REF_getStatic: return resolveStaticGetter( defc, name, (Class<?>) type ); + case REF_putField: return resolveSetter( defc, name, (Class<?>) type ); + case REF_putStatic: return resolveStaticSetter( defc, name, (Class<?>) type ); + case REF_invokeVirtual: return resolveVirtual( defc, name, (MethodType) type ); + case REF_invokeStatic: return resolveStatic( defc, name, (MethodType) type ); + case REF_invokeSpecial: return resolveSpecial( defc, name, (MethodType) type ); + case REF_newInvokeSpecial: return resolveConstructor( defc, (MethodType) type ); + case REF_invokeInterface: return resolveVirtual( defc, name, (MethodType) type ); + } + // oops + throw new ReflectiveOperationException("bad MethodHandle constant #"+refKind+" "+name+" : "+type); + } } /**
--- a/jdk/src/share/classes/java/lang/invoke/SwitchPoint.java Thu Jun 02 13:38:28 2011 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/SwitchPoint.java Fri Jun 03 20:13:50 2011 -0700 @@ -59,14 +59,14 @@ MethodHandle MH_strcat = MethodHandles.lookup() .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class)); SwitchPoint spt = new SwitchPoint(); -assert(spt.isValid()); +assert(!spt.hasBeenInvalidated()); // the following steps may be repeated to re-use the same switch point: MethodHandle worker1 = MH_strcat; MethodHandle worker2 = MethodHandles.permuteArguments(MH_strcat, MH_strcat.type(), 1, 0); MethodHandle worker = spt.guardWithTest(worker1, worker2); assertEquals("method", (String) worker.invokeExact("met", "hod")); SwitchPoint.invalidateAll(new SwitchPoint[]{ spt }); -assert(!spt.isValid()); +assert(spt.hasBeenInvalidated()); assertEquals("hodmet", (String) worker.invokeExact("met", "hod")); * </pre></blockquote> * <p style="font-size:smaller;"> @@ -126,16 +126,30 @@ } /** - * Determines if this switch point is still valid. - * <p> + * Determines if this switch point has been invalidated yet. + * + * <p style="font-size:smaller;"> + * <em>Discussion:</em> + * Because of the one-way nature of invalidation, once a switch point begins + * to return true for {@code hasBeenInvalidated}, + * it will always do so in the future. + * On the other hand, a valid switch point visible to other threads may + * invalidated at any moment, due to a request by another thread. + * <p style="font-size:smaller;"> * Since invalidation is a global and immediate operation, - * this query must be sequenced with any - * other threads that could invalidate this switch point. - * It may therefore be expensive. - * @return true if this switch point has never been invalidated + * the execution of this query, on a valid switchpoint, + * must be internally sequenced with any + * other threads that could cause invalidation. + * This query may therefore be expensive. + * The recommended way to build a boolean-valued method handle + * which queries the invalidation state of a switch point {@code s} is + * to call {@code s.guardWithTest} on + * {@link MethodHandles#constant constant} true and false method handles. + * + * @return true if this switch point has been invalidated */ - public boolean isValid() { - return (mcs.getTarget() == K_true); + public boolean hasBeenInvalidated() { + return (mcs.getTarget() != K_true); } /**
--- a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java Thu Jun 02 13:38:28 2011 -0700 +++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java Fri Jun 03 20:13:50 2011 -0700 @@ -29,6 +29,8 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -38,7 +40,17 @@ public class ValueConversions { private static final Class<?> THIS_CLASS = ValueConversions.class; // Do not adjust this except for special platforms: - private static final int MAX_ARITY = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255); + private static final int MAX_ARITY; + static { + final Object[] values = { 255 }; + AccessController.doPrivileged(new PrivilegedAction<Void>() { + public Void run() { + values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255); + return null; + } + }); + MAX_ARITY = (Integer) values[0]; + } private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
--- a/jdk/test/java/lang/invoke/InvokeDynamicPrintArgs.java Thu Jun 02 13:38:28 2011 -0700 +++ b/jdk/test/java/lang/invoke/InvokeDynamicPrintArgs.java Fri Jun 03 20:13:50 2011 -0700 @@ -30,6 +30,10 @@ * --verify-specifier-count=3 * --expand-properties --classpath ${test.classes} * --java test.java.lang.invoke.InvokeDynamicPrintArgs --check-output + * @run main/othervm + * indify.Indify + * --expand-properties --classpath ${test.classes} + * --java test.java.lang.invoke.InvokeDynamicPrintArgs --security-manager */ package test.java.lang.invoke; @@ -45,7 +49,8 @@ public class InvokeDynamicPrintArgs { public static void main(String... av) throws Throwable { - if (av.length > 0) openBuf(); // --check-output mode + if (av.length > 0 && av[0].equals("--check-output")) openBuf(); + if (av.length > 0 && av[0].equals("--security-manager")) setSM(); System.out.println("Printing some argument lists, starting with a empty one:"); INDY_nothing().invokeExact(); // BSM specifier #0 = {bsm} INDY_bar().invokeExact("bar arg", 1); // BSM specifier #1 = {bsm2, Void.class, "void type"} @@ -55,6 +60,43 @@ // Hence, BSM specifier count should be 3. See "--verify-specifier-count=3" above. System.out.println("Done printing argument lists."); closeBuf(); + checkConstantRefs(); + } + + private static void checkConstantRefs() throws Throwable { + // check some constant references: + assertEquals(MT_bsm(), MH_bsm().type()); + assertEquals(MT_bsm2(), MH_bsm2().type()); + try { + assertEquals(MT_bsm(), non_MH_bsm().type()); + // if SM is installed, must throw before this point + assertEquals(false, System.getSecurityManager() != null); + } catch (SecurityException ex) { + // if SM is installed, must throw to this point + assertEquals(true, System.getSecurityManager() != null); + } + } + private static void assertEquals(Object exp, Object act) { + if (exp == act || (exp != null && exp.equals(act))) return; + throw new AssertionError("not equal: "+exp+", "+act); + } + + private static void setSM() { + // Test for severe security manager interactions (7050328). + class SM extends SecurityManager { + public void checkPackageAccess(String pkg) { + if (pkg.startsWith("test.")) + throw new SecurityException("checkPackageAccess "+pkg); + } + public void checkMemberAccess(Class<?> clazz, int which) { + if (clazz == InvokeDynamicPrintArgs.class) + throw new SecurityException("checkMemberAccess "+clazz.getName()+" #"+which); + } + // allow these others: + public void checkPermission(java.security.Permission perm) { + } + } + System.setSecurityManager(new SM()); } @Test @@ -130,6 +172,9 @@ shouldNotCallThis(); return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm()); } + private static MethodHandle non_MH_bsm() throws ReflectiveOperationException { + return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm()); + } /* Example of a constant call site with user-data. * In this case, the user data is exactly the BSM data.
--- a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Thu Jun 02 13:38:28 2011 -0700 +++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Fri Jun 03 20:13:50 2011 -0700 @@ -477,14 +477,14 @@ MethodHandle MH_strcat = MethodHandles.lookup() .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class)); SwitchPoint spt = new SwitchPoint(); -assert(spt.isValid()); +assert(!spt.hasBeenInvalidated()); // the following steps may be repeated to re-use the same switch point: MethodHandle worker1 = MH_strcat; MethodHandle worker2 = MethodHandles.permuteArguments(MH_strcat, MH_strcat.type(), 1, 0); MethodHandle worker = spt.guardWithTest(worker1, worker2); assertEquals("method", (String) worker.invokeExact("met", "hod")); SwitchPoint.invalidateAll(new SwitchPoint[]{ spt }); -assert(!spt.isValid()); +assert(spt.hasBeenInvalidated()); assertEquals("hodmet", (String) worker.invokeExact("met", "hod")); {} }}
--- a/jdk/test/java/lang/invoke/RicochetTest.java Thu Jun 02 13:38:28 2011 -0700 +++ b/jdk/test/java/lang/invoke/RicochetTest.java Fri Jun 03 20:13:50 2011 -0700 @@ -25,6 +25,10 @@ /* @test * @summary unit tests for recursive method handles + * @run junit/othervm -DRicochetTest.MAX_ARITY=50 test.java.lang.invoke.RicochetTest + */ +/* + * @ignore The following test creates an unreasonable number of adapters in -Xcomp mode (7049122) * @run junit/othervm -DRicochetTest.MAX_ARITY=255 test.java.lang.invoke.RicochetTest */