Wed, 03 Jul 2013 12:39:28 +0200
8010946: AccessControl.doPrivileged is broken when called from js script
Reviewed-by: jlaskey, sundar
1.1 --- a/make/build.xml Wed Jul 03 14:08:00 2013 +0530 1.2 +++ b/make/build.xml Wed Jul 03 12:39:28 2013 +0200 1.3 @@ -235,44 +235,31 @@ 1.4 </target> 1.5 1.6 <target name="generate-policy-file" depends="prepare"> 1.7 - <!-- Generating nashorn.policy file --> 1.8 + <echo file="${build.dir}/nashorn.policy"> 1.9 1.10 - <!-- nashorn internal tests jar requires AllPermission --> 1.11 - <echo message="grant codeBase "file:/${basedir}/${nashorn.internal.tests.jar}" {" file="${build.dir}/nashorn.policy"/> 1.12 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.13 - <echo message=" permission java.security.AllPermission;" file="${build.dir}/nashorn.policy" append="true"/> 1.14 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.15 - <echo message="};" file="${build.dir}/nashorn.policy" append="true"/> 1.16 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.17 +grant codeBase "file:/${basedir}/${nashorn.internal.tests.jar}" { 1.18 + permission java.security.AllPermission; 1.19 +}; 1.20 1.21 - <!-- TestNG framework jar needs AllPermission --> 1.22 - <echo message="grant codeBase "file:/${basedir}/${file.reference.testng.jar}" {" file="${build.dir}/nashorn.policy" append="true"/> 1.23 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.24 - <echo message=" permission java.security.AllPermission;" file="${build.dir}/nashorn.policy" append="true"/> 1.25 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.26 - <echo message="};" file="${build.dir}/nashorn.policy" append="true"/> 1.27 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.28 +grant codeBase "file:/${basedir}/${file.reference.testng.jar}" { 1.29 + permission java.security.AllPermission; 1.30 +}; 1.31 1.32 - <!-- AllPermission to test/script/trusted tests --> 1.33 - <echo message="grant codeBase "file:/${basedir}/test/script/trusted/*" {" file="${build.dir}/nashorn.policy" append="true"/> 1.34 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.35 - <echo message=" permission java.security.AllPermission;" file="${build.dir}/nashorn.policy" append="true"/> 1.36 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.37 - <echo message="};" file="${build.dir}/nashorn.policy" append="true"/> 1.38 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.39 +grant codeBase "file:/${basedir}/test/script/trusted/*" { 1.40 + permission java.security.AllPermission; 1.41 +}; 1.42 1.43 - <echo message="grant codeBase "file:/${basedir}/test/script/basic/*" {" file="${build.dir}/nashorn.policy" append="true"/> 1.44 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.45 - <!-- test/script/basic .js scripts load other script tests --> 1.46 - <echo message=" permission java.io.FilePermission "${basedir}/test/script/-", "read";" file="${build.dir}/nashorn.policy" append="true"/> 1.47 - <echo message=" permission java.io.FilePermission "user.dir", "read";" file="${build.dir}/nashorn.policy" append="true"/> 1.48 - <echo message=" permission java.util.PropertyPermission "user.dir", "read";" file="${build.dir}/nashorn.policy" append="true"/> 1.49 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.50 - <!-- test/script/basic .js scripts can read nashorn.test.* properties --> 1.51 - <echo message=" permission java.util.PropertyPermission "nashorn.test.*", "read";" file="${build.dir}/nashorn.policy" append="true"/> 1.52 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.53 - <echo message="};" file="${build.dir}/nashorn.policy" append="true"/> 1.54 - <echo message="" file="${build.dir}/nashorn.policy" append="true"/> 1.55 +grant codeBase "file:/${basedir}/test/script/basic/*" { 1.56 + permission java.io.FilePermission "${basedir}/test/script/-", "read"; 1.57 + permission java.io.FilePermission "$${user.dir}", "read"; 1.58 + permission java.util.PropertyPermission "user.dir", "read"; 1.59 + permission java.util.PropertyPermission "nashorn.test.*", "read"; 1.60 +}; 1.61 + 1.62 +grant codeBase "file:/${basedir}/test/script/basic/JDK-8010946-privileged.js" { 1.63 + permission java.util.PropertyPermission "java.security.policy", "read"; 1.64 +}; 1.65 + </echo> 1.66 1.67 <replace file="${build.dir}/nashorn.policy"><replacetoken>\</replacetoken><replacevalue>/</replacevalue></replace> <!--hack for Windows - to make URLs with normal path separators --> 1.68 <replace file="${build.dir}/nashorn.policy"><replacetoken>//</replacetoken><replacevalue>/</replacevalue></replace> <!--hack for Unix - to avoid leading // in URLs -->
2.1 --- a/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java Wed Jul 03 14:08:00 2013 +0530 2.2 +++ b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java Wed Jul 03 12:39:28 2013 +0200 2.3 @@ -86,7 +86,10 @@ 2.4 import java.lang.invoke.MethodHandle; 2.5 import java.lang.invoke.MethodHandles; 2.6 import java.lang.invoke.MethodType; 2.7 +import java.lang.reflect.AccessibleObject; 2.8 +import java.lang.reflect.Constructor; 2.9 import java.lang.reflect.Field; 2.10 +import java.lang.reflect.Member; 2.11 import java.lang.reflect.Method; 2.12 import java.lang.reflect.Modifier; 2.13 import java.util.HashMap; 2.14 @@ -109,10 +112,11 @@ 2.15 * @author Attila Szegedi 2.16 */ 2.17 abstract class AbstractJavaLinker implements GuardingDynamicLinker { 2.18 + 2.19 final Class<?> clazz; 2.20 private final MethodHandle classGuard; 2.21 private final MethodHandle assignableGuard; 2.22 - private final Map<String, AnnotatedMethodHandle> propertyGetters = new HashMap<>(); 2.23 + private final Map<String, AnnotatedDynamicMethod> propertyGetters = new HashMap<>(); 2.24 private final Map<String, DynamicMethod> propertySetters = new HashMap<>(); 2.25 private final Map<String, DynamicMethod> methods = new HashMap<>(); 2.26 2.27 @@ -129,22 +133,19 @@ 2.28 // Add methods and properties 2.29 for(Method method: introspector.getMethods()) { 2.30 final String name = method.getName(); 2.31 - final MethodHandle methodHandle = introspector.unreflect(method); 2.32 // Add method 2.33 - addMember(name, methodHandle, methods); 2.34 + addMember(name, method, methods); 2.35 // Add the method as a property getter and/or setter 2.36 if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) { 2.37 // Property getter 2.38 - setPropertyGetter(decapitalize(name.substring(3)), introspector.unreflect( 2.39 - getMostGenericGetter(method)), ValidationType.INSTANCE_OF); 2.40 + setPropertyGetter(method, 3); 2.41 } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 && 2.42 method.getReturnType() == boolean.class) { 2.43 // Boolean property getter 2.44 - setPropertyGetter(decapitalize(name.substring(2)), introspector.unreflect( 2.45 - getMostGenericGetter(method)), ValidationType.INSTANCE_OF); 2.46 + setPropertyGetter(method, 2); 2.47 } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) { 2.48 // Property setter 2.49 - addMember(decapitalize(name.substring(3)), methodHandle, propertySetters); 2.50 + addMember(decapitalize(name.substring(3)), method, propertySetters); 2.51 } 2.52 } 2.53 2.54 @@ -156,7 +157,8 @@ 2.55 setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS); 2.56 } 2.57 if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) { 2.58 - addMember(name, introspector.unreflectSetter(field), propertySetters); 2.59 + addMember(name, new SimpleDynamicMethod(introspector.unreflectSetter(field), clazz, name), 2.60 + propertySetters); 2.61 } 2.62 } 2.63 2.64 @@ -192,38 +194,119 @@ 2.65 2.66 abstract FacetIntrospector createFacetIntrospector(); 2.67 2.68 - void setPropertyGetter(String name, MethodHandle handle, ValidationType validationType) { 2.69 - propertyGetters.put(name, new AnnotatedMethodHandle(handle, validationType)); 2.70 + /** 2.71 + * Sets the specified dynamic method to be the property getter for the specified property. Note that you can only 2.72 + * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties 2.73 + * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)} 2.74 + * instead. 2.75 + * @param name name of the property 2.76 + * @param handle the method handle that implements the property getter 2.77 + * @param validationType the validation type for the property 2.78 + */ 2.79 + private void setPropertyGetter(String name, SingleDynamicMethod handle, ValidationType validationType) { 2.80 + propertyGetters.put(name, new AnnotatedDynamicMethod(handle, validationType)); 2.81 } 2.82 2.83 - private void addMember(String name, MethodHandle mh, Map<String, DynamicMethod> methodMap) { 2.84 + /** 2.85 + * Sets the specified reflective method to be the property getter for the specified property. 2.86 + * @param getter the getter method 2.87 + * @param prefixLen the getter prefix in the method name; should be 3 for getter names starting with "get" and 2 for 2.88 + * names starting with "is". 2.89 + */ 2.90 + private void setPropertyGetter(Method getter, int prefixLen) { 2.91 + setPropertyGetter(decapitalize(getter.getName().substring(prefixLen)), createDynamicMethod( 2.92 + getMostGenericGetter(getter)), ValidationType.INSTANCE_OF); 2.93 + } 2.94 + 2.95 + /** 2.96 + * Sets the specified method handle to be the property getter for the specified property. Note that you can only 2.97 + * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties 2.98 + * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)} 2.99 + * instead. 2.100 + * @param name name of the property 2.101 + * @param handle the method handle that implements the property getter 2.102 + * @param validationType the validation type for the property 2.103 + */ 2.104 + void setPropertyGetter(String name, MethodHandle handle, ValidationType validationType) { 2.105 + setPropertyGetter(name, new SimpleDynamicMethod(handle, clazz, name), validationType); 2.106 + } 2.107 + 2.108 + private void addMember(String name, AccessibleObject ao, Map<String, DynamicMethod> methodMap) { 2.109 + addMember(name, createDynamicMethod(ao), methodMap); 2.110 + } 2.111 + 2.112 + private void addMember(String name, SingleDynamicMethod method, Map<String, DynamicMethod> methodMap) { 2.113 final DynamicMethod existingMethod = methodMap.get(name); 2.114 - final DynamicMethod newMethod = addMember(mh, existingMethod, clazz, name); 2.115 + final DynamicMethod newMethod = mergeMethods(method, existingMethod, clazz, name); 2.116 if(newMethod != existingMethod) { 2.117 methodMap.put(name, newMethod); 2.118 } 2.119 } 2.120 2.121 - static DynamicMethod createDynamicMethod(Iterable<MethodHandle> methodHandles, Class<?> clazz, String name) { 2.122 + /** 2.123 + * Given one or more reflective methods or constructors, creates a dynamic method that represents them all. The 2.124 + * methods should represent all overloads of the same name (or all constructors of the class). 2.125 + * @param members the reflective members 2.126 + * @param clazz the class declaring the reflective members 2.127 + * @param name the common name of the reflective members. 2.128 + * @return a dynamic method representing all the specified reflective members. 2.129 + */ 2.130 + static DynamicMethod createDynamicMethod(Iterable<? extends AccessibleObject> members, Class<?> clazz, String name) { 2.131 DynamicMethod dynMethod = null; 2.132 - for(MethodHandle methodHandle: methodHandles) { 2.133 - dynMethod = addMember(methodHandle, dynMethod, clazz, name); 2.134 + for(AccessibleObject method: members) { 2.135 + dynMethod = mergeMethods(createDynamicMethod(method), dynMethod, clazz, name); 2.136 } 2.137 return dynMethod; 2.138 } 2.139 2.140 - private static DynamicMethod addMember(MethodHandle mh, DynamicMethod existing, Class<?> clazz, String name) { 2.141 + /** 2.142 + * Given a reflective method or a constructor, creates a dynamic method that represents it. This method will 2.143 + * distinguish between caller sensitive and ordinary methods/constructors, and create appropriate caller sensitive 2.144 + * dynamic method when needed. 2.145 + * @param m the reflective member 2.146 + * @return the single dynamic method representing the reflective member 2.147 + */ 2.148 + private static SingleDynamicMethod createDynamicMethod(AccessibleObject m) { 2.149 + if(CallerSensitiveDetector.isCallerSensitive(m)) { 2.150 + return new CallerSensitiveDynamicMethod(m); 2.151 + } 2.152 + final Member member = (Member)m; 2.153 + return new SimpleDynamicMethod(unreflectSafely(m), member.getDeclaringClass(), member.getName()); 2.154 + } 2.155 + 2.156 + /** 2.157 + * Unreflects a method handle from a Method or a Constructor using safe (zero-privilege) unreflection. Should be 2.158 + * only used for methods and constructors that are not caller sensitive. If a caller sensitive method were 2.159 + * unreflected through this mechanism, it would not be a security issue, but would be bound to the zero-privilege 2.160 + * unreflector as its caller, and thus completely useless. 2.161 + * @param m the method or constructor 2.162 + * @return the method handle 2.163 + */ 2.164 + private static MethodHandle unreflectSafely(AccessibleObject m) { 2.165 + if(m instanceof Method) { 2.166 + final Method reflMethod = (Method)m; 2.167 + final MethodHandle handle = SafeUnreflector.unreflect(reflMethod); 2.168 + if(Modifier.isStatic(reflMethod.getModifiers())) { 2.169 + return StaticClassIntrospector.editStaticMethodHandle(handle); 2.170 + } 2.171 + return handle; 2.172 + } 2.173 + return StaticClassIntrospector.editConstructorMethodHandle(SafeUnreflector.unreflectConstructor( 2.174 + (Constructor<?>)m)); 2.175 + } 2.176 + 2.177 + private static DynamicMethod mergeMethods(SingleDynamicMethod method, DynamicMethod existing, Class<?> clazz, String name) { 2.178 if(existing == null) { 2.179 - return new SimpleDynamicMethod(mh, clazz, name); 2.180 - } else if(existing.contains(mh)) { 2.181 + return method; 2.182 + } else if(existing.contains(method)) { 2.183 return existing; 2.184 - } else if(existing instanceof SimpleDynamicMethod) { 2.185 + } else if(existing instanceof SingleDynamicMethod) { 2.186 final OverloadedDynamicMethod odm = new OverloadedDynamicMethod(clazz, name); 2.187 - odm.addMethod(((SimpleDynamicMethod)existing)); 2.188 - odm.addMethod(mh); 2.189 + odm.addMethod(((SingleDynamicMethod)existing)); 2.190 + odm.addMethod(method); 2.191 return odm; 2.192 } else if(existing instanceof OverloadedDynamicMethod) { 2.193 - ((OverloadedDynamicMethod)existing).addMethod(mh); 2.194 + ((OverloadedDynamicMethod)existing).addMethod(method); 2.195 return existing; 2.196 } 2.197 throw new AssertionError(); 2.198 @@ -296,7 +379,7 @@ 2.199 private GuardedInvocation getCallPropWithThis(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) { 2.200 switch(callSiteDescriptor.getNameTokenCount()) { 2.201 case 3: { 2.202 - return createGuardedDynamicMethodInvocation(callSiteDescriptor.getMethodType(), linkerServices, 2.203 + return createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices, 2.204 callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), methods); 2.205 } 2.206 default: { 2.207 @@ -305,16 +388,16 @@ 2.208 } 2.209 } 2.210 2.211 - private GuardedInvocation createGuardedDynamicMethodInvocation(MethodType callSiteType, 2.212 + private GuardedInvocation createGuardedDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor, 2.213 LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap){ 2.214 - final MethodHandle inv = getDynamicMethodInvocation(callSiteType, linkerServices, methodName, methodMap); 2.215 - return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteType)); 2.216 + final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap); 2.217 + return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteDescriptor.getMethodType())); 2.218 } 2.219 2.220 - private static MethodHandle getDynamicMethodInvocation(MethodType callSiteType, LinkerServices linkerServices, 2.221 - String methodName, Map<String, DynamicMethod> methodMap) { 2.222 + private static MethodHandle getDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor, 2.223 + LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap) { 2.224 final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap); 2.225 - return dynaMethod != null ? dynaMethod.getInvocation(callSiteType, linkerServices) : null; 2.226 + return dynaMethod != null ? dynaMethod.getInvocation(callSiteDescriptor, linkerServices) : null; 2.227 } 2.228 2.229 private static DynamicMethod getDynamicMethod(String methodName, Map<String, DynamicMethod> methodMap) { 2.230 @@ -322,13 +405,13 @@ 2.231 return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap); 2.232 } 2.233 2.234 - private static SimpleDynamicMethod getExplicitSignatureDynamicMethod(String methodName, 2.235 + private static SingleDynamicMethod getExplicitSignatureDynamicMethod(String methodName, 2.236 Map<String, DynamicMethod> methodsMap) { 2.237 // What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name 2.238 // to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method 2.239 // resolution works correctly in almost every situation. However, in presence of many language-specific 2.240 // conversions with a radically dynamic language, most overloaded methods will end up being constantly selected 2.241 - // at invocation time, so a programmer knowledgable of the situation might choose to pin down an exact overload 2.242 + // at invocation time, so a programmer knowledgeable of the situation might choose to pin down an exact overload 2.243 // for performance reasons. 2.244 2.245 // Is the method name lexically of the form "name(types)"? 2.246 @@ -377,8 +460,8 @@ 2.247 final MethodType setterType = type.dropParameterTypes(1, 2); 2.248 // Bind property setter handle to the expected setter type and linker services. Type is 2.249 // MethodHandle(Object, String, Object) 2.250 - final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0, setterType, 2.251 - linkerServices); 2.252 + final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0, 2.253 + CallSiteDescriptorFactory.dropParameterTypes(callSiteDescriptor, 1, 2), linkerServices); 2.254 2.255 // Cast getter to MethodHandle(O, N, V) 2.256 final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType( 2.257 @@ -415,9 +498,8 @@ 2.258 case 3: { 2.259 // Must have two arguments: target object and property value 2.260 assertParameterCount(callSiteDescriptor, 2); 2.261 - final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor.getMethodType(), 2.262 - linkerServices, callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), 2.263 - propertySetters); 2.264 + final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices, 2.265 + callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), propertySetters); 2.266 // If we have a property setter with this name, this composite operation will always stop here 2.267 if(gi != null) { 2.268 return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS); 2.269 @@ -435,14 +517,13 @@ 2.270 2.271 private static final Lookup privateLookup = new Lookup(MethodHandles.lookup()); 2.272 2.273 - private static final MethodHandle IS_ANNOTATED_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType( 2.274 - boolean.class, AnnotatedMethodHandle.class)); 2.275 - private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_HANDLE = MethodHandles.dropArguments( 2.276 - MethodHandles.constant(Object.class, null), 0, AnnotatedMethodHandle.class); 2.277 - private static final MethodHandle GET_ANNOTATED_HANDLE = privateLookup.findGetter(AnnotatedMethodHandle.class, 2.278 - "handle", MethodHandle.class); 2.279 - private static final MethodHandle GENERIC_PROPERTY_GETTER_HANDLER_INVOKER = MethodHandles.filterArguments( 2.280 - MethodHandles.invoker(MethodType.methodType(Object.class, Object.class)), 0, GET_ANNOTATED_HANDLE); 2.281 + private static final MethodHandle IS_ANNOTATED_METHOD_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType( 2.282 + boolean.class, AnnotatedDynamicMethod.class)); 2.283 + private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_METHOD = MethodHandles.dropArguments( 2.284 + MethodHandles.constant(Object.class, null), 0, AnnotatedDynamicMethod.class); 2.285 + private static final MethodHandle GET_ANNOTATED_METHOD = privateLookup.findVirtual(AnnotatedDynamicMethod.class, 2.286 + "getTarget", MethodType.methodType(MethodHandle.class, MethodHandles.Lookup.class)); 2.287 + private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class)); 2.288 2.289 private GuardedInvocationComponent getPropertyGetter(CallSiteDescriptor callSiteDescriptor, 2.290 LinkerServices linkerServices, List<String> ops) throws Exception { 2.291 @@ -455,16 +536,20 @@ 2.292 // What's below is basically: 2.293 // foldArguments(guardWithTest(isNotNull, invoke(get_handle), null|nextComponent.invocation), get_getter_handle) 2.294 // only with a bunch of method signature adjustments. Basically, retrieve method getter 2.295 - // AnnotatedMethodHandle; if it is non-null, invoke its "handle" field, otherwise either return null, 2.296 + // AnnotatedDynamicMethod; if it is non-null, invoke its "handle" field, otherwise either return null, 2.297 // or delegate to next component's invocation. 2.298 2.299 final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType( 2.300 - AnnotatedMethodHandle.class)); 2.301 - // Object(AnnotatedMethodHandle, Object)->R(AnnotatedMethodHandle, T0) 2.302 - final MethodHandle invokeHandleTyped = linkerServices.asType(GENERIC_PROPERTY_GETTER_HANDLER_INVOKER, 2.303 - MethodType.methodType(type.returnType(), AnnotatedMethodHandle.class, type.parameterType(0))); 2.304 + AnnotatedDynamicMethod.class)); 2.305 + final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments( 2.306 + GET_ANNOTATED_METHOD, 1, callSiteDescriptor.getLookup()); 2.307 + final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0, 2.308 + callSiteBoundMethodGetter); 2.309 + // Object(AnnotatedDynamicMethod, Object)->R(AnnotatedDynamicMethod, T0) 2.310 + final MethodHandle invokeHandleTyped = linkerServices.asType(callSiteBoundInvoker, 2.311 + MethodType.methodType(type.returnType(), AnnotatedDynamicMethod.class, type.parameterType(0))); 2.312 // Since it's in the target of a fold, drop the unnecessary second argument 2.313 - // R(AnnotatedMethodHandle, T0)->R(AnnotatedMethodHandle, T0, T1) 2.314 + // R(AnnotatedDynamicMethod, T0)->R(AnnotatedDynamicMethod, T0, T1) 2.315 final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2, 2.316 type.parameterType(1)); 2.317 final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, 2.318 @@ -472,19 +557,19 @@ 2.319 2.320 final MethodHandle fallbackFolded; 2.321 if(nextComponent == null) { 2.322 - // Object(AnnotatedMethodHandle)->R(AnnotatedMethodHandle, T0, T1); returns constant null 2.323 - fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_HANDLE, 1, 2.324 - type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedMethodHandle.class)); 2.325 + // Object(AnnotatedDynamicMethod)->R(AnnotatedDynamicMethod, T0, T1); returns constant null 2.326 + fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_METHOD, 1, 2.327 + type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedDynamicMethod.class)); 2.328 } else { 2.329 - // R(T0, T1)->R(AnnotatedMethodHAndle, T0, T1); adapts the next component's invocation to drop the 2.330 + // R(T0, T1)->R(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to drop the 2.331 // extra argument resulting from fold 2.332 fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(), 2.333 - 0, AnnotatedMethodHandle.class); 2.334 + 0, AnnotatedDynamicMethod.class); 2.335 } 2.336 2.337 - // fold(R(AnnotatedMethodHandle, T0, T1), AnnotatedMethodHandle(T0, T1)) 2.338 + // fold(R(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1)) 2.339 final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( 2.340 - IS_ANNOTATED_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); 2.341 + IS_ANNOTATED_METHOD_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); 2.342 if(nextComponent == null) { 2.343 return getClassGuardedInvocationComponent(compositeGetter, type); 2.344 } 2.345 @@ -494,13 +579,13 @@ 2.346 // Must have exactly one argument: receiver 2.347 assertParameterCount(callSiteDescriptor, 1); 2.348 // Fixed name 2.349 - final AnnotatedMethodHandle annGetter = propertyGetters.get(callSiteDescriptor.getNameToken( 2.350 + final AnnotatedDynamicMethod annGetter = propertyGetters.get(callSiteDescriptor.getNameToken( 2.351 CallSiteDescriptor.NAME_OPERAND)); 2.352 if(annGetter == null) { 2.353 // We have no such property, always delegate to the next component operation 2.354 return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops); 2.355 } 2.356 - final MethodHandle getter = annGetter.handle; 2.357 + final MethodHandle getter = annGetter.getInvocation(callSiteDescriptor, linkerServices); 2.358 // NOTE: since property getters (not field getters!) are no-arg, we don't have to worry about them being 2.359 // overloaded in a subclass. Therefore, we can discover the most abstract superclass that has the 2.360 // method, and use that as the guard with Guards.isInstance() for a more stably linked call site. If 2.361 @@ -508,6 +593,7 @@ 2.362 // NOTE: No delegation to the next component operation if we have a property with this name, even if its 2.363 // value is null. 2.364 final ValidationType validationType = annGetter.validationType; 2.365 + // TODO: we aren't using the type that declares the most generic getter here! 2.366 return new GuardedInvocationComponent(linkerServices.asType(getter, type), getGuard(validationType, 2.367 type), clazz, validationType); 2.368 } 2.369 @@ -623,14 +709,15 @@ 2.370 // args are dropped; this makes handles with first three args conform to "Object, String, Object" though, which is 2.371 // a typical property setter with variable name signature (target, name, value). 2.372 private static final MethodHandle GET_PROPERTY_SETTER_HANDLE = MethodHandles.dropArguments(MethodHandles.dropArguments( 2.373 - privateLookup.findOwnSpecial("getPropertySetterHandle", MethodHandle.class, MethodType.class, 2.374 + privateLookup.findOwnSpecial("getPropertySetterHandle", MethodHandle.class, CallSiteDescriptor.class, 2.375 LinkerServices.class, Object.class), 3, Object.class), 5, Object.class); 2.376 // Type is MethodHandle(MethodType, LinkerServices, Object, String, Object) 2.377 private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this); 2.378 2.379 @SuppressWarnings("unused") 2.380 - private MethodHandle getPropertySetterHandle(MethodType setterType, LinkerServices linkerServices, Object id) { 2.381 - return getDynamicMethodInvocation(setterType, linkerServices, String.valueOf(id), propertySetters); 2.382 + private MethodHandle getPropertySetterHandle(CallSiteDescriptor setterDescriptor, LinkerServices linkerServices, 2.383 + Object id) { 2.384 + return getDynamicMethodInvocation(setterDescriptor, linkerServices, String.valueOf(id), propertySetters); 2.385 } 2.386 2.387 private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial( 2.388 @@ -689,13 +776,24 @@ 2.389 return null; 2.390 } 2.391 2.392 - private static final class AnnotatedMethodHandle { 2.393 - final MethodHandle handle; 2.394 + private static final class AnnotatedDynamicMethod { 2.395 + private final SingleDynamicMethod method; 2.396 /*private*/ final ValidationType validationType; 2.397 2.398 - AnnotatedMethodHandle(MethodHandle handle, ValidationType validationType) { 2.399 - this.handle = handle; 2.400 + AnnotatedDynamicMethod(SingleDynamicMethod method, ValidationType validationType) { 2.401 + this.method = method; 2.402 this.validationType = validationType; 2.403 } 2.404 + 2.405 + MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) { 2.406 + return method.getInvocation(callSiteDescriptor, linkerServices); 2.407 + } 2.408 + 2.409 + @SuppressWarnings("unused") 2.410 + MethodHandle getTarget(MethodHandles.Lookup lookup) { 2.411 + MethodHandle inv = method.getTarget(lookup); 2.412 + assert inv != null; 2.413 + return inv; 2.414 + } 2.415 } 2.416 }
3.1 --- a/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java Wed Jul 03 14:08:00 2013 +0530 3.2 +++ b/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java Wed Jul 03 12:39:28 2013 +0200 3.3 @@ -83,7 +83,6 @@ 3.4 3.5 package jdk.internal.dynalink.beans; 3.6 3.7 -import java.lang.invoke.MethodHandle; 3.8 import java.lang.invoke.MethodType; 3.9 import java.util.LinkedList; 3.10 import java.util.List; 3.11 @@ -95,7 +94,7 @@ 3.12 * @author Attila Szegedi 3.13 */ 3.14 class ApplicableOverloadedMethods { 3.15 - private final List<MethodHandle> methods; 3.16 + private final List<SingleDynamicMethod> methods; 3.17 private final boolean varArgs; 3.18 3.19 /** 3.20 @@ -106,10 +105,10 @@ 3.21 * @param test applicability test. One of {@link #APPLICABLE_BY_SUBTYPING}, 3.22 * {@link #APPLICABLE_BY_METHOD_INVOCATION_CONVERSION}, or {@link #APPLICABLE_BY_VARIABLE_ARITY}. 3.23 */ 3.24 - ApplicableOverloadedMethods(final List<MethodHandle> methods, final MethodType callSiteType, 3.25 + ApplicableOverloadedMethods(final List<SingleDynamicMethod> methods, final MethodType callSiteType, 3.26 final ApplicabilityTest test) { 3.27 this.methods = new LinkedList<>(); 3.28 - for(MethodHandle m: methods) { 3.29 + for(SingleDynamicMethod m: methods) { 3.30 if(test.isApplicable(callSiteType, m)) { 3.31 this.methods.add(m); 3.32 } 3.33 @@ -122,7 +121,7 @@ 3.34 * 3.35 * @return list of all methods. 3.36 */ 3.37 - List<MethodHandle> getMethods() { 3.38 + List<SingleDynamicMethod> getMethods() { 3.39 return methods; 3.40 } 3.41 3.42 @@ -131,12 +130,12 @@ 3.43 * 3.44 * @return a list of maximally specific methods. 3.45 */ 3.46 - List<MethodHandle> findMaximallySpecificMethods() { 3.47 + List<SingleDynamicMethod> findMaximallySpecificMethods() { 3.48 return MaximallySpecific.getMaximallySpecificMethods(methods, varArgs); 3.49 } 3.50 3.51 abstract static class ApplicabilityTest { 3.52 - abstract boolean isApplicable(MethodType callSiteType, MethodHandle method); 3.53 + abstract boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method); 3.54 } 3.55 3.56 /** 3.57 @@ -144,8 +143,8 @@ 3.58 */ 3.59 static final ApplicabilityTest APPLICABLE_BY_SUBTYPING = new ApplicabilityTest() { 3.60 @Override 3.61 - boolean isApplicable(MethodType callSiteType, MethodHandle method) { 3.62 - final MethodType methodType = method.type(); 3.63 + boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) { 3.64 + final MethodType methodType = method.getMethodType(); 3.65 final int methodArity = methodType.parameterCount(); 3.66 if(methodArity != callSiteType.parameterCount()) { 3.67 return false; 3.68 @@ -166,8 +165,8 @@ 3.69 */ 3.70 static final ApplicabilityTest APPLICABLE_BY_METHOD_INVOCATION_CONVERSION = new ApplicabilityTest() { 3.71 @Override 3.72 - boolean isApplicable(MethodType callSiteType, MethodHandle method) { 3.73 - final MethodType methodType = method.type(); 3.74 + boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) { 3.75 + final MethodType methodType = method.getMethodType(); 3.76 final int methodArity = methodType.parameterCount(); 3.77 if(methodArity != callSiteType.parameterCount()) { 3.78 return false; 3.79 @@ -189,11 +188,11 @@ 3.80 */ 3.81 static final ApplicabilityTest APPLICABLE_BY_VARIABLE_ARITY = new ApplicabilityTest() { 3.82 @Override 3.83 - boolean isApplicable(MethodType callSiteType, MethodHandle method) { 3.84 - if(!method.isVarargsCollector()) { 3.85 + boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) { 3.86 + if(!method.isVarArgs()) { 3.87 return false; 3.88 } 3.89 - final MethodType methodType = method.type(); 3.90 + final MethodType methodType = method.getMethodType(); 3.91 final int methodArity = methodType.parameterCount(); 3.92 final int fixArity = methodArity - 1; 3.93 final int callSiteArity = callSiteType.parameterCount();
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java Wed Jul 03 12:39:28 2013 +0200 4.3 @@ -0,0 +1,148 @@ 4.4 +/* 4.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. Oracle designates this 4.11 + * particular file as subject to the "Classpath" exception as provided 4.12 + * by Oracle in the LICENSE file that accompanied this code. 4.13 + * 4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.17 + * version 2 for more details (a copy is included in the LICENSE file that 4.18 + * accompanied this code). 4.19 + * 4.20 + * You should have received a copy of the GNU General Public License version 4.21 + * 2 along with this work; if not, write to the Free Software Foundation, 4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.23 + * 4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.25 + * or visit www.oracle.com if you need additional information or have any 4.26 + * questions. 4.27 + */ 4.28 + 4.29 +/* 4.30 + * This file is available under and governed by the GNU General Public 4.31 + * License version 2 only, as published by the Free Software Foundation. 4.32 + * However, the following notice accompanied the original version of this 4.33 + * file, and Oracle licenses the original version of this file under the BSD 4.34 + * license: 4.35 + */ 4.36 +/* 4.37 + Copyright 2009-2013 Attila Szegedi 4.38 + 4.39 + Licensed under both the Apache License, Version 2.0 (the "Apache License") 4.40 + and the BSD License (the "BSD License"), with licensee being free to 4.41 + choose either of the two at their discretion. 4.42 + 4.43 + You may not use this file except in compliance with either the Apache 4.44 + License or the BSD License. 4.45 + 4.46 + If you choose to use this file in compliance with the Apache License, the 4.47 + following notice applies to you: 4.48 + 4.49 + You may obtain a copy of the Apache License at 4.50 + 4.51 + http://www.apache.org/licenses/LICENSE-2.0 4.52 + 4.53 + Unless required by applicable law or agreed to in writing, software 4.54 + distributed under the License is distributed on an "AS IS" BASIS, 4.55 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 4.56 + implied. See the License for the specific language governing 4.57 + permissions and limitations under the License. 4.58 + 4.59 + If you choose to use this file in compliance with the BSD License, the 4.60 + following notice applies to you: 4.61 + 4.62 + Redistribution and use in source and binary forms, with or without 4.63 + modification, are permitted provided that the following conditions are 4.64 + met: 4.65 + * Redistributions of source code must retain the above copyright 4.66 + notice, this list of conditions and the following disclaimer. 4.67 + * Redistributions in binary form must reproduce the above copyright 4.68 + notice, this list of conditions and the following disclaimer in the 4.69 + documentation and/or other materials provided with the distribution. 4.70 + * Neither the name of the copyright holder nor the names of 4.71 + contributors may be used to endorse or promote products derived from 4.72 + this software without specific prior written permission. 4.73 + 4.74 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 4.75 + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 4.76 + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 4.77 + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER 4.78 + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 4.79 + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 4.80 + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 4.81 + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 4.82 + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 4.83 + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 4.84 + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4.85 +*/ 4.86 + 4.87 +package jdk.internal.dynalink.beans; 4.88 + 4.89 +import java.lang.annotation.Annotation; 4.90 +import java.lang.reflect.AccessibleObject; 4.91 +import sun.reflect.CallerSensitive; 4.92 + 4.93 +/** 4.94 + * Utility class that determines if a method or constructor is caller sensitive. It actually encapsulates two different 4.95 + * strategies for determining caller sensitivity; a more robust one that works if Dynalink runs as code with access 4.96 + * to {@code sun.reflect} package, and an unprivileged one that is used when Dynalink doesn't have access to that 4.97 + * package. Note that even the unprivileged strategy is ordinarily robust, but it relies on the {@code toString} method 4.98 + * of the annotation. If an attacker were to use a different annotation to spoof the string representation of the 4.99 + * {@code CallerSensitive} annotation, they could designate their own methods as caller sensitive. This however does not 4.100 + * escalate privileges, only causes Dynalink to never cache method handles for such methods, so all it would do would 4.101 + * decrease the performance in linking such methods. In the opposite case when an attacker could trick Dynalink into not 4.102 + * recognizing genuine {@code CallerSensitive} annotations, Dynalink would treat caller sensitive methods as ordinary 4.103 + * methods, and would cache them bound to a zero-privilege delegate as the caller (just what Dynalink did before it 4.104 + * could handle caller-sensitive methods). That would practically render caller-sensitive methods exposed through 4.105 + * Dynalink unusable, but again, can not lead to any privilege escalations. Therefore, even the less robust unprivileged 4.106 + * strategy is safe; the worst thing a successful attack against it can achieve is slight reduction in Dynalink-exposed 4.107 + * functionality or performance. 4.108 + */ 4.109 +public class CallerSensitiveDetector { 4.110 + 4.111 + private static final DetectionStrategy DETECTION_STRATEGY = getDetectionStrategy(); 4.112 + 4.113 + static boolean isCallerSensitive(AccessibleObject ao) { 4.114 + return DETECTION_STRATEGY.isCallerSensitive(ao); 4.115 + } 4.116 + 4.117 + private static DetectionStrategy getDetectionStrategy() { 4.118 + try { 4.119 + return new PrivilegedDetectionStrategy(); 4.120 + } catch(Throwable t) { 4.121 + return new UnprivilegedDetectionStrategy(); 4.122 + } 4.123 + } 4.124 + 4.125 + private abstract static class DetectionStrategy { 4.126 + abstract boolean isCallerSensitive(AccessibleObject ao); 4.127 + } 4.128 + 4.129 + private static class PrivilegedDetectionStrategy extends DetectionStrategy { 4.130 + private static final Class<? extends Annotation> CALLER_SENSITIVE_ANNOTATION_CLASS = CallerSensitive.class; 4.131 + 4.132 + @Override 4.133 + boolean isCallerSensitive(AccessibleObject ao) { 4.134 + return ao.getAnnotation(CALLER_SENSITIVE_ANNOTATION_CLASS) != null; 4.135 + } 4.136 + } 4.137 + 4.138 + private static class UnprivilegedDetectionStrategy extends DetectionStrategy { 4.139 + private static final String CALLER_SENSITIVE_ANNOTATION_STRING = "@sun.reflect.CallerSensitive()"; 4.140 + 4.141 + @Override 4.142 + boolean isCallerSensitive(AccessibleObject o) { 4.143 + for(Annotation a: o.getAnnotations()) { 4.144 + if(String.valueOf(a).equals(CALLER_SENSITIVE_ANNOTATION_STRING)) { 4.145 + return true; 4.146 + } 4.147 + } 4.148 + return false; 4.149 + } 4.150 + } 4.151 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Wed Jul 03 12:39:28 2013 +0200 5.3 @@ -0,0 +1,158 @@ 5.4 +/* 5.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. Oracle designates this 5.11 + * particular file as subject to the "Classpath" exception as provided 5.12 + * by Oracle in the LICENSE file that accompanied this code. 5.13 + * 5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.17 + * version 2 for more details (a copy is included in the LICENSE file that 5.18 + * accompanied this code). 5.19 + * 5.20 + * You should have received a copy of the GNU General Public License version 5.21 + * 2 along with this work; if not, write to the Free Software Foundation, 5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.23 + * 5.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.25 + * or visit www.oracle.com if you need additional information or have any 5.26 + * questions. 5.27 + */ 5.28 + 5.29 +/* 5.30 + * This file is available under and governed by the GNU General Public 5.31 + * License version 2 only, as published by the Free Software Foundation. 5.32 + * However, the following notice accompanied the original version of this 5.33 + * file, and Oracle licenses the original version of this file under the BSD 5.34 + * license: 5.35 + */ 5.36 +/* 5.37 + Copyright 2009-2013 Attila Szegedi 5.38 + 5.39 + Licensed under both the Apache License, Version 2.0 (the "Apache License") 5.40 + and the BSD License (the "BSD License"), with licensee being free to 5.41 + choose either of the two at their discretion. 5.42 + 5.43 + You may not use this file except in compliance with either the Apache 5.44 + License or the BSD License. 5.45 + 5.46 + If you choose to use this file in compliance with the Apache License, the 5.47 + following notice applies to you: 5.48 + 5.49 + You may obtain a copy of the Apache License at 5.50 + 5.51 + http://www.apache.org/licenses/LICENSE-2.0 5.52 + 5.53 + Unless required by applicable law or agreed to in writing, software 5.54 + distributed under the License is distributed on an "AS IS" BASIS, 5.55 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 5.56 + implied. See the License for the specific language governing 5.57 + permissions and limitations under the License. 5.58 + 5.59 + If you choose to use this file in compliance with the BSD License, the 5.60 + following notice applies to you: 5.61 + 5.62 + Redistribution and use in source and binary forms, with or without 5.63 + modification, are permitted provided that the following conditions are 5.64 + met: 5.65 + * Redistributions of source code must retain the above copyright 5.66 + notice, this list of conditions and the following disclaimer. 5.67 + * Redistributions in binary form must reproduce the above copyright 5.68 + notice, this list of conditions and the following disclaimer in the 5.69 + documentation and/or other materials provided with the distribution. 5.70 + * Neither the name of the copyright holder nor the names of 5.71 + contributors may be used to endorse or promote products derived from 5.72 + this software without specific prior written permission. 5.73 + 5.74 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 5.75 + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 5.76 + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 5.77 + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER 5.78 + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 5.79 + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 5.80 + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 5.81 + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 5.82 + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 5.83 + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 5.84 + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5.85 +*/ 5.86 + 5.87 +package jdk.internal.dynalink.beans; 5.88 + 5.89 +import java.lang.invoke.MethodHandle; 5.90 +import java.lang.invoke.MethodHandles; 5.91 +import java.lang.invoke.MethodType; 5.92 +import java.lang.reflect.AccessibleObject; 5.93 +import java.lang.reflect.Constructor; 5.94 +import java.lang.reflect.Member; 5.95 +import java.lang.reflect.Method; 5.96 +import java.lang.reflect.Modifier; 5.97 +import jdk.internal.dynalink.support.Lookup; 5.98 + 5.99 +/** 5.100 + * A dynamic method bound to exactly one Java method or constructor that is caller sensitive. Since the target method is 5.101 + * caller sensitive, it doesn't cache a method handle but rather uses the passed lookup object in 5.102 + * {@link #getTarget(java.lang.invoke.MethodHandles.Lookup)} to unreflect a method handle from the reflective member on 5.103 + * every request. 5.104 + * 5.105 + * @author Attila Szegedi 5.106 + */ 5.107 +class CallerSensitiveDynamicMethod extends SingleDynamicMethod { 5.108 + // Typed as "AccessibleObject" as it can be either a method or a constructor. 5.109 + // If we were Java8-only, we could use java.lang.reflect.Executable 5.110 + private final AccessibleObject target; 5.111 + private final MethodType type; 5.112 + 5.113 + public CallerSensitiveDynamicMethod(AccessibleObject target) { 5.114 + super(getName(target)); 5.115 + this.target = target; 5.116 + this.type = getMethodType(target); 5.117 + } 5.118 + 5.119 + private static String getName(AccessibleObject target) { 5.120 + final Member m = (Member)target; 5.121 + return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(), 5.122 + m.getName())); 5.123 + } 5.124 + 5.125 + @Override 5.126 + MethodType getMethodType() { 5.127 + return type; 5.128 + } 5.129 + 5.130 + private static MethodType getMethodType(AccessibleObject ao) { 5.131 + final boolean isMethod = ao instanceof Method; 5.132 + final Class<?> rtype = isMethod ? ((Method)ao).getReturnType() : ((Constructor<?>)ao).getDeclaringClass(); 5.133 + final Class<?>[] ptypes = isMethod ? ((Method)ao).getParameterTypes() : ((Constructor<?>)ao).getParameterTypes(); 5.134 + final MethodType type = MethodType.methodType(rtype, ptypes); 5.135 + final Member m = (Member)ao; 5.136 + return type.insertParameterTypes(0, 5.137 + isMethod ? 5.138 + Modifier.isStatic(m.getModifiers()) ? 5.139 + Object.class : 5.140 + m.getDeclaringClass() : 5.141 + StaticClass.class); 5.142 + } 5.143 + 5.144 + @Override 5.145 + boolean isVarArgs() { 5.146 + return target instanceof Method ? ((Method)target).isVarArgs() : ((Constructor<?>)target).isVarArgs(); 5.147 + } 5.148 + 5.149 + @Override 5.150 + MethodHandle getTarget(MethodHandles.Lookup lookup) { 5.151 + if(target instanceof Method) { 5.152 + final MethodHandle mh = Lookup.unreflect(lookup, (Method)target); 5.153 + if(Modifier.isStatic(((Member)target).getModifiers())) { 5.154 + return StaticClassIntrospector.editStaticMethodHandle(mh); 5.155 + } 5.156 + return mh; 5.157 + } 5.158 + return StaticClassIntrospector.editConstructorMethodHandle(Lookup.unreflectConstructor(lookup, 5.159 + (Constructor<?>)target)); 5.160 + } 5.161 +}
6.1 --- a/src/jdk/internal/dynalink/beans/ClassString.java Wed Jul 03 14:08:00 2013 +0530 6.2 +++ b/src/jdk/internal/dynalink/beans/ClassString.java Wed Jul 03 12:39:28 2013 +0200 6.3 @@ -155,8 +155,8 @@ 6.4 } 6.5 6.6 List<MethodHandle> getMaximallySpecifics(List<MethodHandle> methods, LinkerServices linkerServices, boolean varArg) { 6.7 - return MaximallySpecific.getMaximallySpecificMethods(getApplicables(methods, linkerServices, varArg), varArg, 6.8 - classes, linkerServices); 6.9 + return MaximallySpecific.getMaximallySpecificMethodHandles(getApplicables(methods, linkerServices, varArg), 6.10 + varArg, classes, linkerServices); 6.11 } 6.12 6.13 /**
7.1 --- a/src/jdk/internal/dynalink/beans/DynamicMethod.java Wed Jul 03 14:08:00 2013 +0530 7.2 +++ b/src/jdk/internal/dynalink/beans/DynamicMethod.java Wed Jul 03 12:39:28 2013 +0200 7.3 @@ -84,8 +84,7 @@ 7.4 package jdk.internal.dynalink.beans; 7.5 7.6 import java.lang.invoke.MethodHandle; 7.7 -import java.lang.invoke.MethodType; 7.8 -import java.util.StringTokenizer; 7.9 +import jdk.internal.dynalink.CallSiteDescriptor; 7.10 import jdk.internal.dynalink.linker.LinkerServices; 7.11 7.12 /** 7.13 @@ -116,45 +115,28 @@ 7.14 * is a variable arguments (vararg) method, it will pack the extra arguments in an array before the invocation of 7.15 * the underlying method if it is not already done. 7.16 * 7.17 - * @param callSiteType the method type at a call site 7.18 + * @param callSiteDescriptor the descriptor of the call site 7.19 * @param linkerServices linker services. Used for language-specific type conversions. 7.20 * @return an invocation suitable for calling the method from the specified call site. 7.21 */ 7.22 - abstract MethodHandle getInvocation(MethodType callSiteType, LinkerServices linkerServices); 7.23 + abstract MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices); 7.24 7.25 /** 7.26 - * Returns a simple dynamic method representing a single underlying Java method (possibly selected among several 7.27 + * Returns a single dynamic method representing a single underlying Java method (possibly selected among several 7.28 * overloads) with formal parameter types exactly matching the passed signature. 7.29 * @param paramTypes the comma-separated list of requested parameter type names. The names will match both 7.30 * qualified and unqualified type names. 7.31 - * @return a simple dynamic method representing a single underlying Java method, or null if none of the Java methods 7.32 + * @return a single dynamic method representing a single underlying Java method, or null if none of the Java methods 7.33 * behind this dynamic method exactly match the requested parameter types. 7.34 */ 7.35 - abstract SimpleDynamicMethod getMethodForExactParamTypes(String paramTypes); 7.36 + abstract SingleDynamicMethod getMethodForExactParamTypes(String paramTypes); 7.37 7.38 /** 7.39 - * True if this dynamic method already contains a method handle with an identical signature as the passed in method 7.40 - * handle. 7.41 - * @param mh the method handle to check 7.42 - * @return true if it already contains an equivalent method handle. 7.43 + * True if this dynamic method already contains a method with an identical signature as the passed in method. 7.44 + * @param method the method to check 7.45 + * @return true if it already contains an equivalent method. 7.46 */ 7.47 - abstract boolean contains(MethodHandle mh); 7.48 - 7.49 - static boolean typeMatchesDescription(String paramTypes, MethodType type) { 7.50 - final StringTokenizer tok = new StringTokenizer(paramTypes, ", "); 7.51 - for(int i = 1; i < type.parameterCount(); ++i) { // i = 1 as we ignore the receiver 7.52 - if(!(tok.hasMoreTokens() && typeNameMatches(tok.nextToken(), type.parameterType(i)))) { 7.53 - return false; 7.54 - } 7.55 - } 7.56 - return !tok.hasMoreTokens(); 7.57 - } 7.58 - 7.59 - private static boolean typeNameMatches(String typeName, Class<?> type) { 7.60 - final int lastDot = typeName.lastIndexOf('.'); 7.61 - final String fullTypeName = type.getCanonicalName(); 7.62 - return lastDot != -1 && fullTypeName.endsWith(typeName.substring(lastDot)) || typeName.equals(fullTypeName); 7.63 - } 7.64 + abstract boolean contains(SingleDynamicMethod method); 7.65 7.66 static String getClassAndMethodName(Class<?> clazz, String name) { 7.67 final String clazzName = clazz.getCanonicalName();
8.1 --- a/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java Wed Jul 03 14:08:00 2013 +0530 8.2 +++ b/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java Wed Jul 03 12:39:28 2013 +0200 8.3 @@ -85,12 +85,12 @@ 8.4 8.5 import java.lang.invoke.MethodHandle; 8.6 import java.lang.invoke.MethodHandles; 8.7 -import java.lang.invoke.MethodType; 8.8 import jdk.internal.dynalink.CallSiteDescriptor; 8.9 import jdk.internal.dynalink.linker.GuardedInvocation; 8.10 import jdk.internal.dynalink.linker.LinkRequest; 8.11 import jdk.internal.dynalink.linker.LinkerServices; 8.12 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; 8.13 +import jdk.internal.dynalink.support.CallSiteDescriptorFactory; 8.14 import jdk.internal.dynalink.support.Guards; 8.15 8.16 /** 8.17 @@ -110,19 +110,18 @@ 8.18 return null; 8.19 } 8.20 final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); 8.21 - if(desc.getNameTokenCount() != 2 && desc.getNameToken(CallSiteDescriptor.SCHEME) != "dyn") { 8.22 + if(desc.getNameTokenCount() != 2 && desc.getNameToken(CallSiteDescriptor.SCHEME) != "dyn") { 8.23 return null; 8.24 } 8.25 final String operator = desc.getNameToken(CallSiteDescriptor.OPERATOR); 8.26 if(operator == "call") { 8.27 - final MethodType type = desc.getMethodType(); 8.28 - final MethodHandle invocation = ((DynamicMethod)receiver).getInvocation(type.dropParameterTypes(0, 1), 8.29 - linkerServices); 8.30 + final MethodHandle invocation = ((DynamicMethod)receiver).getInvocation( 8.31 + CallSiteDescriptorFactory.dropParameterTypes(desc, 0, 1), linkerServices); 8.32 if(invocation == null) { 8.33 return null; 8.34 } 8.35 - return new GuardedInvocation(MethodHandles.dropArguments(invocation, 0, type.parameterType(0)), 8.36 - Guards.getIdentityGuard(receiver)); 8.37 + return new GuardedInvocation(MethodHandles.dropArguments(invocation, 0, 8.38 + desc.getMethodType().parameterType(0)), Guards.getIdentityGuard(receiver)); 8.39 } 8.40 return null; 8.41 }
9.1 --- a/src/jdk/internal/dynalink/beans/FacetIntrospector.java Wed Jul 03 14:08:00 2013 +0530 9.2 +++ b/src/jdk/internal/dynalink/beans/FacetIntrospector.java Wed Jul 03 12:39:28 2013 +0200 9.3 @@ -167,10 +167,6 @@ 9.4 return editMethodHandle(SafeUnreflector.unreflectSetter(field)); 9.5 } 9.6 9.7 - MethodHandle unreflect(Method method) { 9.8 - return editMethodHandle(SafeUnreflector.unreflect(method)); 9.9 - } 9.10 - 9.11 /** 9.12 * Returns an edited method handle. A facet might need to edit an unreflected method handle before it is usable with 9.13 * the facet. By default, returns the passed method handle unchanged. The class' static facet will introduce a
10.1 --- a/src/jdk/internal/dynalink/beans/MaximallySpecific.java Wed Jul 03 14:08:00 2013 +0530 10.2 +++ b/src/jdk/internal/dynalink/beans/MaximallySpecific.java Wed Jul 03 12:39:28 2013 +0200 10.3 @@ -105,10 +105,58 @@ 10.4 * @param varArgs whether to assume the methods are varargs 10.5 * @return the list of maximally specific methods. 10.6 */ 10.7 - static List<MethodHandle> getMaximallySpecificMethods(List<MethodHandle> methods, boolean varArgs) { 10.8 - return getMaximallySpecificMethods(methods, varArgs, null, null); 10.9 + static List<SingleDynamicMethod> getMaximallySpecificMethods(List<SingleDynamicMethod> methods, boolean varArgs) { 10.10 + return getMaximallySpecificSingleDynamicMethods(methods, varArgs, null, null); 10.11 } 10.12 10.13 + private abstract static class MethodTypeGetter<T> { 10.14 + abstract MethodType getMethodType(T t); 10.15 + } 10.16 + 10.17 + private static final MethodTypeGetter<MethodHandle> METHOD_HANDLE_TYPE_GETTER = 10.18 + new MethodTypeGetter<MethodHandle>() { 10.19 + @Override 10.20 + MethodType getMethodType(MethodHandle t) { 10.21 + return t.type(); 10.22 + } 10.23 + }; 10.24 + 10.25 + private static final MethodTypeGetter<SingleDynamicMethod> DYNAMIC_METHOD_TYPE_GETTER = 10.26 + new MethodTypeGetter<SingleDynamicMethod>() { 10.27 + @Override 10.28 + MethodType getMethodType(SingleDynamicMethod t) { 10.29 + return t.getMethodType(); 10.30 + } 10.31 + }; 10.32 + 10.33 + /** 10.34 + * Given a list of methods handles, returns a list of maximally specific methods, applying language-runtime 10.35 + * specific conversion preferences. 10.36 + * 10.37 + * @param methods the list of method handles 10.38 + * @param varArgs whether to assume the method handles are varargs 10.39 + * @param argTypes concrete argument types for the invocation 10.40 + * @return the list of maximally specific method handles. 10.41 + */ 10.42 + static List<MethodHandle> getMaximallySpecificMethodHandles(List<MethodHandle> methods, boolean varArgs, 10.43 + Class<?>[] argTypes, LinkerServices ls) { 10.44 + return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, METHOD_HANDLE_TYPE_GETTER); 10.45 + } 10.46 + 10.47 + /** 10.48 + * Given a list of methods, returns a list of maximally specific methods, applying language-runtime specific 10.49 + * conversion preferences. 10.50 + * 10.51 + * @param methods the list of methods 10.52 + * @param varArgs whether to assume the methods are varargs 10.53 + * @param argTypes concrete argument types for the invocation 10.54 + * @return the list of maximally specific methods. 10.55 + */ 10.56 + static List<SingleDynamicMethod> getMaximallySpecificSingleDynamicMethods(List<SingleDynamicMethod> methods, 10.57 + boolean varArgs, Class<?>[] argTypes, LinkerServices ls) { 10.58 + return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, DYNAMIC_METHOD_TYPE_GETTER); 10.59 + } 10.60 + 10.61 /** 10.62 * Given a list of methods, returns a list of maximally specific methods, applying language-runtime specific 10.63 * conversion preferences. 10.64 @@ -118,18 +166,18 @@ 10.65 * @param argTypes concrete argument types for the invocation 10.66 * @return the list of maximally specific methods. 10.67 */ 10.68 - static List<MethodHandle> getMaximallySpecificMethods(List<MethodHandle> methods, boolean varArgs, 10.69 - Class<?>[] argTypes, LinkerServices ls) { 10.70 + private static <T> List<T> getMaximallySpecificMethods(List<T> methods, boolean varArgs, 10.71 + Class<?>[] argTypes, LinkerServices ls, MethodTypeGetter<T> methodTypeGetter) { 10.72 if(methods.size() < 2) { 10.73 return methods; 10.74 } 10.75 - final LinkedList<MethodHandle> maximals = new LinkedList<>(); 10.76 - for(MethodHandle m: methods) { 10.77 - final MethodType methodType = m.type(); 10.78 + final LinkedList<T> maximals = new LinkedList<>(); 10.79 + for(T m: methods) { 10.80 + final MethodType methodType = methodTypeGetter.getMethodType(m); 10.81 boolean lessSpecific = false; 10.82 - for(Iterator<MethodHandle> maximal = maximals.iterator(); maximal.hasNext();) { 10.83 - final MethodHandle max = maximal.next(); 10.84 - switch(isMoreSpecific(methodType, max.type(), varArgs, argTypes, ls)) { 10.85 + for(Iterator<T> maximal = maximals.iterator(); maximal.hasNext();) { 10.86 + final T max = maximal.next(); 10.87 + switch(isMoreSpecific(methodType, methodTypeGetter.getMethodType(max), varArgs, argTypes, ls)) { 10.88 case TYPE_1_BETTER: { 10.89 maximal.remove(); 10.90 break;
11.1 --- a/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Wed Jul 03 14:08:00 2013 +0530 11.2 +++ b/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Wed Jul 03 12:39:28 2013 +0200 11.3 @@ -84,16 +84,21 @@ 11.4 package jdk.internal.dynalink.beans; 11.5 11.6 import java.lang.invoke.MethodHandle; 11.7 +import java.lang.invoke.MethodHandles; 11.8 import java.lang.invoke.MethodType; 11.9 +import java.util.ArrayList; 11.10 import java.util.Iterator; 11.11 import java.util.LinkedList; 11.12 import java.util.List; 11.13 +import jdk.internal.dynalink.CallSiteDescriptor; 11.14 import jdk.internal.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest; 11.15 import jdk.internal.dynalink.linker.LinkerServices; 11.16 import jdk.internal.dynalink.support.TypeUtilities; 11.17 11.18 /** 11.19 - * Represents an overloaded method. 11.20 + * Represents a group of {@link SingleDynamicMethod} objects that represents all overloads of a particular name (or all 11.21 + * constructors) for a particular class. Correctly handles overload resolution, variable arity methods, and caller 11.22 + * sensitive methods within the overloads. 11.23 * 11.24 * @author Attila Szegedi 11.25 */ 11.26 @@ -101,7 +106,7 @@ 11.27 /** 11.28 * Holds a list of all methods. 11.29 */ 11.30 - private final LinkedList<MethodHandle> methods; 11.31 + private final LinkedList<SingleDynamicMethod> methods; 11.32 private final ClassLoader classLoader; 11.33 11.34 /** 11.35 @@ -111,21 +116,22 @@ 11.36 * @param name the name of the method 11.37 */ 11.38 OverloadedDynamicMethod(Class<?> clazz, String name) { 11.39 - this(new LinkedList<MethodHandle>(), clazz.getClassLoader(), getClassAndMethodName(clazz, name)); 11.40 + this(new LinkedList<SingleDynamicMethod>(), clazz.getClassLoader(), getClassAndMethodName(clazz, name)); 11.41 } 11.42 11.43 - private OverloadedDynamicMethod(LinkedList<MethodHandle> methods, ClassLoader classLoader, String name) { 11.44 + private OverloadedDynamicMethod(LinkedList<SingleDynamicMethod> methods, ClassLoader classLoader, String name) { 11.45 super(name); 11.46 this.methods = methods; 11.47 this.classLoader = classLoader; 11.48 } 11.49 11.50 @Override 11.51 - SimpleDynamicMethod getMethodForExactParamTypes(String paramTypes) { 11.52 - final LinkedList<MethodHandle> matchingMethods = new LinkedList<>(); 11.53 - for(MethodHandle method: methods) { 11.54 - if(typeMatchesDescription(paramTypes, method.type())) { 11.55 - matchingMethods.add(method); 11.56 + SingleDynamicMethod getMethodForExactParamTypes(String paramTypes) { 11.57 + final LinkedList<SingleDynamicMethod> matchingMethods = new LinkedList<>(); 11.58 + for(SingleDynamicMethod method: methods) { 11.59 + final SingleDynamicMethod matchingMethod = method.getMethodForExactParamTypes(paramTypes); 11.60 + if(matchingMethod != null) { 11.61 + matchingMethods.add(matchingMethod); 11.62 } 11.63 } 11.64 switch(matchingMethods.size()) { 11.65 @@ -133,8 +139,7 @@ 11.66 return null; 11.67 } 11.68 case 1: { 11.69 - final MethodHandle target = matchingMethods.get(0); 11.70 - return new SimpleDynamicMethod(target, SimpleDynamicMethod.getMethodNameWithSignature(target, getName())); 11.71 + return matchingMethods.getFirst(); 11.72 } 11.73 default: { 11.74 throw new BootstrapMethodError("Can't choose among " + matchingMethods + " for argument types " 11.75 @@ -144,7 +149,8 @@ 11.76 } 11.77 11.78 @Override 11.79 - public MethodHandle getInvocation(final MethodType callSiteType, final LinkerServices linkerServices) { 11.80 + public MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { 11.81 + final MethodType callSiteType = callSiteDescriptor.getMethodType(); 11.82 // First, find all methods applicable to the call site by subtyping (JLS 15.12.2.2) 11.83 final ApplicableOverloadedMethods subtypingApplicables = getApplicables(callSiteType, 11.84 ApplicableOverloadedMethods.APPLICABLE_BY_SUBTYPING); 11.85 @@ -156,7 +162,7 @@ 11.86 ApplicableOverloadedMethods.APPLICABLE_BY_VARIABLE_ARITY); 11.87 11.88 // Find the methods that are maximally specific based on the call site signature 11.89 - List<MethodHandle> maximallySpecifics = subtypingApplicables.findMaximallySpecificMethods(); 11.90 + List<SingleDynamicMethod> maximallySpecifics = subtypingApplicables.findMaximallySpecificMethods(); 11.91 if(maximallySpecifics.isEmpty()) { 11.92 maximallySpecifics = methodInvocationApplicables.findMaximallySpecificMethods(); 11.93 if(maximallySpecifics.isEmpty()) { 11.94 @@ -171,12 +177,12 @@ 11.95 // (Object, Object), and we have a method whose parameter types are (String, int). None of the JLS applicability 11.96 // rules will trigger, but we must consider the method, as it can be the right match for a concrete invocation. 11.97 @SuppressWarnings({ "unchecked", "rawtypes" }) 11.98 - final List<MethodHandle> invokables = (List)methods.clone(); 11.99 + final List<SingleDynamicMethod> invokables = (List)methods.clone(); 11.100 invokables.removeAll(subtypingApplicables.getMethods()); 11.101 invokables.removeAll(methodInvocationApplicables.getMethods()); 11.102 invokables.removeAll(variableArityApplicables.getMethods()); 11.103 - for(final Iterator<MethodHandle> it = invokables.iterator(); it.hasNext();) { 11.104 - final MethodHandle m = it.next(); 11.105 + for(final Iterator<SingleDynamicMethod> it = invokables.iterator(); it.hasNext();) { 11.106 + final SingleDynamicMethod m = it.next(); 11.107 if(!isApplicableDynamically(linkerServices, callSiteType, m)) { 11.108 it.remove(); 11.109 } 11.110 @@ -199,54 +205,45 @@ 11.111 } 11.112 case 1: { 11.113 // Very lucky, we ended up with a single candidate method handle based on the call site signature; we 11.114 - // can link it very simply by delegating to a SimpleDynamicMethod. 11.115 - final MethodHandle mh = invokables.iterator().next(); 11.116 - return new SimpleDynamicMethod(mh).getInvocation(callSiteType, linkerServices); 11.117 + // can link it very simply by delegating to the SingleDynamicMethod. 11.118 + invokables.iterator().next().getInvocation(callSiteDescriptor, linkerServices); 11.119 } 11.120 default: { 11.121 // We have more than one candidate. We have no choice but to link to a method that resolves overloads on 11.122 // every invocation (alternatively, we could opportunistically link the one method that resolves for the 11.123 // current arguments, but we'd need to install a fairly complex guard for that and when it'd fail, we'd 11.124 - // go back all the way to candidate selection. 11.125 - // TODO: cache per call site type 11.126 - return new OverloadedMethod(invokables, this, callSiteType, linkerServices).getInvoker(); 11.127 + // go back all the way to candidate selection. Note that we're resolving any potential caller sensitive 11.128 + // methods here to their handles, as the OverloadedMethod instance is specific to a call site, so it 11.129 + // has an already determined Lookup. 11.130 + final List<MethodHandle> methodHandles = new ArrayList<>(invokables.size()); 11.131 + final MethodHandles.Lookup lookup = callSiteDescriptor.getLookup(); 11.132 + for(SingleDynamicMethod method: invokables) { 11.133 + methodHandles.add(method.getTarget(lookup)); 11.134 + } 11.135 + return new OverloadedMethod(methodHandles, this, callSiteType, linkerServices).getInvoker(); 11.136 } 11.137 } 11.138 11.139 } 11.140 11.141 @Override 11.142 - public boolean contains(MethodHandle mh) { 11.143 - final MethodType type = mh.type(); 11.144 - for(MethodHandle method: methods) { 11.145 - if(typesEqualNoReceiver(type, method.type())) { 11.146 + public boolean contains(SingleDynamicMethod m) { 11.147 + for(SingleDynamicMethod method: methods) { 11.148 + if(method.contains(m)) { 11.149 return true; 11.150 } 11.151 } 11.152 return false; 11.153 } 11.154 11.155 - private static boolean typesEqualNoReceiver(MethodType type1, MethodType type2) { 11.156 - final int pc = type1.parameterCount(); 11.157 - if(pc != type2.parameterCount()) { 11.158 - return false; 11.159 - } 11.160 - for(int i = 1; i < pc; ++i) { // i = 1: ignore receiver 11.161 - if(type1.parameterType(i) != type2.parameterType(i)) { 11.162 - return false; 11.163 - } 11.164 - } 11.165 - return true; 11.166 - } 11.167 - 11.168 ClassLoader getClassLoader() { 11.169 return classLoader; 11.170 } 11.171 11.172 private static boolean isApplicableDynamically(LinkerServices linkerServices, MethodType callSiteType, 11.173 - MethodHandle m) { 11.174 - final MethodType methodType = m.type(); 11.175 - final boolean varArgs = m.isVarargsCollector(); 11.176 + SingleDynamicMethod m) { 11.177 + final MethodType methodType = m.getMethodType(); 11.178 + final boolean varArgs = m.isVarArgs(); 11.179 final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0); 11.180 final int callSiteArgLen = callSiteType.parameterCount(); 11.181 11.182 @@ -301,20 +298,11 @@ 11.183 } 11.184 11.185 /** 11.186 - * Add a method identified by a {@link SimpleDynamicMethod} to this overloaded method's set. 11.187 - * 11.188 - * @param method the method to add. 11.189 - */ 11.190 - void addMethod(SimpleDynamicMethod method) { 11.191 - addMethod(method.getTarget()); 11.192 - } 11.193 - 11.194 - /** 11.195 * Add a method to this overloaded method's set. 11.196 * 11.197 * @param method a method to add 11.198 */ 11.199 - public void addMethod(MethodHandle method) { 11.200 + public void addMethod(SingleDynamicMethod method) { 11.201 methods.add(method); 11.202 } 11.203 }
12.1 --- a/src/jdk/internal/dynalink/beans/OverloadedMethod.java Wed Jul 03 14:08:00 2013 +0530 12.2 +++ b/src/jdk/internal/dynalink/beans/OverloadedMethod.java Wed Jul 03 12:39:28 2013 +0200 12.3 @@ -135,7 +135,7 @@ 12.4 varArgMethods.trimToSize(); 12.5 12.6 final MethodHandle bound = SELECT_METHOD.bindTo(this); 12.7 - final MethodHandle collecting = SimpleDynamicMethod.collectArguments(bound, argNum).asType( 12.8 + final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType( 12.9 callSiteType.changeReturnType(MethodHandle.class)); 12.10 invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(callSiteType), collecting); 12.11 } 12.12 @@ -167,7 +167,7 @@ 12.13 break; 12.14 } 12.15 case 1: { 12.16 - method = new SimpleDynamicMethod(methods.get(0)).getInvocation(callSiteType, linkerServices); 12.17 + method = SingleDynamicMethod.getInvocation(methods.get(0), callSiteType, linkerServices); 12.18 break; 12.19 } 12.20 default: {
13.1 --- a/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Wed Jul 03 14:08:00 2013 +0530 13.2 +++ b/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Wed Jul 03 12:39:28 2013 +0200 13.3 @@ -84,29 +84,22 @@ 13.4 package jdk.internal.dynalink.beans; 13.5 13.6 import java.lang.invoke.MethodHandle; 13.7 -import java.lang.invoke.MethodHandles; 13.8 +import java.lang.invoke.MethodHandles.Lookup; 13.9 import java.lang.invoke.MethodType; 13.10 -import java.lang.reflect.Array; 13.11 -import jdk.internal.dynalink.linker.LinkerServices; 13.12 -import jdk.internal.dynalink.support.Guards; 13.13 13.14 /** 13.15 - * A dynamic method bound to exactly one, non-overloaded Java method. Handles varargs. 13.16 + * A dynamic method bound to exactly one Java method or constructor that is not caller sensitive. Since its target is 13.17 + * not caller sensitive, this class pre-caches its method handle and always returns it from the call to 13.18 + * {@link #getTarget(Lookup)}. Can be used in general to represents dynamic methods bound to a single method handle, 13.19 + * even if that handle is not mapped to a Java method, i.e. as a wrapper around field getters/setters, array element 13.20 + * getters/setters, etc. 13.21 * 13.22 * @author Attila Szegedi 13.23 */ 13.24 -class SimpleDynamicMethod extends DynamicMethod { 13.25 +class SimpleDynamicMethod extends SingleDynamicMethod { 13.26 private final MethodHandle target; 13.27 13.28 /** 13.29 - * Creates a simple dynamic method with no name. 13.30 - * @param target the target method handle 13.31 - */ 13.32 - SimpleDynamicMethod(MethodHandle target) { 13.33 - this(target, null); 13.34 - } 13.35 - 13.36 - /** 13.37 * Creates a new simple dynamic method, with a name constructed from the class name, method name, and handle 13.38 * signature. 13.39 * 13.40 @@ -115,125 +108,26 @@ 13.41 * @param name the simple name of the method 13.42 */ 13.43 SimpleDynamicMethod(MethodHandle target, Class<?> clazz, String name) { 13.44 - this(target, getName(target, clazz, name)); 13.45 - } 13.46 - 13.47 - SimpleDynamicMethod(MethodHandle target, String name) { 13.48 - super(name); 13.49 + super(getName(target, clazz, name)); 13.50 this.target = target; 13.51 } 13.52 13.53 private static String getName(MethodHandle target, Class<?> clazz, String name) { 13.54 - return getMethodNameWithSignature(target, getClassAndMethodName(clazz, name)); 13.55 - } 13.56 - 13.57 - static String getMethodNameWithSignature(MethodHandle target, String methodName) { 13.58 - final String typeStr = target.type().toString(); 13.59 - final int retTypeIndex = typeStr.lastIndexOf(')') + 1; 13.60 - int secondParamIndex = typeStr.indexOf(',') + 1; 13.61 - if(secondParamIndex == 0) { 13.62 - secondParamIndex = retTypeIndex - 1; 13.63 - } 13.64 - return typeStr.substring(retTypeIndex) + " " + methodName + "(" + typeStr.substring(secondParamIndex, retTypeIndex); 13.65 - } 13.66 - 13.67 - /** 13.68 - * Returns the target of this dynamic method 13.69 - * 13.70 - * @return the target of this dynamic method 13.71 - */ 13.72 - MethodHandle getTarget() { 13.73 - return target; 13.74 + return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name)); 13.75 } 13.76 13.77 @Override 13.78 - SimpleDynamicMethod getMethodForExactParamTypes(String paramTypes) { 13.79 - return typeMatchesDescription(paramTypes, target.type()) ? this : null; 13.80 + boolean isVarArgs() { 13.81 + return target.isVarargsCollector(); 13.82 } 13.83 13.84 @Override 13.85 - MethodHandle getInvocation(MethodType callSiteType, LinkerServices linkerServices) { 13.86 - final MethodType methodType = target.type(); 13.87 - final int paramsLen = methodType.parameterCount(); 13.88 - final boolean varArgs = target.isVarargsCollector(); 13.89 - final MethodHandle fixTarget = varArgs ? target.asFixedArity() : target; 13.90 - final int fixParamsLen = varArgs ? paramsLen - 1 : paramsLen; 13.91 - final int argsLen = callSiteType.parameterCount(); 13.92 - if(argsLen < fixParamsLen) { 13.93 - // Less actual arguments than number of fixed declared arguments; can't invoke. 13.94 - return null; 13.95 - } 13.96 - // Method handle has the same number of fixed arguments as the call site type 13.97 - if(argsLen == fixParamsLen) { 13.98 - // Method handle that matches the number of actual arguments as the number of fixed arguments 13.99 - final MethodHandle matchedMethod; 13.100 - if(varArgs) { 13.101 - // If vararg, add a zero-length array of the expected type as the last argument to signify no variable 13.102 - // arguments. 13.103 - matchedMethod = MethodHandles.insertArguments(fixTarget, fixParamsLen, Array.newInstance( 13.104 - methodType.parameterType(fixParamsLen).getComponentType(), 0)); 13.105 - } else { 13.106 - // Otherwise, just use the method 13.107 - matchedMethod = fixTarget; 13.108 - } 13.109 - return createConvertingInvocation(matchedMethod, linkerServices, callSiteType); 13.110 - } 13.111 - 13.112 - // What's below only works for varargs 13.113 - if(!varArgs) { 13.114 - return null; 13.115 - } 13.116 - 13.117 - final Class<?> varArgType = methodType.parameterType(fixParamsLen); 13.118 - // Handle a somewhat sinister corner case: caller passes exactly one argument in the vararg position, and we 13.119 - // must handle both a prepacked vararg array as well as a genuine 1-long vararg sequence. 13.120 - if(argsLen == paramsLen) { 13.121 - final Class<?> callSiteLastArgType = callSiteType.parameterType(fixParamsLen); 13.122 - if(varArgType.isAssignableFrom(callSiteLastArgType)) { 13.123 - // Call site signature guarantees we'll always be passed a single compatible array; just link directly 13.124 - // to the method. 13.125 - return createConvertingInvocation(fixTarget, linkerServices, callSiteType); 13.126 - } 13.127 - if(!linkerServices.canConvert(callSiteLastArgType, varArgType)) { 13.128 - // Call site signature guarantees the argument can definitely not be an array (i.e. it is primitive); 13.129 - // link immediately to a vararg-packing method handle. 13.130 - return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType); 13.131 - } 13.132 - // Call site signature makes no guarantees that the single argument in the vararg position will be 13.133 - // compatible across all invocations. Need to insert an appropriate guard and fall back to generic vararg 13.134 - // method when it is not. 13.135 - return MethodHandles.guardWithTest(Guards.isInstance(varArgType, fixParamsLen, callSiteType), 13.136 - createConvertingInvocation(fixTarget, linkerServices, callSiteType), 13.137 - createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType)); 13.138 - } 13.139 - 13.140 - // Remaining case: more than one vararg. 13.141 - return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType); 13.142 + MethodType getMethodType() { 13.143 + return target.type(); 13.144 } 13.145 13.146 @Override 13.147 - public boolean contains(MethodHandle mh) { 13.148 - return target.type().parameterList().equals(mh.type().parameterList()); 13.149 - } 13.150 - 13.151 - /** 13.152 - * Creates a method handle out of the original target that will collect the varargs for the exact component type of 13.153 - * the varArg array. Note that this will nicely trigger language-specific type converters for exactly those varargs 13.154 - * for which it is necessary when later passed to linkerServices.convertArguments(). 13.155 - * 13.156 - * @param target the original method handle 13.157 - * @param parameterCount the total number of arguments in the new method handle 13.158 - * @return a collecting method handle 13.159 - */ 13.160 - static MethodHandle collectArguments(MethodHandle target, final int parameterCount) { 13.161 - final MethodType methodType = target.type(); 13.162 - final int fixParamsLen = methodType.parameterCount() - 1; 13.163 - final Class<?> arrayType = methodType.parameterType(fixParamsLen); 13.164 - return target.asCollector(arrayType, parameterCount - fixParamsLen); 13.165 - } 13.166 - 13.167 - private static MethodHandle createConvertingInvocation(final MethodHandle sizedMethod, 13.168 - final LinkerServices linkerServices, final MethodType callSiteType) { 13.169 - return linkerServices.asType(sizedMethod, callSiteType); 13.170 + MethodHandle getTarget(Lookup lookup) { 13.171 + return target; 13.172 } 13.173 }
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java Wed Jul 03 12:39:28 2013 +0200 14.3 @@ -0,0 +1,255 @@ 14.4 +/* 14.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 14.7 + * 14.8 + * This code is free software; you can redistribute it and/or modify it 14.9 + * under the terms of the GNU General Public License version 2 only, as 14.10 + * published by the Free Software Foundation. Oracle designates this 14.11 + * particular file as subject to the "Classpath" exception as provided 14.12 + * by Oracle in the LICENSE file that accompanied this code. 14.13 + * 14.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 14.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14.17 + * version 2 for more details (a copy is included in the LICENSE file that 14.18 + * accompanied this code). 14.19 + * 14.20 + * You should have received a copy of the GNU General Public License version 14.21 + * 2 along with this work; if not, write to the Free Software Foundation, 14.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 14.23 + * 14.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 14.25 + * or visit www.oracle.com if you need additional information or have any 14.26 + * questions. 14.27 + */ 14.28 + 14.29 +/* 14.30 + * This file is available under and governed by the GNU General Public 14.31 + * License version 2 only, as published by the Free Software Foundation. 14.32 + * However, the following notice accompanied the original version of this 14.33 + * file, and Oracle licenses the original version of this file under the BSD 14.34 + * license: 14.35 + */ 14.36 +/* 14.37 + Copyright 2009-2013 Attila Szegedi 14.38 + 14.39 + Licensed under both the Apache License, Version 2.0 (the "Apache License") 14.40 + and the BSD License (the "BSD License"), with licensee being free to 14.41 + choose either of the two at their discretion. 14.42 + 14.43 + You may not use this file except in compliance with either the Apache 14.44 + License or the BSD License. 14.45 + 14.46 + If you choose to use this file in compliance with the Apache License, the 14.47 + following notice applies to you: 14.48 + 14.49 + You may obtain a copy of the Apache License at 14.50 + 14.51 + http://www.apache.org/licenses/LICENSE-2.0 14.52 + 14.53 + Unless required by applicable law or agreed to in writing, software 14.54 + distributed under the License is distributed on an "AS IS" BASIS, 14.55 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 14.56 + implied. See the License for the specific language governing 14.57 + permissions and limitations under the License. 14.58 + 14.59 + If you choose to use this file in compliance with the BSD License, the 14.60 + following notice applies to you: 14.61 + 14.62 + Redistribution and use in source and binary forms, with or without 14.63 + modification, are permitted provided that the following conditions are 14.64 + met: 14.65 + * Redistributions of source code must retain the above copyright 14.66 + notice, this list of conditions and the following disclaimer. 14.67 + * Redistributions in binary form must reproduce the above copyright 14.68 + notice, this list of conditions and the following disclaimer in the 14.69 + documentation and/or other materials provided with the distribution. 14.70 + * Neither the name of the copyright holder nor the names of 14.71 + contributors may be used to endorse or promote products derived from 14.72 + this software without specific prior written permission. 14.73 + 14.74 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 14.75 + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 14.76 + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 14.77 + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER 14.78 + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 14.79 + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 14.80 + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 14.81 + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 14.82 + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 14.83 + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 14.84 + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14.85 +*/ 14.86 + 14.87 +package jdk.internal.dynalink.beans; 14.88 + 14.89 +import java.lang.invoke.MethodHandle; 14.90 +import java.lang.invoke.MethodHandles; 14.91 +import java.lang.invoke.MethodType; 14.92 +import java.lang.reflect.Array; 14.93 +import java.util.StringTokenizer; 14.94 +import jdk.internal.dynalink.CallSiteDescriptor; 14.95 +import jdk.internal.dynalink.linker.LinkerServices; 14.96 +import jdk.internal.dynalink.support.Guards; 14.97 + 14.98 +/** 14.99 + * Base class for dynamic methods that dispatch to a single target Java method or constructor. Handles adaptation of the 14.100 + * target method to a call site type (including mapping variable arity methods to a call site signature with different 14.101 + * arity). 14.102 + * @author Attila Szegedi 14.103 + * @version $Id: $ 14.104 + */ 14.105 +abstract class SingleDynamicMethod extends DynamicMethod { 14.106 + SingleDynamicMethod(String name) { 14.107 + super(name); 14.108 + } 14.109 + 14.110 + /** 14.111 + * Returns true if this method is variable arity. 14.112 + * @return true if this method is variable arity. 14.113 + */ 14.114 + abstract boolean isVarArgs(); 14.115 + 14.116 + /** 14.117 + * Returns this method's native type. 14.118 + * @return this method's native type. 14.119 + */ 14.120 + abstract MethodType getMethodType(); 14.121 + 14.122 + /** 14.123 + * Given a specified lookup, returns a method handle to this method's target. 14.124 + * @param lookup the lookup to use. 14.125 + * @return the handle to this method's target method. 14.126 + */ 14.127 + abstract MethodHandle getTarget(MethodHandles.Lookup lookup); 14.128 + 14.129 + @Override 14.130 + MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) { 14.131 + return getInvocation(getTarget(callSiteDescriptor.getLookup()), callSiteDescriptor.getMethodType(), 14.132 + linkerServices); 14.133 + } 14.134 + 14.135 + @Override 14.136 + SingleDynamicMethod getMethodForExactParamTypes(String paramTypes) { 14.137 + return typeMatchesDescription(paramTypes, getMethodType()) ? this : null; 14.138 + } 14.139 + 14.140 + @Override 14.141 + boolean contains(SingleDynamicMethod method) { 14.142 + return getMethodType().parameterList().equals(method.getMethodType().parameterList()); 14.143 + } 14.144 + 14.145 + static String getMethodNameWithSignature(MethodType type, String methodName) { 14.146 + final String typeStr = type.toString(); 14.147 + final int retTypeIndex = typeStr.lastIndexOf(')') + 1; 14.148 + int secondParamIndex = typeStr.indexOf(',') + 1; 14.149 + if(secondParamIndex == 0) { 14.150 + secondParamIndex = retTypeIndex - 1; 14.151 + } 14.152 + return typeStr.substring(retTypeIndex) + " " + methodName + "(" + typeStr.substring(secondParamIndex, retTypeIndex); 14.153 + } 14.154 + 14.155 + /** 14.156 + * Given a method handle and a call site type, adapts the method handle to the call site type. Performs type 14.157 + * conversions as needed using the specified linker services, and in case that the method handle is a vararg 14.158 + * collector, matches it to the arity of the call site. 14.159 + * @param target the method handle to adapt 14.160 + * @param callSiteType the type of the call site 14.161 + * @param linkerServices the linker services used for type conversions 14.162 + * @return the adapted method handle. 14.163 + */ 14.164 + static MethodHandle getInvocation(MethodHandle target, MethodType callSiteType, LinkerServices linkerServices) { 14.165 + final MethodType methodType = target.type(); 14.166 + final int paramsLen = methodType.parameterCount(); 14.167 + final boolean varArgs = target.isVarargsCollector(); 14.168 + final MethodHandle fixTarget = varArgs ? target.asFixedArity() : target; 14.169 + final int fixParamsLen = varArgs ? paramsLen - 1 : paramsLen; 14.170 + final int argsLen = callSiteType.parameterCount(); 14.171 + if(argsLen < fixParamsLen) { 14.172 + // Less actual arguments than number of fixed declared arguments; can't invoke. 14.173 + return null; 14.174 + } 14.175 + // Method handle has the same number of fixed arguments as the call site type 14.176 + if(argsLen == fixParamsLen) { 14.177 + // Method handle that matches the number of actual arguments as the number of fixed arguments 14.178 + final MethodHandle matchedMethod; 14.179 + if(varArgs) { 14.180 + // If vararg, add a zero-length array of the expected type as the last argument to signify no variable 14.181 + // arguments. 14.182 + matchedMethod = MethodHandles.insertArguments(fixTarget, fixParamsLen, Array.newInstance( 14.183 + methodType.parameterType(fixParamsLen).getComponentType(), 0)); 14.184 + } else { 14.185 + // Otherwise, just use the method 14.186 + matchedMethod = fixTarget; 14.187 + } 14.188 + return createConvertingInvocation(matchedMethod, linkerServices, callSiteType); 14.189 + } 14.190 + 14.191 + // What's below only works for varargs 14.192 + if(!varArgs) { 14.193 + return null; 14.194 + } 14.195 + 14.196 + final Class<?> varArgType = methodType.parameterType(fixParamsLen); 14.197 + // Handle a somewhat sinister corner case: caller passes exactly one argument in the vararg position, and we 14.198 + // must handle both a prepacked vararg array as well as a genuine 1-long vararg sequence. 14.199 + if(argsLen == paramsLen) { 14.200 + final Class<?> callSiteLastArgType = callSiteType.parameterType(fixParamsLen); 14.201 + if(varArgType.isAssignableFrom(callSiteLastArgType)) { 14.202 + // Call site signature guarantees we'll always be passed a single compatible array; just link directly 14.203 + // to the method, introducing necessary conversions. Also, preserve it being a variable arity method. 14.204 + return createConvertingInvocation(target, linkerServices, callSiteType).asVarargsCollector( 14.205 + callSiteLastArgType); 14.206 + } 14.207 + if(!linkerServices.canConvert(callSiteLastArgType, varArgType)) { 14.208 + // Call site signature guarantees the argument can definitely not be an array (i.e. it is primitive); 14.209 + // link immediately to a vararg-packing method handle. 14.210 + return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType); 14.211 + } 14.212 + // Call site signature makes no guarantees that the single argument in the vararg position will be 14.213 + // compatible across all invocations. Need to insert an appropriate guard and fall back to generic vararg 14.214 + // method when it is not. 14.215 + return MethodHandles.guardWithTest(Guards.isInstance(varArgType, fixParamsLen, callSiteType), 14.216 + createConvertingInvocation(fixTarget, linkerServices, callSiteType), 14.217 + createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType)); 14.218 + } 14.219 + 14.220 + // Remaining case: more than one vararg. 14.221 + return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType); 14.222 + } 14.223 + 14.224 + /** 14.225 + * Creates a method handle out of the original target that will collect the varargs for the exact component type of 14.226 + * the varArg array. Note that this will nicely trigger language-specific type converters for exactly those varargs 14.227 + * for which it is necessary when later passed to linkerServices.convertArguments(). 14.228 + * 14.229 + * @param target the original method handle 14.230 + * @param parameterCount the total number of arguments in the new method handle 14.231 + * @return a collecting method handle 14.232 + */ 14.233 + static MethodHandle collectArguments(MethodHandle target, final int parameterCount) { 14.234 + final MethodType methodType = target.type(); 14.235 + final int fixParamsLen = methodType.parameterCount() - 1; 14.236 + final Class<?> arrayType = methodType.parameterType(fixParamsLen); 14.237 + return target.asCollector(arrayType, parameterCount - fixParamsLen); 14.238 + } 14.239 + 14.240 + private static MethodHandle createConvertingInvocation(final MethodHandle sizedMethod, 14.241 + final LinkerServices linkerServices, final MethodType callSiteType) { 14.242 + return linkerServices.asType(sizedMethod, callSiteType); 14.243 + } 14.244 + 14.245 + private static boolean typeMatchesDescription(String paramTypes, MethodType type) { 14.246 + final StringTokenizer tok = new StringTokenizer(paramTypes, ", "); 14.247 + for(int i = 1; i < type.parameterCount(); ++i) { // i = 1 as we ignore the receiver 14.248 + if(!(tok.hasMoreTokens() && typeNameMatches(tok.nextToken(), type.parameterType(i)))) { 14.249 + return false; 14.250 + } 14.251 + } 14.252 + return !tok.hasMoreTokens(); 14.253 + } 14.254 + 14.255 + private static boolean typeNameMatches(String typeName, Class<?> type) { 14.256 + return typeName.equals(typeName.indexOf('.') == -1 ? type.getSimpleName() : type.getCanonicalName()); 14.257 + } 14.258 +}
15.1 --- a/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java Wed Jul 03 14:08:00 2013 +0530 15.2 +++ b/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java Wed Jul 03 12:39:28 2013 +0200 15.3 @@ -106,10 +106,18 @@ 15.4 15.5 @Override 15.6 MethodHandle editMethodHandle(MethodHandle mh) { 15.7 + return editStaticMethodHandle(mh); 15.8 + } 15.9 + 15.10 + static MethodHandle editStaticMethodHandle(MethodHandle mh) { 15.11 return dropReceiver(mh, Object.class); 15.12 } 15.13 15.14 - static MethodHandle dropReceiver(final MethodHandle mh, final Class<?> receiverClass) { 15.15 + static MethodHandle editConstructorMethodHandle(MethodHandle cmh) { 15.16 + return dropReceiver(cmh, StaticClass.class); 15.17 + } 15.18 + 15.19 + private static MethodHandle dropReceiver(final MethodHandle mh, final Class<?> receiverClass) { 15.20 MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, receiverClass); 15.21 // NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state. 15.22 if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) {
16.1 --- a/src/jdk/internal/dynalink/beans/StaticClassLinker.java Wed Jul 03 14:08:00 2013 +0530 16.2 +++ b/src/jdk/internal/dynalink/beans/StaticClassLinker.java Wed Jul 03 12:39:28 2013 +0200 16.3 @@ -87,9 +87,7 @@ 16.4 import java.lang.invoke.MethodHandles; 16.5 import java.lang.invoke.MethodType; 16.6 import java.lang.reflect.Array; 16.7 -import java.lang.reflect.Constructor; 16.8 -import java.util.ArrayList; 16.9 -import java.util.List; 16.10 +import java.util.Arrays; 16.11 import jdk.internal.dynalink.CallSiteDescriptor; 16.12 import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType; 16.13 import jdk.internal.dynalink.linker.GuardedInvocation; 16.14 @@ -131,20 +129,11 @@ 16.15 private static DynamicMethod createConstructorMethod(Class<?> clazz) { 16.16 if(clazz.isArray()) { 16.17 final MethodHandle boundArrayCtor = ARRAY_CTOR.bindTo(clazz.getComponentType()); 16.18 - return new SimpleDynamicMethod(drop(boundArrayCtor.asType(boundArrayCtor.type().changeReturnType( 16.19 - clazz))), clazz, "<init>"); 16.20 + return new SimpleDynamicMethod(StaticClassIntrospector.editConstructorMethodHandle( 16.21 + boundArrayCtor.asType(boundArrayCtor.type().changeReturnType(clazz))), clazz, "<init>"); 16.22 } 16.23 16.24 - final Constructor<?>[] ctrs = clazz.getConstructors(); 16.25 - final List<MethodHandle> mhs = new ArrayList<>(ctrs.length); 16.26 - for(int i = 0; i < ctrs.length; ++i) { 16.27 - mhs.add(drop(SafeUnreflector.unreflectConstructor(ctrs[i]))); 16.28 - } 16.29 - return createDynamicMethod(mhs, clazz, "<init>"); 16.30 - } 16.31 - 16.32 - private static MethodHandle drop(MethodHandle mh) { 16.33 - return StaticClassIntrospector.dropReceiver(mh, StaticClass.class); 16.34 + return createDynamicMethod(Arrays.asList(clazz.getConstructors()), clazz, "<init>"); 16.35 } 16.36 16.37 @Override 16.38 @@ -161,11 +150,10 @@ 16.39 } 16.40 final CallSiteDescriptor desc = request.getCallSiteDescriptor(); 16.41 final String op = desc.getNameToken(CallSiteDescriptor.OPERATOR); 16.42 - final MethodType methodType = desc.getMethodType(); 16.43 if("new" == op && constructor != null) { 16.44 - final MethodHandle ctorInvocation = constructor.getInvocation(methodType, linkerServices); 16.45 + final MethodHandle ctorInvocation = constructor.getInvocation(desc, linkerServices); 16.46 if(ctorInvocation != null) { 16.47 - return new GuardedInvocation(ctorInvocation, getClassGuard(methodType)); 16.48 + return new GuardedInvocation(ctorInvocation, getClassGuard(desc.getMethodType())); 16.49 } 16.50 } 16.51 return null;
17.1 --- a/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java Wed Jul 03 14:08:00 2013 +0530 17.2 +++ b/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java Wed Jul 03 12:39:28 2013 +0200 17.3 @@ -139,8 +139,9 @@ 17.4 17.5 @Override 17.6 public int hashCode() { 17.7 + final MethodHandles.Lookup lookup = getLookup(); 17.8 + int h = lookup.lookupClass().hashCode() + 31 * lookup.lookupModes(); 17.9 final int c = getNameTokenCount(); 17.10 - int h = 0; 17.11 for(int i = 0; i < c; ++i) { 17.12 h = h * 31 + getNameToken(i).hashCode(); 17.13 }
18.1 --- a/src/jdk/internal/dynalink/support/Lookup.java Wed Jul 03 14:08:00 2013 +0530 18.2 +++ b/src/jdk/internal/dynalink/support/Lookup.java Wed Jul 03 12:39:28 2013 +0200 18.3 @@ -122,6 +122,18 @@ 18.4 * @return the unreflected method handle. 18.5 */ 18.6 public MethodHandle unreflect(Method m) { 18.7 + return unreflect(lookup, m); 18.8 + } 18.9 + 18.10 + /** 18.11 + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, converting any encountered 18.12 + * {@link IllegalAccessException} into an {@link IllegalAccessError}. 18.13 + * 18.14 + * @param lookup the lookup used to unreflect 18.15 + * @param m the method to unreflect 18.16 + * @return the unreflected method handle. 18.17 + */ 18.18 + public static MethodHandle unreflect(MethodHandles.Lookup lookup, Method m) { 18.19 try { 18.20 return lookup.unreflect(m); 18.21 } catch(IllegalAccessException e) { 18.22 @@ -131,7 +143,6 @@ 18.23 } 18.24 } 18.25 18.26 - 18.27 /** 18.28 * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter(Field)}, converting any encountered 18.29 * {@link IllegalAccessException} into an {@link IllegalAccessError}. 18.30 @@ -202,6 +213,18 @@ 18.31 * @return the unreflected constructor handle. 18.32 */ 18.33 public MethodHandle unreflectConstructor(Constructor<?> c) { 18.34 + return unreflectConstructor(lookup, c); 18.35 + } 18.36 + 18.37 + /** 18.38 + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, converting any 18.39 + * encountered {@link IllegalAccessException} into an {@link IllegalAccessError}. 18.40 + * 18.41 + * @param lookup the lookup used to unreflect 18.42 + * @param c the constructor to unreflect 18.43 + * @return the unreflected constructor handle. 18.44 + */ 18.45 + public static MethodHandle unreflectConstructor(MethodHandles.Lookup lookup, Constructor<?> c) { 18.46 try { 18.47 return lookup.unreflectConstructor(c); 18.48 } catch(IllegalAccessException e) {
19.1 --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Jul 03 14:08:00 2013 +0530 19.2 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Jul 03 12:39:28 2013 +0200 19.3 @@ -78,7 +78,7 @@ 19.4 * @return CallSite with MethodHandle to appropriate method or null if not found. 19.5 */ 19.6 public static CallSite bootstrap(final Lookup lookup, final String opDesc, final MethodType type, final int flags) { 19.7 - return dynamicLinker.link(LinkerCallSite.newLinkerCallSite(opDesc, type, flags)); 19.8 + return dynamicLinker.link(LinkerCallSite.newLinkerCallSite(lookup, opDesc, type, flags)); 19.9 } 19.10 19.11 /** 19.12 @@ -94,12 +94,12 @@ 19.13 return new RuntimeCallSite(type, initialName); 19.14 } 19.15 19.16 - 19.17 /** 19.18 - * Returns a dynamic invoker for a specified dynamic operation. You can use this method to create a method handle 19.19 - * that when invoked acts completely as if it were a Nashorn-linked call site. An overview of available dynamic 19.20 - * operations can be found in the <a href="https://github.com/szegedi/dynalink/wiki/User-Guide-0.4">Dynalink User Guide</a>, 19.21 - * but we'll show few examples here: 19.22 + * Returns a dynamic invoker for a specified dynamic operation using the public lookup. You can use this method to 19.23 + * create a method handle that when invoked acts completely as if it were a Nashorn-linked call site. An overview of 19.24 + * available dynamic operations can be found in the 19.25 + * <a href="https://github.com/szegedi/dynalink/wiki/User-Guide-0.6">Dynalink User Guide</a>, but we'll show few 19.26 + * examples here: 19.27 * <ul> 19.28 * <li>Get a named property with fixed name: 19.29 * <pre> 19.30 @@ -196,7 +196,7 @@ 19.31 } 19.32 19.33 /** 19.34 - * Returns a dynamic invoker for a specified dynamic operation. Similar to 19.35 + * Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to 19.36 * {@link #createDynamicInvoker(String, Class, Class...)} but with return and parameter types composed into a 19.37 * method type in the signature. See the discussion of that method for details. 19.38 * @param opDesc Dynalink dynamic operation descriptor. 19.39 @@ -204,7 +204,7 @@ 19.40 * @return MethodHandle for invoking the operation. 19.41 */ 19.42 public static MethodHandle createDynamicInvoker(final String opDesc, final MethodType type) { 19.43 - return bootstrap(null, opDesc, type, 0).dynamicInvoker(); 19.44 + return bootstrap(MethodHandles.publicLookup(), opDesc, type, 0).dynamicInvoker(); 19.45 } 19.46 19.47 /**
20.1 --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed Jul 03 14:08:00 2013 +0530 20.2 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed Jul 03 12:39:28 2013 +0200 20.3 @@ -28,6 +28,7 @@ 20.4 import static jdk.nashorn.internal.lookup.Lookup.MH; 20.5 20.6 import java.lang.invoke.MethodHandle; 20.7 +import java.lang.invoke.MethodHandles; 20.8 import java.lang.invoke.MethodType; 20.9 import java.lang.reflect.Modifier; 20.10 import java.security.AccessController; 20.11 @@ -39,7 +40,6 @@ 20.12 import java.util.HashMap; 20.13 import java.util.List; 20.14 import java.util.Map; 20.15 - 20.16 import jdk.internal.dynalink.beans.StaticClass; 20.17 import jdk.internal.dynalink.support.LinkRequestImpl; 20.18 import jdk.nashorn.internal.objects.NativeJava; 20.19 @@ -119,9 +119,12 @@ 20.20 return AccessController.doPrivileged(new PrivilegedExceptionAction<MethodHandle>() { 20.21 @Override 20.22 public MethodHandle run() throws Exception { 20.23 - return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl(NashornCallSiteDescriptor.get( 20.24 - "dyn:new", MethodType.methodType(targetType, StaticClass.class, sourceType), 0), false, 20.25 - adapterClass, null)).getInvocation(), adapterClass); 20.26 + // NOTE: we use publicLookup(), but none of our adapter constructors are caller sensitive, so this is 20.27 + // okay, we won't artificially limit access. 20.28 + return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl( 20.29 + NashornCallSiteDescriptor.get(MethodHandles.publicLookup(), "dyn:new", 20.30 + MethodType.methodType(targetType, StaticClass.class, sourceType), 0), false, 20.31 + adapterClass, null)).getInvocation(), adapterClass); 20.32 } 20.33 }); 20.34 }
21.1 --- a/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Wed Jul 03 14:08:00 2013 +0530 21.2 +++ b/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Wed Jul 03 12:39:28 2013 +0200 21.3 @@ -25,7 +25,6 @@ 21.4 21.5 package jdk.nashorn.internal.runtime.linker; 21.6 21.7 -import jdk.nashorn.internal.lookup.MethodHandleFactory; 21.8 import static jdk.nashorn.internal.lookup.Lookup.MH; 21.9 21.10 import java.io.FileNotFoundException; 21.11 @@ -47,6 +46,7 @@ 21.12 import jdk.internal.dynalink.ChainedCallSite; 21.13 import jdk.internal.dynalink.DynamicLinker; 21.14 import jdk.internal.dynalink.linker.GuardedInvocation; 21.15 +import jdk.nashorn.internal.lookup.MethodHandleFactory; 21.16 import jdk.nashorn.internal.runtime.Context; 21.17 import jdk.nashorn.internal.runtime.Debug; 21.18 import jdk.nashorn.internal.runtime.ScriptObject; 21.19 @@ -79,8 +79,9 @@ 21.20 * @param flags Call site specific flags. 21.21 * @return New LinkerCallSite. 21.22 */ 21.23 - static LinkerCallSite newLinkerCallSite(final String name, final MethodType type, final int flags) { 21.24 - final NashornCallSiteDescriptor desc = NashornCallSiteDescriptor.get(name, type, flags); 21.25 + static LinkerCallSite newLinkerCallSite(final MethodHandles.Lookup lookup, final String name, final MethodType type, 21.26 + final int flags) { 21.27 + final NashornCallSiteDescriptor desc = NashornCallSiteDescriptor.get(lookup, name, type, flags); 21.28 21.29 if (desc.isProfile()) { 21.30 return ProfilingLinkerCallSite.newProfilingLinkerCallSite(desc);
22.1 --- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Wed Jul 03 14:08:00 2013 +0530 22.2 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Wed Jul 03 12:39:28 2013 +0200 22.3 @@ -25,9 +25,12 @@ 22.4 22.5 package jdk.nashorn.internal.runtime.linker; 22.6 22.7 +import java.lang.invoke.MethodHandles; 22.8 +import java.lang.invoke.MethodHandles.Lookup; 22.9 import java.lang.invoke.MethodType; 22.10 -import java.lang.ref.WeakReference; 22.11 -import java.util.WeakHashMap; 22.12 +import java.util.Map; 22.13 +import java.util.concurrent.ConcurrentHashMap; 22.14 +import java.util.concurrent.ConcurrentMap; 22.15 import jdk.internal.dynalink.CallSiteDescriptor; 22.16 import jdk.internal.dynalink.support.AbstractCallSiteDescriptor; 22.17 import jdk.internal.dynalink.support.CallSiteDescriptorFactory; 22.18 @@ -70,9 +73,15 @@ 22.19 * set. */ 22.20 public static final int CALLSITE_TRACE_SCOPE = 0x200; 22.21 22.22 - private static final WeakHashMap<NashornCallSiteDescriptor, WeakReference<NashornCallSiteDescriptor>> canonicals = 22.23 - new WeakHashMap<>(); 22.24 + private static final ClassValue<ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor>> canonicals = 22.25 + new ClassValue<ConcurrentMap<NashornCallSiteDescriptor,NashornCallSiteDescriptor>>() { 22.26 + @Override 22.27 + protected ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor> computeValue(Class<?> type) { 22.28 + return new ConcurrentHashMap<>(); 22.29 + } 22.30 + }; 22.31 22.32 + private final MethodHandles.Lookup lookup; 22.33 private final String operator; 22.34 private final String operand; 22.35 private final MethodType methodType; 22.36 @@ -81,39 +90,35 @@ 22.37 /** 22.38 * Retrieves a Nashorn call site descriptor with the specified values. Since call site descriptors are immutable 22.39 * this method is at liberty to retrieve canonicalized instances (although it is not guaranteed it will do so). 22.40 + * @param lookup the lookup describing the script 22.41 * @param name the name at the call site, e.g. {@code "dyn:getProp|getElem|getMethod:color"}. 22.42 * @param methodType the method type at the call site 22.43 * @param flags Nashorn-specific call site flags 22.44 * @return a call site descriptor with the specified values. 22.45 */ 22.46 - public static NashornCallSiteDescriptor get(final String name, final MethodType methodType, final int flags) { 22.47 + public static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final String name, 22.48 + final MethodType methodType, final int flags) { 22.49 final String[] tokenizedName = CallSiteDescriptorFactory.tokenizeName(name); 22.50 assert tokenizedName.length == 2 || tokenizedName.length == 3; 22.51 assert "dyn".equals(tokenizedName[0]); 22.52 assert tokenizedName[1] != null; 22.53 // TODO: see if we can move mangling/unmangling into Dynalink 22.54 - return get(tokenizedName[1], tokenizedName.length == 3 ? tokenizedName[2].intern() : null, 22.55 + return get(lookup, tokenizedName[1], tokenizedName.length == 3 ? tokenizedName[2].intern() : null, 22.56 methodType, flags); 22.57 } 22.58 22.59 - private static NashornCallSiteDescriptor get(final String operator, final String operand, final MethodType methodType, final int flags) { 22.60 - final NashornCallSiteDescriptor csd = new NashornCallSiteDescriptor(operator, operand, methodType, flags); 22.61 + private static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final String operator, final String operand, final MethodType methodType, final int flags) { 22.62 + final NashornCallSiteDescriptor csd = new NashornCallSiteDescriptor(lookup, operator, operand, methodType, flags); 22.63 // Many of these call site descriptors are identical (e.g. every getter for a property color will be 22.64 - // "dyn:getProp:color(Object)Object", so it makes sense canonicalizing them in a weak map 22.65 - synchronized(canonicals) { 22.66 - final WeakReference<NashornCallSiteDescriptor> ref = canonicals.get(csd); 22.67 - if(ref != null) { 22.68 - final NashornCallSiteDescriptor canonical = ref.get(); 22.69 - if(canonical != null) { 22.70 - return canonical; 22.71 - } 22.72 - } 22.73 - canonicals.put(csd, new WeakReference<>(csd)); 22.74 - } 22.75 - return csd; 22.76 + // "dyn:getProp:color(Object)Object", so it makes sense canonicalizing them. 22.77 + final Map<NashornCallSiteDescriptor, NashornCallSiteDescriptor> classCanonicals = canonicals.get(lookup.lookupClass()); 22.78 + final NashornCallSiteDescriptor canonical = classCanonicals.putIfAbsent(csd, csd); 22.79 + return canonical != null ? canonical : csd; 22.80 } 22.81 22.82 - private NashornCallSiteDescriptor(final String operator, final String operand, final MethodType methodType, final int flags) { 22.83 + private NashornCallSiteDescriptor(final MethodHandles.Lookup lookup, final String operator, final String operand, 22.84 + final MethodType methodType, final int flags) { 22.85 + this.lookup = lookup; 22.86 this.operator = operator; 22.87 this.operand = operand; 22.88 this.methodType = methodType; 22.89 @@ -142,6 +147,11 @@ 22.90 } 22.91 22.92 @Override 22.93 + public Lookup getLookup() { 22.94 + return lookup; 22.95 + } 22.96 + 22.97 + @Override 22.98 public boolean equals(final CallSiteDescriptor csd) { 22.99 return super.equals(csd) && flags == getFlags(csd); 22.100 } 22.101 @@ -279,6 +289,6 @@ 22.102 22.103 @Override 22.104 public CallSiteDescriptor changeMethodType(final MethodType newMethodType) { 22.105 - return get(operator, operand, newMethodType, flags); 22.106 + return get(getLookup(), operator, operand, newMethodType, flags); 22.107 } 22.108 }
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/test/script/basic/JDK-8010946-2.js Wed Jul 03 12:39:28 2013 +0200 23.3 @@ -0,0 +1,38 @@ 23.4 +/* 23.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 23.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 23.7 + * 23.8 + * This code is free software; you can redistribute it and/or modify it 23.9 + * under the terms of the GNU General Public License version 2 only, as 23.10 + * published by the Free Software Foundation. 23.11 + * 23.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 23.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 23.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 23.15 + * version 2 for more details (a copy is included in the LICENSE file that 23.16 + * accompanied this code). 23.17 + * 23.18 + * You should have received a copy of the GNU General Public License version 23.19 + * 2 along with this work; if not, write to the Free Software Foundation, 23.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23.21 + * 23.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23.23 + * or visit www.oracle.com if you need additional information or have any 23.24 + * questions. 23.25 + */ 23.26 + 23.27 +/** 23.28 + * JDK-8010946: AccessController.doPrivileged() doesn't work as expected. 23.29 + * This is actually a broader issue of having Dynalink correctly handle 23.30 + * caller-sensitive methods. 23.31 + * 23.32 + * @test 23.33 + * @run 23.34 + */ 23.35 + 23.36 +// Ensure these are CallerSensitiveDynamicMethods 23.37 +print(java.security.AccessController["doPrivileged(PrivilegedAction)"]) 23.38 +print(java.lang.Class["forName(String)"]) 23.39 + 23.40 +// Ensure this is not 23.41 +print(java.lang.String["valueOf(char)"])
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/test/script/basic/JDK-8010946-2.js.EXPECTED Wed Jul 03 12:39:28 2013 +0200 24.3 @@ -0,0 +1,3 @@ 24.4 +[jdk.internal.dynalink.beans.CallerSensitiveDynamicMethod Object java.security.AccessController.doPrivileged(PrivilegedAction)] 24.5 +[jdk.internal.dynalink.beans.CallerSensitiveDynamicMethod Class java.lang.Class.forName(String)] 24.6 +[jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.valueOf(char)]
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/test/script/basic/JDK-8010946-privileged.js Wed Jul 03 12:39:28 2013 +0200 25.3 @@ -0,0 +1,47 @@ 25.4 +/* 25.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 25.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 25.7 + * 25.8 + * This code is free software; you can redistribute it and/or modify it 25.9 + * under the terms of the GNU General Public License version 2 only, as 25.10 + * published by the Free Software Foundation. 25.11 + * 25.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 25.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 25.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 25.15 + * version 2 for more details (a copy is included in the LICENSE file that 25.16 + * accompanied this code). 25.17 + * 25.18 + * You should have received a copy of the GNU General Public License version 25.19 + * 2 along with this work; if not, write to the Free Software Foundation, 25.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 25.21 + * 25.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 25.23 + * or visit www.oracle.com if you need additional information or have any 25.24 + * questions. 25.25 + */ 25.26 + 25.27 +/** 25.28 + * JDK-8010946: AccessController.doPrivileged() doesn't work as expected. 25.29 + * This is actually a broader issue of having Dynalink correctly handle 25.30 + * caller-sensitive methods. 25.31 + * 25.32 + * NOTE: This is not a standalone test file, it is loaded by JDK-801946.js 25.33 + * @subtest 25.34 + */ 25.35 + 25.36 +(function() { 25.37 + var getProperty = java.lang.System.getProperty 25.38 + var doPrivileged = java.security.AccessController["doPrivileged(PrivilegedAction)"] 25.39 + 25.40 + this.executeUnprivileged = function() { 25.41 + var x = getProperty("java.security.policy") 25.42 + if(x != null) { 25.43 + print("Successfully retrieved restricted system property.") 25.44 + } 25.45 + } 25.46 + 25.47 + this.executePrivileged = function() { 25.48 + doPrivileged(executeUnprivileged) 25.49 + } 25.50 +})();
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/test/script/basic/JDK-8010946.js Wed Jul 03 12:39:28 2013 +0200 26.3 @@ -0,0 +1,51 @@ 26.4 +/* 26.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 26.7 + * 26.8 + * This code is free software; you can redistribute it and/or modify it 26.9 + * under the terms of the GNU General Public License version 2 only, as 26.10 + * published by the Free Software Foundation. 26.11 + * 26.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 26.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 26.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 26.15 + * version 2 for more details (a copy is included in the LICENSE file that 26.16 + * accompanied this code). 26.17 + * 26.18 + * You should have received a copy of the GNU General Public License version 26.19 + * 2 along with this work; if not, write to the Free Software Foundation, 26.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26.21 + * 26.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 26.23 + * or visit www.oracle.com if you need additional information or have any 26.24 + * questions. 26.25 + */ 26.26 + 26.27 +/** 26.28 + * JDK-8010946: AccessController.doPrivileged() doesn't work as expected. 26.29 + * This is actually a broader issue of having Dynalink correctly handle 26.30 + * caller-sensitive methods. 26.31 + * 26.32 + * @test 26.33 + * @run 26.34 + */ 26.35 + 26.36 +// This is unprivileged code that loads privileged code. 26.37 +load(__DIR__ + "JDK-8010946-privileged.js") 26.38 + 26.39 +try { 26.40 + // This should fail, even though the code itself resides in the 26.41 + // privileged script, as we're invoking it without going through 26.42 + // doPrivileged() 26.43 + print("Attempting unprivileged execution...") 26.44 + executeUnprivileged() 26.45 + print("FAIL: Unprivileged execution succeeded!") 26.46 +} catch(e) { 26.47 + print("Unprivileged execution failed with " + e) 26.48 +} 26.49 + 26.50 +print() 26.51 + 26.52 +// This should succeed, as it's going through doPrivileged(). 26.53 +print("Attempting privileged execution...") 26.54 +executePrivileged()
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/test/script/basic/JDK-8010946.js.EXPECTED Wed Jul 03 12:39:28 2013 +0200 27.3 @@ -0,0 +1,5 @@ 27.4 +Attempting unprivileged execution... 27.5 +Unprivileged execution failed with java.security.AccessControlException: access denied ("java.util.PropertyPermission" "java.security.policy" "read") 27.6 + 27.7 +Attempting privileged execution... 27.8 +Successfully retrieved restricted system property.