src/jdk/internal/dynalink/beans/AbstractJavaLinker.java

changeset 404
18d467e94150
parent 123
071e859b371e
child 439
973d78ee0728
equal deleted inserted replaced
403:4afdc5bec43b 404:18d467e94150
84 package jdk.internal.dynalink.beans; 84 package jdk.internal.dynalink.beans;
85 85
86 import java.lang.invoke.MethodHandle; 86 import java.lang.invoke.MethodHandle;
87 import java.lang.invoke.MethodHandles; 87 import java.lang.invoke.MethodHandles;
88 import java.lang.invoke.MethodType; 88 import java.lang.invoke.MethodType;
89 import java.lang.reflect.AccessibleObject;
90 import java.lang.reflect.Constructor;
89 import java.lang.reflect.Field; 91 import java.lang.reflect.Field;
92 import java.lang.reflect.Member;
90 import java.lang.reflect.Method; 93 import java.lang.reflect.Method;
91 import java.lang.reflect.Modifier; 94 import java.lang.reflect.Modifier;
92 import java.util.HashMap; 95 import java.util.HashMap;
93 import java.util.List; 96 import java.util.List;
94 import java.util.Map; 97 import java.util.Map;
107 * exposure and method calls for both static and instance facets of a class. 110 * exposure and method calls for both static and instance facets of a class.
108 * 111 *
109 * @author Attila Szegedi 112 * @author Attila Szegedi
110 */ 113 */
111 abstract class AbstractJavaLinker implements GuardingDynamicLinker { 114 abstract class AbstractJavaLinker implements GuardingDynamicLinker {
115
112 final Class<?> clazz; 116 final Class<?> clazz;
113 private final MethodHandle classGuard; 117 private final MethodHandle classGuard;
114 private final MethodHandle assignableGuard; 118 private final MethodHandle assignableGuard;
115 private final Map<String, AnnotatedMethodHandle> propertyGetters = new HashMap<>(); 119 private final Map<String, AnnotatedDynamicMethod> propertyGetters = new HashMap<>();
116 private final Map<String, DynamicMethod> propertySetters = new HashMap<>(); 120 private final Map<String, DynamicMethod> propertySetters = new HashMap<>();
117 private final Map<String, DynamicMethod> methods = new HashMap<>(); 121 private final Map<String, DynamicMethod> methods = new HashMap<>();
118 122
119 AbstractJavaLinker(Class<?> clazz, MethodHandle classGuard) { 123 AbstractJavaLinker(Class<?> clazz, MethodHandle classGuard) {
120 this(clazz, classGuard, classGuard); 124 this(clazz, classGuard, classGuard);
127 131
128 final FacetIntrospector introspector = createFacetIntrospector(); 132 final FacetIntrospector introspector = createFacetIntrospector();
129 // Add methods and properties 133 // Add methods and properties
130 for(Method method: introspector.getMethods()) { 134 for(Method method: introspector.getMethods()) {
131 final String name = method.getName(); 135 final String name = method.getName();
132 final MethodHandle methodHandle = introspector.unreflect(method);
133 // Add method 136 // Add method
134 addMember(name, methodHandle, methods); 137 addMember(name, method, methods);
135 // Add the method as a property getter and/or setter 138 // Add the method as a property getter and/or setter
136 if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) { 139 if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) {
137 // Property getter 140 // Property getter
138 setPropertyGetter(decapitalize(name.substring(3)), introspector.unreflect( 141 setPropertyGetter(method, 3);
139 getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
140 } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 && 142 } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 &&
141 method.getReturnType() == boolean.class) { 143 method.getReturnType() == boolean.class) {
142 // Boolean property getter 144 // Boolean property getter
143 setPropertyGetter(decapitalize(name.substring(2)), introspector.unreflect( 145 setPropertyGetter(method, 2);
144 getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
145 } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) { 146 } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
146 // Property setter 147 // Property setter
147 addMember(decapitalize(name.substring(3)), methodHandle, propertySetters); 148 addMember(decapitalize(name.substring(3)), method, propertySetters);
148 } 149 }
149 } 150 }
150 151
151 // Add field getter/setters as property getters/setters. 152 // Add field getter/setters as property getters/setters.
152 for(Field field: introspector.getFields()) { 153 for(Field field: introspector.getFields()) {
154 // Only add a property getter when one is not defined already as a getXxx()/isXxx() method. 155 // Only add a property getter when one is not defined already as a getXxx()/isXxx() method.
155 if(!propertyGetters.containsKey(name)) { 156 if(!propertyGetters.containsKey(name)) {
156 setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS); 157 setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS);
157 } 158 }
158 if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) { 159 if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) {
159 addMember(name, introspector.unreflectSetter(field), propertySetters); 160 addMember(name, new SimpleDynamicMethod(introspector.unreflectSetter(field), clazz, name),
161 propertySetters);
160 } 162 }
161 } 163 }
162 164
163 // Add inner classes, but only those for which we don't hide a property with it 165 // Add inner classes, but only those for which we don't hide a property with it
164 for(Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) { 166 for(Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
190 return new String(c); 192 return new String(c);
191 } 193 }
192 194
193 abstract FacetIntrospector createFacetIntrospector(); 195 abstract FacetIntrospector createFacetIntrospector();
194 196
197 /**
198 * Sets the specified dynamic method to be the property getter for the specified property. Note that you can only
199 * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties
200 * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)}
201 * instead.
202 * @param name name of the property
203 * @param handle the method handle that implements the property getter
204 * @param validationType the validation type for the property
205 */
206 private void setPropertyGetter(String name, SingleDynamicMethod handle, ValidationType validationType) {
207 propertyGetters.put(name, new AnnotatedDynamicMethod(handle, validationType));
208 }
209
210 /**
211 * Sets the specified reflective method to be the property getter for the specified property.
212 * @param getter the getter method
213 * @param prefixLen the getter prefix in the method name; should be 3 for getter names starting with "get" and 2 for
214 * names starting with "is".
215 */
216 private void setPropertyGetter(Method getter, int prefixLen) {
217 setPropertyGetter(decapitalize(getter.getName().substring(prefixLen)), createDynamicMethod(
218 getMostGenericGetter(getter)), ValidationType.INSTANCE_OF);
219 }
220
221 /**
222 * Sets the specified method handle to be the property getter for the specified property. Note that you can only
223 * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties
224 * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)}
225 * instead.
226 * @param name name of the property
227 * @param handle the method handle that implements the property getter
228 * @param validationType the validation type for the property
229 */
195 void setPropertyGetter(String name, MethodHandle handle, ValidationType validationType) { 230 void setPropertyGetter(String name, MethodHandle handle, ValidationType validationType) {
196 propertyGetters.put(name, new AnnotatedMethodHandle(handle, validationType)); 231 setPropertyGetter(name, new SimpleDynamicMethod(handle, clazz, name), validationType);
197 } 232 }
198 233
199 private void addMember(String name, MethodHandle mh, Map<String, DynamicMethod> methodMap) { 234 private void addMember(String name, AccessibleObject ao, Map<String, DynamicMethod> methodMap) {
235 addMember(name, createDynamicMethod(ao), methodMap);
236 }
237
238 private void addMember(String name, SingleDynamicMethod method, Map<String, DynamicMethod> methodMap) {
200 final DynamicMethod existingMethod = methodMap.get(name); 239 final DynamicMethod existingMethod = methodMap.get(name);
201 final DynamicMethod newMethod = addMember(mh, existingMethod, clazz, name); 240 final DynamicMethod newMethod = mergeMethods(method, existingMethod, clazz, name);
202 if(newMethod != existingMethod) { 241 if(newMethod != existingMethod) {
203 methodMap.put(name, newMethod); 242 methodMap.put(name, newMethod);
204 } 243 }
205 } 244 }
206 245
207 static DynamicMethod createDynamicMethod(Iterable<MethodHandle> methodHandles, Class<?> clazz, String name) { 246 /**
247 * Given one or more reflective methods or constructors, creates a dynamic method that represents them all. The
248 * methods should represent all overloads of the same name (or all constructors of the class).
249 * @param members the reflective members
250 * @param clazz the class declaring the reflective members
251 * @param name the common name of the reflective members.
252 * @return a dynamic method representing all the specified reflective members.
253 */
254 static DynamicMethod createDynamicMethod(Iterable<? extends AccessibleObject> members, Class<?> clazz, String name) {
208 DynamicMethod dynMethod = null; 255 DynamicMethod dynMethod = null;
209 for(MethodHandle methodHandle: methodHandles) { 256 for(AccessibleObject method: members) {
210 dynMethod = addMember(methodHandle, dynMethod, clazz, name); 257 dynMethod = mergeMethods(createDynamicMethod(method), dynMethod, clazz, name);
211 } 258 }
212 return dynMethod; 259 return dynMethod;
213 } 260 }
214 261
215 private static DynamicMethod addMember(MethodHandle mh, DynamicMethod existing, Class<?> clazz, String name) { 262 /**
263 * Given a reflective method or a constructor, creates a dynamic method that represents it. This method will
264 * distinguish between caller sensitive and ordinary methods/constructors, and create appropriate caller sensitive
265 * dynamic method when needed.
266 * @param m the reflective member
267 * @return the single dynamic method representing the reflective member
268 */
269 private static SingleDynamicMethod createDynamicMethod(AccessibleObject m) {
270 if(CallerSensitiveDetector.isCallerSensitive(m)) {
271 return new CallerSensitiveDynamicMethod(m);
272 }
273 final Member member = (Member)m;
274 return new SimpleDynamicMethod(unreflectSafely(m), member.getDeclaringClass(), member.getName());
275 }
276
277 /**
278 * Unreflects a method handle from a Method or a Constructor using safe (zero-privilege) unreflection. Should be
279 * only used for methods and constructors that are not caller sensitive. If a caller sensitive method were
280 * unreflected through this mechanism, it would not be a security issue, but would be bound to the zero-privilege
281 * unreflector as its caller, and thus completely useless.
282 * @param m the method or constructor
283 * @return the method handle
284 */
285 private static MethodHandle unreflectSafely(AccessibleObject m) {
286 if(m instanceof Method) {
287 final Method reflMethod = (Method)m;
288 final MethodHandle handle = SafeUnreflector.unreflect(reflMethod);
289 if(Modifier.isStatic(reflMethod.getModifiers())) {
290 return StaticClassIntrospector.editStaticMethodHandle(handle);
291 }
292 return handle;
293 }
294 return StaticClassIntrospector.editConstructorMethodHandle(SafeUnreflector.unreflectConstructor(
295 (Constructor<?>)m));
296 }
297
298 private static DynamicMethod mergeMethods(SingleDynamicMethod method, DynamicMethod existing, Class<?> clazz, String name) {
216 if(existing == null) { 299 if(existing == null) {
217 return new SimpleDynamicMethod(mh, clazz, name); 300 return method;
218 } else if(existing.contains(mh)) { 301 } else if(existing.contains(method)) {
219 return existing; 302 return existing;
220 } else if(existing instanceof SimpleDynamicMethod) { 303 } else if(existing instanceof SingleDynamicMethod) {
221 final OverloadedDynamicMethod odm = new OverloadedDynamicMethod(clazz, name); 304 final OverloadedDynamicMethod odm = new OverloadedDynamicMethod(clazz, name);
222 odm.addMethod(((SimpleDynamicMethod)existing)); 305 odm.addMethod(((SingleDynamicMethod)existing));
223 odm.addMethod(mh); 306 odm.addMethod(method);
224 return odm; 307 return odm;
225 } else if(existing instanceof OverloadedDynamicMethod) { 308 } else if(existing instanceof OverloadedDynamicMethod) {
226 ((OverloadedDynamicMethod)existing).addMethod(mh); 309 ((OverloadedDynamicMethod)existing).addMethod(method);
227 return existing; 310 return existing;
228 } 311 }
229 throw new AssertionError(); 312 throw new AssertionError();
230 } 313 }
231 314
294 } 377 }
295 378
296 private GuardedInvocation getCallPropWithThis(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) { 379 private GuardedInvocation getCallPropWithThis(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
297 switch(callSiteDescriptor.getNameTokenCount()) { 380 switch(callSiteDescriptor.getNameTokenCount()) {
298 case 3: { 381 case 3: {
299 return createGuardedDynamicMethodInvocation(callSiteDescriptor.getMethodType(), linkerServices, 382 return createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices,
300 callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), methods); 383 callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), methods);
301 } 384 }
302 default: { 385 default: {
303 return null; 386 return null;
304 } 387 }
305 } 388 }
306 } 389 }
307 390
308 private GuardedInvocation createGuardedDynamicMethodInvocation(MethodType callSiteType, 391 private GuardedInvocation createGuardedDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor,
309 LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap){ 392 LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap){
310 final MethodHandle inv = getDynamicMethodInvocation(callSiteType, linkerServices, methodName, methodMap); 393 final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap);
311 return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteType)); 394 return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteDescriptor.getMethodType()));
312 } 395 }
313 396
314 private static MethodHandle getDynamicMethodInvocation(MethodType callSiteType, LinkerServices linkerServices, 397 private static MethodHandle getDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor,
315 String methodName, Map<String, DynamicMethod> methodMap) { 398 LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap) {
316 final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap); 399 final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap);
317 return dynaMethod != null ? dynaMethod.getInvocation(callSiteType, linkerServices) : null; 400 return dynaMethod != null ? dynaMethod.getInvocation(callSiteDescriptor, linkerServices) : null;
318 } 401 }
319 402
320 private static DynamicMethod getDynamicMethod(String methodName, Map<String, DynamicMethod> methodMap) { 403 private static DynamicMethod getDynamicMethod(String methodName, Map<String, DynamicMethod> methodMap) {
321 final DynamicMethod dynaMethod = methodMap.get(methodName); 404 final DynamicMethod dynaMethod = methodMap.get(methodName);
322 return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap); 405 return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap);
323 } 406 }
324 407
325 private static SimpleDynamicMethod getExplicitSignatureDynamicMethod(String methodName, 408 private static SingleDynamicMethod getExplicitSignatureDynamicMethod(String methodName,
326 Map<String, DynamicMethod> methodsMap) { 409 Map<String, DynamicMethod> methodsMap) {
327 // What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name 410 // What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name
328 // to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method 411 // to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method
329 // resolution works correctly in almost every situation. However, in presence of many language-specific 412 // resolution works correctly in almost every situation. However, in presence of many language-specific
330 // conversions with a radically dynamic language, most overloaded methods will end up being constantly selected 413 // conversions with a radically dynamic language, most overloaded methods will end up being constantly selected
331 // at invocation time, so a programmer knowledgable of the situation might choose to pin down an exact overload 414 // at invocation time, so a programmer knowledgeable of the situation might choose to pin down an exact overload
332 // for performance reasons. 415 // for performance reasons.
333 416
334 // Is the method name lexically of the form "name(types)"? 417 // Is the method name lexically of the form "name(types)"?
335 final int lastChar = methodName.length() - 1; 418 final int lastChar = methodName.length() - 1;
336 if(methodName.charAt(lastChar) != ')') { 419 if(methodName.charAt(lastChar) != ')') {
375 // abbreviate to R(O, N, V) going forward. 458 // abbreviate to R(O, N, V) going forward.
376 // We want setters that conform to "R(O, V)" 459 // We want setters that conform to "R(O, V)"
377 final MethodType setterType = type.dropParameterTypes(1, 2); 460 final MethodType setterType = type.dropParameterTypes(1, 2);
378 // Bind property setter handle to the expected setter type and linker services. Type is 461 // Bind property setter handle to the expected setter type and linker services. Type is
379 // MethodHandle(Object, String, Object) 462 // MethodHandle(Object, String, Object)
380 final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0, setterType, 463 final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0,
381 linkerServices); 464 CallSiteDescriptorFactory.dropParameterTypes(callSiteDescriptor, 1, 2), linkerServices);
382 465
383 // Cast getter to MethodHandle(O, N, V) 466 // Cast getter to MethodHandle(O, N, V)
384 final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType( 467 final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType(
385 MethodHandle.class)); 468 MethodHandle.class));
386 469
413 return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); 496 return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
414 } 497 }
415 case 3: { 498 case 3: {
416 // Must have two arguments: target object and property value 499 // Must have two arguments: target object and property value
417 assertParameterCount(callSiteDescriptor, 2); 500 assertParameterCount(callSiteDescriptor, 2);
418 final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor.getMethodType(), 501 final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices,
419 linkerServices, callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), 502 callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), propertySetters);
420 propertySetters);
421 // If we have a property setter with this name, this composite operation will always stop here 503 // If we have a property setter with this name, this composite operation will always stop here
422 if(gi != null) { 504 if(gi != null) {
423 return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS); 505 return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS);
424 } 506 }
425 // If we don't have a property setter with this name, always fall back to the next operation in the 507 // If we don't have a property setter with this name, always fall back to the next operation in the
433 } 515 }
434 } 516 }
435 517
436 private static final Lookup privateLookup = new Lookup(MethodHandles.lookup()); 518 private static final Lookup privateLookup = new Lookup(MethodHandles.lookup());
437 519
438 private static final MethodHandle IS_ANNOTATED_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType( 520 private static final MethodHandle IS_ANNOTATED_METHOD_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
439 boolean.class, AnnotatedMethodHandle.class)); 521 boolean.class, AnnotatedDynamicMethod.class));
440 private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_HANDLE = MethodHandles.dropArguments( 522 private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_METHOD = MethodHandles.dropArguments(
441 MethodHandles.constant(Object.class, null), 0, AnnotatedMethodHandle.class); 523 MethodHandles.constant(Object.class, null), 0, AnnotatedDynamicMethod.class);
442 private static final MethodHandle GET_ANNOTATED_HANDLE = privateLookup.findGetter(AnnotatedMethodHandle.class, 524 private static final MethodHandle GET_ANNOTATED_METHOD = privateLookup.findVirtual(AnnotatedDynamicMethod.class,
443 "handle", MethodHandle.class); 525 "getTarget", MethodType.methodType(MethodHandle.class, MethodHandles.Lookup.class));
444 private static final MethodHandle GENERIC_PROPERTY_GETTER_HANDLER_INVOKER = MethodHandles.filterArguments( 526 private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class));
445 MethodHandles.invoker(MethodType.methodType(Object.class, Object.class)), 0, GET_ANNOTATED_HANDLE);
446 527
447 private GuardedInvocationComponent getPropertyGetter(CallSiteDescriptor callSiteDescriptor, 528 private GuardedInvocationComponent getPropertyGetter(CallSiteDescriptor callSiteDescriptor,
448 LinkerServices linkerServices, List<String> ops) throws Exception { 529 LinkerServices linkerServices, List<String> ops) throws Exception {
449 final MethodType type = callSiteDescriptor.getMethodType(); 530 final MethodType type = callSiteDescriptor.getMethodType();
450 switch(callSiteDescriptor.getNameTokenCount()) { 531 switch(callSiteDescriptor.getNameTokenCount()) {
453 assertParameterCount(callSiteDescriptor, 2); 534 assertParameterCount(callSiteDescriptor, 2);
454 535
455 // What's below is basically: 536 // What's below is basically:
456 // foldArguments(guardWithTest(isNotNull, invoke(get_handle), null|nextComponent.invocation), get_getter_handle) 537 // foldArguments(guardWithTest(isNotNull, invoke(get_handle), null|nextComponent.invocation), get_getter_handle)
457 // only with a bunch of method signature adjustments. Basically, retrieve method getter 538 // only with a bunch of method signature adjustments. Basically, retrieve method getter
458 // AnnotatedMethodHandle; if it is non-null, invoke its "handle" field, otherwise either return null, 539 // AnnotatedDynamicMethod; if it is non-null, invoke its "handle" field, otherwise either return null,
459 // or delegate to next component's invocation. 540 // or delegate to next component's invocation.
460 541
461 final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType( 542 final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType(
462 AnnotatedMethodHandle.class)); 543 AnnotatedDynamicMethod.class));
463 // Object(AnnotatedMethodHandle, Object)->R(AnnotatedMethodHandle, T0) 544 final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments(
464 final MethodHandle invokeHandleTyped = linkerServices.asType(GENERIC_PROPERTY_GETTER_HANDLER_INVOKER, 545 GET_ANNOTATED_METHOD, 1, callSiteDescriptor.getLookup());
465 MethodType.methodType(type.returnType(), AnnotatedMethodHandle.class, type.parameterType(0))); 546 final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0,
547 callSiteBoundMethodGetter);
548 // Object(AnnotatedDynamicMethod, Object)->R(AnnotatedDynamicMethod, T0)
549 final MethodHandle invokeHandleTyped = linkerServices.asType(callSiteBoundInvoker,
550 MethodType.methodType(type.returnType(), AnnotatedDynamicMethod.class, type.parameterType(0)));
466 // Since it's in the target of a fold, drop the unnecessary second argument 551 // Since it's in the target of a fold, drop the unnecessary second argument
467 // R(AnnotatedMethodHandle, T0)->R(AnnotatedMethodHandle, T0, T1) 552 // R(AnnotatedDynamicMethod, T0)->R(AnnotatedDynamicMethod, T0, T1)
468 final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2, 553 final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2,
469 type.parameterType(1)); 554 type.parameterType(1));
470 final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, 555 final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
471 linkerServices, ops); 556 linkerServices, ops);
472 557
473 final MethodHandle fallbackFolded; 558 final MethodHandle fallbackFolded;
474 if(nextComponent == null) { 559 if(nextComponent == null) {
475 // Object(AnnotatedMethodHandle)->R(AnnotatedMethodHandle, T0, T1); returns constant null 560 // Object(AnnotatedDynamicMethod)->R(AnnotatedDynamicMethod, T0, T1); returns constant null
476 fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_HANDLE, 1, 561 fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_METHOD, 1,
477 type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedMethodHandle.class)); 562 type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedDynamicMethod.class));
478 } else { 563 } else {
479 // R(T0, T1)->R(AnnotatedMethodHAndle, T0, T1); adapts the next component's invocation to drop the 564 // R(T0, T1)->R(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to drop the
480 // extra argument resulting from fold 565 // extra argument resulting from fold
481 fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(), 566 fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
482 0, AnnotatedMethodHandle.class); 567 0, AnnotatedDynamicMethod.class);
483 } 568 }
484 569
485 // fold(R(AnnotatedMethodHandle, T0, T1), AnnotatedMethodHandle(T0, T1)) 570 // fold(R(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1))
486 final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( 571 final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
487 IS_ANNOTATED_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); 572 IS_ANNOTATED_METHOD_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
488 if(nextComponent == null) { 573 if(nextComponent == null) {
489 return getClassGuardedInvocationComponent(compositeGetter, type); 574 return getClassGuardedInvocationComponent(compositeGetter, type);
490 } 575 }
491 return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); 576 return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
492 } 577 }
493 case 3: { 578 case 3: {
494 // Must have exactly one argument: receiver 579 // Must have exactly one argument: receiver
495 assertParameterCount(callSiteDescriptor, 1); 580 assertParameterCount(callSiteDescriptor, 1);
496 // Fixed name 581 // Fixed name
497 final AnnotatedMethodHandle annGetter = propertyGetters.get(callSiteDescriptor.getNameToken( 582 final AnnotatedDynamicMethod annGetter = propertyGetters.get(callSiteDescriptor.getNameToken(
498 CallSiteDescriptor.NAME_OPERAND)); 583 CallSiteDescriptor.NAME_OPERAND));
499 if(annGetter == null) { 584 if(annGetter == null) {
500 // We have no such property, always delegate to the next component operation 585 // We have no such property, always delegate to the next component operation
501 return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops); 586 return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops);
502 } 587 }
503 final MethodHandle getter = annGetter.handle; 588 final MethodHandle getter = annGetter.getInvocation(callSiteDescriptor, linkerServices);
504 // NOTE: since property getters (not field getters!) are no-arg, we don't have to worry about them being 589 // NOTE: since property getters (not field getters!) are no-arg, we don't have to worry about them being
505 // overloaded in a subclass. Therefore, we can discover the most abstract superclass that has the 590 // overloaded in a subclass. Therefore, we can discover the most abstract superclass that has the
506 // method, and use that as the guard with Guards.isInstance() for a more stably linked call site. If 591 // method, and use that as the guard with Guards.isInstance() for a more stably linked call site. If
507 // we're linking against a field getter, don't make the assumption. 592 // we're linking against a field getter, don't make the assumption.
508 // NOTE: No delegation to the next component operation if we have a property with this name, even if its 593 // NOTE: No delegation to the next component operation if we have a property with this name, even if its
509 // value is null. 594 // value is null.
510 final ValidationType validationType = annGetter.validationType; 595 final ValidationType validationType = annGetter.validationType;
596 // TODO: we aren't using the type that declares the most generic getter here!
511 return new GuardedInvocationComponent(linkerServices.asType(getter, type), getGuard(validationType, 597 return new GuardedInvocationComponent(linkerServices.asType(getter, type), getGuard(validationType,
512 type), clazz, validationType); 598 type), clazz, validationType);
513 } 599 }
514 default: { 600 default: {
515 // Can't do anything with more than 3 name components 601 // Can't do anything with more than 3 name components
621 707
622 // Type is MethodHandle(BeanLinker, MethodType, LinkerServices, Object, String, Object), of which the two "Object" 708 // Type is MethodHandle(BeanLinker, MethodType, LinkerServices, Object, String, Object), of which the two "Object"
623 // args are dropped; this makes handles with first three args conform to "Object, String, Object" though, which is 709 // args are dropped; this makes handles with first three args conform to "Object, String, Object" though, which is
624 // a typical property setter with variable name signature (target, name, value). 710 // a typical property setter with variable name signature (target, name, value).
625 private static final MethodHandle GET_PROPERTY_SETTER_HANDLE = MethodHandles.dropArguments(MethodHandles.dropArguments( 711 private static final MethodHandle GET_PROPERTY_SETTER_HANDLE = MethodHandles.dropArguments(MethodHandles.dropArguments(
626 privateLookup.findOwnSpecial("getPropertySetterHandle", MethodHandle.class, MethodType.class, 712 privateLookup.findOwnSpecial("getPropertySetterHandle", MethodHandle.class, CallSiteDescriptor.class,
627 LinkerServices.class, Object.class), 3, Object.class), 5, Object.class); 713 LinkerServices.class, Object.class), 3, Object.class), 5, Object.class);
628 // Type is MethodHandle(MethodType, LinkerServices, Object, String, Object) 714 // Type is MethodHandle(MethodType, LinkerServices, Object, String, Object)
629 private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this); 715 private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this);
630 716
631 @SuppressWarnings("unused") 717 @SuppressWarnings("unused")
632 private MethodHandle getPropertySetterHandle(MethodType setterType, LinkerServices linkerServices, Object id) { 718 private MethodHandle getPropertySetterHandle(CallSiteDescriptor setterDescriptor, LinkerServices linkerServices,
633 return getDynamicMethodInvocation(setterType, linkerServices, String.valueOf(id), propertySetters); 719 Object id) {
720 return getDynamicMethodInvocation(setterDescriptor, linkerServices, String.valueOf(id), propertySetters);
634 } 721 }
635 722
636 private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial( 723 private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
637 "getDynamicMethod", DynamicMethod.class, Object.class), 1, Object.class); 724 "getDynamicMethod", DynamicMethod.class, Object.class), 1, Object.class);
638 private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this); 725 private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this);
687 } 774 }
688 } 775 }
689 return null; 776 return null;
690 } 777 }
691 778
692 private static final class AnnotatedMethodHandle { 779 private static final class AnnotatedDynamicMethod {
693 final MethodHandle handle; 780 private final SingleDynamicMethod method;
694 /*private*/ final ValidationType validationType; 781 /*private*/ final ValidationType validationType;
695 782
696 AnnotatedMethodHandle(MethodHandle handle, ValidationType validationType) { 783 AnnotatedDynamicMethod(SingleDynamicMethod method, ValidationType validationType) {
697 this.handle = handle; 784 this.method = method;
698 this.validationType = validationType; 785 this.validationType = validationType;
699 } 786 }
787
788 MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
789 return method.getInvocation(callSiteDescriptor, linkerServices);
790 }
791
792 @SuppressWarnings("unused")
793 MethodHandle getTarget(MethodHandles.Lookup lookup) {
794 MethodHandle inv = method.getTarget(lookup);
795 assert inv != null;
796 return inv;
797 }
700 } 798 }
701 } 799 }

mercurial