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

changeset 0
b1a7da25b547
child 952
6d5471a497fb
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java	Wed Apr 27 01:36:41 2016 +0800
     1.3 @@ -0,0 +1,817 @@
     1.4 +/*
     1.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +/*
    1.30 + * This file is available under and governed by the GNU General Public
    1.31 + * License version 2 only, as published by the Free Software Foundation.
    1.32 + * However, the following notice accompanied the original version of this
    1.33 + * file, and Oracle licenses the original version of this file under the BSD
    1.34 + * license:
    1.35 + */
    1.36 +/*
    1.37 +   Copyright 2009-2013 Attila Szegedi
    1.38 +
    1.39 +   Licensed under both the Apache License, Version 2.0 (the "Apache License")
    1.40 +   and the BSD License (the "BSD License"), with licensee being free to
    1.41 +   choose either of the two at their discretion.
    1.42 +
    1.43 +   You may not use this file except in compliance with either the Apache
    1.44 +   License or the BSD License.
    1.45 +
    1.46 +   If you choose to use this file in compliance with the Apache License, the
    1.47 +   following notice applies to you:
    1.48 +
    1.49 +       You may obtain a copy of the Apache License at
    1.50 +
    1.51 +           http://www.apache.org/licenses/LICENSE-2.0
    1.52 +
    1.53 +       Unless required by applicable law or agreed to in writing, software
    1.54 +       distributed under the License is distributed on an "AS IS" BASIS,
    1.55 +       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    1.56 +       implied. See the License for the specific language governing
    1.57 +       permissions and limitations under the License.
    1.58 +
    1.59 +   If you choose to use this file in compliance with the BSD License, the
    1.60 +   following notice applies to you:
    1.61 +
    1.62 +       Redistribution and use in source and binary forms, with or without
    1.63 +       modification, are permitted provided that the following conditions are
    1.64 +       met:
    1.65 +       * Redistributions of source code must retain the above copyright
    1.66 +         notice, this list of conditions and the following disclaimer.
    1.67 +       * Redistributions in binary form must reproduce the above copyright
    1.68 +         notice, this list of conditions and the following disclaimer in the
    1.69 +         documentation and/or other materials provided with the distribution.
    1.70 +       * Neither the name of the copyright holder nor the names of
    1.71 +         contributors may be used to endorse or promote products derived from
    1.72 +         this software without specific prior written permission.
    1.73 +
    1.74 +       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    1.75 +       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    1.76 +       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    1.77 +       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
    1.78 +       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    1.79 +       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    1.80 +       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
    1.81 +       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    1.82 +       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    1.83 +       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
    1.84 +       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.85 +*/
    1.86 +
    1.87 +package jdk.internal.dynalink.beans;
    1.88 +
    1.89 +import java.lang.invoke.MethodHandle;
    1.90 +import java.lang.invoke.MethodHandles;
    1.91 +import java.lang.invoke.MethodType;
    1.92 +import java.lang.reflect.AccessibleObject;
    1.93 +import java.lang.reflect.Constructor;
    1.94 +import java.lang.reflect.Field;
    1.95 +import java.lang.reflect.Member;
    1.96 +import java.lang.reflect.Method;
    1.97 +import java.lang.reflect.Modifier;
    1.98 +import java.util.Collection;
    1.99 +import java.util.Collections;
   1.100 +import java.util.HashMap;
   1.101 +import java.util.List;
   1.102 +import java.util.Map;
   1.103 +
   1.104 +import jdk.internal.dynalink.CallSiteDescriptor;
   1.105 +import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType;
   1.106 +import jdk.internal.dynalink.linker.GuardedInvocation;
   1.107 +import jdk.internal.dynalink.linker.GuardingDynamicLinker;
   1.108 +import jdk.internal.dynalink.linker.LinkRequest;
   1.109 +import jdk.internal.dynalink.linker.LinkerServices;
   1.110 +import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
   1.111 +import jdk.internal.dynalink.support.Guards;
   1.112 +import jdk.internal.dynalink.support.Lookup;
   1.113 +
   1.114 +/**
   1.115 + * A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property
   1.116 + * exposure and method calls for both static and instance facets of a class.
   1.117 + *
   1.118 + * @author Attila Szegedi
   1.119 + */
   1.120 +abstract class AbstractJavaLinker implements GuardingDynamicLinker {
   1.121 +
   1.122 +    final Class<?> clazz;
   1.123 +    private final MethodHandle classGuard;
   1.124 +    private final MethodHandle assignableGuard;
   1.125 +    private final Map<String, AnnotatedDynamicMethod> propertyGetters = new HashMap<>();
   1.126 +    private final Map<String, DynamicMethod> propertySetters = new HashMap<>();
   1.127 +    private final Map<String, DynamicMethod> methods = new HashMap<>();
   1.128 +
   1.129 +    AbstractJavaLinker(Class<?> clazz, MethodHandle classGuard) {
   1.130 +        this(clazz, classGuard, classGuard);
   1.131 +    }
   1.132 +
   1.133 +    AbstractJavaLinker(Class<?> clazz, MethodHandle classGuard, MethodHandle assignableGuard) {
   1.134 +        this.clazz = clazz;
   1.135 +        this.classGuard = classGuard;
   1.136 +        this.assignableGuard = assignableGuard;
   1.137 +
   1.138 +        final FacetIntrospector introspector = createFacetIntrospector();
   1.139 +        // Add methods and properties
   1.140 +        for(Method method: introspector.getMethods()) {
   1.141 +            final String name = method.getName();
   1.142 +            // Add method
   1.143 +            addMember(name, method, methods);
   1.144 +            // Add the method as a property getter and/or setter
   1.145 +            if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) {
   1.146 +                // Property getter
   1.147 +                setPropertyGetter(method, 3);
   1.148 +            } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 &&
   1.149 +                    method.getReturnType() == boolean.class) {
   1.150 +                // Boolean property getter
   1.151 +                setPropertyGetter(method, 2);
   1.152 +            } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
   1.153 +                // Property setter
   1.154 +                addMember(decapitalize(name.substring(3)), method, propertySetters);
   1.155 +            }
   1.156 +        }
   1.157 +
   1.158 +        // Add field getter/setters as property getters/setters.
   1.159 +        for(Field field: introspector.getFields()) {
   1.160 +            final String name = field.getName();
   1.161 +            // Only add a property getter when one is not defined already as a getXxx()/isXxx() method.
   1.162 +            if(!propertyGetters.containsKey(name)) {
   1.163 +                setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS);
   1.164 +            }
   1.165 +            if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) {
   1.166 +                addMember(name, new SimpleDynamicMethod(introspector.unreflectSetter(field), clazz, name),
   1.167 +                        propertySetters);
   1.168 +            }
   1.169 +        }
   1.170 +
   1.171 +        // Add inner classes, but only those for which we don't hide a property with it
   1.172 +        for(Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
   1.173 +            final String name = innerClassSpec.getKey();
   1.174 +            if(!propertyGetters.containsKey(name)) {
   1.175 +                setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS);
   1.176 +            }
   1.177 +        }
   1.178 +    }
   1.179 +
   1.180 +    private static String decapitalize(String str) {
   1.181 +        assert str != null;
   1.182 +        if(str.isEmpty()) {
   1.183 +            return str;
   1.184 +        }
   1.185 +
   1.186 +        final char c0 = str.charAt(0);
   1.187 +        if(Character.isLowerCase(c0)) {
   1.188 +            return str;
   1.189 +        }
   1.190 +
   1.191 +        // If it has two consecutive upper-case characters, i.e. "URL", don't decapitalize
   1.192 +        if(str.length() > 1 && Character.isUpperCase(str.charAt(1))) {
   1.193 +            return str;
   1.194 +        }
   1.195 +
   1.196 +        final char c[] = str.toCharArray();
   1.197 +        c[0] = Character.toLowerCase(c0);
   1.198 +        return new String(c);
   1.199 +    }
   1.200 +
   1.201 +    abstract FacetIntrospector createFacetIntrospector();
   1.202 +
   1.203 +    Collection<String> getReadablePropertyNames() {
   1.204 +        return getUnmodifiableKeys(propertyGetters);
   1.205 +    }
   1.206 +
   1.207 +    Collection<String> getWritablePropertyNames() {
   1.208 +        return getUnmodifiableKeys(propertySetters);
   1.209 +    }
   1.210 +
   1.211 +    Collection<String> getMethodNames() {
   1.212 +        return getUnmodifiableKeys(methods);
   1.213 +    }
   1.214 +
   1.215 +    private static Collection<String> getUnmodifiableKeys(Map<String, ?> m) {
   1.216 +        return Collections.unmodifiableCollection(m.keySet());
   1.217 +    }
   1.218 +
   1.219 +    /**
   1.220 +     * Sets the specified dynamic method to be the property getter for the specified property. Note that you can only
   1.221 +     * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties
   1.222 +     * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)}
   1.223 +     * instead.
   1.224 +     * @param name name of the property
   1.225 +     * @param handle the method handle that implements the property getter
   1.226 +     * @param validationType the validation type for the property
   1.227 +     */
   1.228 +    private void setPropertyGetter(String name, SingleDynamicMethod handle, ValidationType validationType) {
   1.229 +        propertyGetters.put(name, new AnnotatedDynamicMethod(handle, validationType));
   1.230 +    }
   1.231 +
   1.232 +    /**
   1.233 +     * Sets the specified reflective method to be the property getter for the specified property.
   1.234 +     * @param getter the getter method
   1.235 +     * @param prefixLen the getter prefix in the method name; should be 3 for getter names starting with "get" and 2 for
   1.236 +     * names starting with "is".
   1.237 +     */
   1.238 +    private void setPropertyGetter(Method getter, int prefixLen) {
   1.239 +        setPropertyGetter(decapitalize(getter.getName().substring(prefixLen)), createDynamicMethod(
   1.240 +                getMostGenericGetter(getter)), ValidationType.INSTANCE_OF);
   1.241 +    }
   1.242 +
   1.243 +    /**
   1.244 +     * Sets the specified method handle to be the property getter for the specified property. Note that you can only
   1.245 +     * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties
   1.246 +     * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)}
   1.247 +     * instead.
   1.248 +     * @param name name of the property
   1.249 +     * @param handle the method handle that implements the property getter
   1.250 +     * @param validationType the validation type for the property
   1.251 +     */
   1.252 +    void setPropertyGetter(String name, MethodHandle handle, ValidationType validationType) {
   1.253 +        setPropertyGetter(name, new SimpleDynamicMethod(handle, clazz, name), validationType);
   1.254 +    }
   1.255 +
   1.256 +    private void addMember(String name, AccessibleObject ao, Map<String, DynamicMethod> methodMap) {
   1.257 +        addMember(name, createDynamicMethod(ao), methodMap);
   1.258 +    }
   1.259 +
   1.260 +    private void addMember(String name, SingleDynamicMethod method, Map<String, DynamicMethod> methodMap) {
   1.261 +        final DynamicMethod existingMethod = methodMap.get(name);
   1.262 +        final DynamicMethod newMethod = mergeMethods(method, existingMethod, clazz, name);
   1.263 +        if(newMethod != existingMethod) {
   1.264 +            methodMap.put(name, newMethod);
   1.265 +        }
   1.266 +    }
   1.267 +
   1.268 +    /**
   1.269 +     * Given one or more reflective methods or constructors, creates a dynamic method that represents them all. The
   1.270 +     * methods should represent all overloads of the same name (or all constructors of the class).
   1.271 +     * @param members the reflective members
   1.272 +     * @param clazz the class declaring the reflective members
   1.273 +     * @param name the common name of the reflective members.
   1.274 +     * @return a dynamic method representing all the specified reflective members.
   1.275 +     */
   1.276 +    static DynamicMethod createDynamicMethod(Iterable<? extends AccessibleObject> members, Class<?> clazz, String name) {
   1.277 +        DynamicMethod dynMethod = null;
   1.278 +        for(AccessibleObject method: members) {
   1.279 +            dynMethod = mergeMethods(createDynamicMethod(method), dynMethod, clazz, name);
   1.280 +        }
   1.281 +        return dynMethod;
   1.282 +    }
   1.283 +
   1.284 +    /**
   1.285 +     * Given a reflective method or a constructor, creates a dynamic method that represents it. This method will
   1.286 +     * distinguish between caller sensitive and ordinary methods/constructors, and create appropriate caller sensitive
   1.287 +     * dynamic method when needed.
   1.288 +     * @param m the reflective member
   1.289 +     * @return the single dynamic method representing the reflective member
   1.290 +     */
   1.291 +    private static SingleDynamicMethod createDynamicMethod(AccessibleObject m) {
   1.292 +        if(CallerSensitiveDetector.isCallerSensitive(m)) {
   1.293 +            return new CallerSensitiveDynamicMethod(m);
   1.294 +        }
   1.295 +        final Member member = (Member)m;
   1.296 +        return new SimpleDynamicMethod(unreflectSafely(m), member.getDeclaringClass(), member.getName());
   1.297 +    }
   1.298 +
   1.299 +    /**
   1.300 +     * Unreflects a method handle from a Method or a Constructor using safe (zero-privilege) unreflection. Should be
   1.301 +     * only used for methods and constructors that are not caller sensitive. If a caller sensitive method were
   1.302 +     * unreflected through this mechanism, it would not be a security issue, but would be bound to the zero-privilege
   1.303 +     * unreflector as its caller, and thus completely useless.
   1.304 +     * @param m the method or constructor
   1.305 +     * @return the method handle
   1.306 +     */
   1.307 +    private static MethodHandle unreflectSafely(AccessibleObject m) {
   1.308 +        if(m instanceof Method) {
   1.309 +            final Method reflMethod = (Method)m;
   1.310 +            final MethodHandle handle = Lookup.PUBLIC.unreflect(reflMethod);
   1.311 +            if(Modifier.isStatic(reflMethod.getModifiers())) {
   1.312 +                return StaticClassIntrospector.editStaticMethodHandle(handle);
   1.313 +            }
   1.314 +            return handle;
   1.315 +        }
   1.316 +        return StaticClassIntrospector.editConstructorMethodHandle(Lookup.PUBLIC.unreflectConstructor((Constructor<?>)m));
   1.317 +    }
   1.318 +
   1.319 +    private static DynamicMethod mergeMethods(SingleDynamicMethod method, DynamicMethod existing, Class<?> clazz, String name) {
   1.320 +        if(existing == null) {
   1.321 +            return method;
   1.322 +        } else if(existing.contains(method)) {
   1.323 +            return existing;
   1.324 +        } else if(existing instanceof SingleDynamicMethod) {
   1.325 +            final OverloadedDynamicMethod odm = new OverloadedDynamicMethod(clazz, name);
   1.326 +            odm.addMethod(((SingleDynamicMethod)existing));
   1.327 +            odm.addMethod(method);
   1.328 +            return odm;
   1.329 +        } else if(existing instanceof OverloadedDynamicMethod) {
   1.330 +            ((OverloadedDynamicMethod)existing).addMethod(method);
   1.331 +            return existing;
   1.332 +        }
   1.333 +        throw new AssertionError();
   1.334 +    }
   1.335 +
   1.336 +    @Override
   1.337 +    public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices)
   1.338 +            throws Exception {
   1.339 +        final LinkRequest ncrequest = request.withoutRuntimeContext();
   1.340 +        // BeansLinker already checked that the name is at least 2 elements long and the first element is "dyn".
   1.341 +        final CallSiteDescriptor callSiteDescriptor = ncrequest.getCallSiteDescriptor();
   1.342 +        final String op = callSiteDescriptor.getNameToken(CallSiteDescriptor.OPERATOR);
   1.343 +        // Either dyn:callMethod:name(this[,args]) or dyn:callMethod(this,name[,args]).
   1.344 +        if("callMethod" == op) {
   1.345 +            return getCallPropWithThis(callSiteDescriptor, linkerServices);
   1.346 +        }
   1.347 +        List<String> operations = CallSiteDescriptorFactory.tokenizeOperators(callSiteDescriptor);
   1.348 +        while(!operations.isEmpty()) {
   1.349 +            final GuardedInvocationComponent gic = getGuardedInvocationComponent(callSiteDescriptor, linkerServices,
   1.350 +                    operations);
   1.351 +            if(gic != null) {
   1.352 +                return gic.getGuardedInvocation();
   1.353 +            }
   1.354 +            operations = pop(operations);
   1.355 +        }
   1.356 +        return null;
   1.357 +    }
   1.358 +
   1.359 +    protected GuardedInvocationComponent getGuardedInvocationComponent(CallSiteDescriptor callSiteDescriptor,
   1.360 +            LinkerServices linkerServices, List<String> operations) throws Exception {
   1.361 +        if(operations.isEmpty()) {
   1.362 +            return null;
   1.363 +        }
   1.364 +        final String op = operations.get(0);
   1.365 +        // Either dyn:getProp:name(this) or dyn:getProp(this, name)
   1.366 +        if("getProp".equals(op)) {
   1.367 +            return getPropertyGetter(callSiteDescriptor, linkerServices, pop(operations));
   1.368 +        }
   1.369 +        // Either dyn:setProp:name(this, value) or dyn:setProp(this, name, value)
   1.370 +        if("setProp".equals(op)) {
   1.371 +            return getPropertySetter(callSiteDescriptor, linkerServices, pop(operations));
   1.372 +        }
   1.373 +        // Either dyn:getMethod:name(this), or dyn:getMethod(this, name)
   1.374 +        if("getMethod".equals(op)) {
   1.375 +            return getMethodGetter(callSiteDescriptor, linkerServices, pop(operations));
   1.376 +        }
   1.377 +        return null;
   1.378 +    }
   1.379 +
   1.380 +    static final <T> List<T> pop(List<T> l) {
   1.381 +        return l.subList(1, l.size());
   1.382 +    }
   1.383 +
   1.384 +    MethodHandle getClassGuard(CallSiteDescriptor desc) {
   1.385 +        return getClassGuard(desc.getMethodType());
   1.386 +    }
   1.387 +
   1.388 +    MethodHandle getClassGuard(MethodType type) {
   1.389 +        return Guards.asType(classGuard, type);
   1.390 +    }
   1.391 +
   1.392 +    GuardedInvocationComponent getClassGuardedInvocationComponent(MethodHandle invocation, MethodType type) {
   1.393 +        return new GuardedInvocationComponent(invocation, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
   1.394 +    }
   1.395 +
   1.396 +    private MethodHandle getAssignableGuard(MethodType type) {
   1.397 +        return Guards.asType(assignableGuard, type);
   1.398 +    }
   1.399 +
   1.400 +    private GuardedInvocation getCallPropWithThis(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
   1.401 +        switch(callSiteDescriptor.getNameTokenCount()) {
   1.402 +            case 3: {
   1.403 +                return createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices,
   1.404 +                        callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), methods);
   1.405 +            }
   1.406 +            default: {
   1.407 +                return null;
   1.408 +            }
   1.409 +        }
   1.410 +    }
   1.411 +
   1.412 +    private GuardedInvocation createGuardedDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor,
   1.413 +            LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap){
   1.414 +        final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap);
   1.415 +        return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteDescriptor.getMethodType()));
   1.416 +    }
   1.417 +
   1.418 +    private static MethodHandle getDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor,
   1.419 +            LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap) {
   1.420 +        final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap);
   1.421 +        return dynaMethod != null ? dynaMethod.getInvocation(callSiteDescriptor, linkerServices) : null;
   1.422 +    }
   1.423 +
   1.424 +    private static DynamicMethod getDynamicMethod(String methodName, Map<String, DynamicMethod> methodMap) {
   1.425 +        final DynamicMethod dynaMethod = methodMap.get(methodName);
   1.426 +        return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap);
   1.427 +    }
   1.428 +
   1.429 +    private static SingleDynamicMethod getExplicitSignatureDynamicMethod(String methodName,
   1.430 +            Map<String, DynamicMethod> methodsMap) {
   1.431 +        // What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name
   1.432 +        // to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method
   1.433 +        // resolution works correctly in almost every situation. However, in presence of many language-specific
   1.434 +        // conversions with a radically dynamic language, most overloaded methods will end up being constantly selected
   1.435 +        // at invocation time, so a programmer knowledgeable of the situation might choose to pin down an exact overload
   1.436 +        // for performance reasons.
   1.437 +
   1.438 +        // Is the method name lexically of the form "name(types)"?
   1.439 +        final int lastChar = methodName.length() - 1;
   1.440 +        if(methodName.charAt(lastChar) != ')') {
   1.441 +            return null;
   1.442 +        }
   1.443 +        final int openBrace = methodName.indexOf('(');
   1.444 +        if(openBrace == -1) {
   1.445 +            return null;
   1.446 +        }
   1.447 +
   1.448 +        // Find an existing method for the "name" part
   1.449 +        final DynamicMethod simpleNamedMethod = methodsMap.get(methodName.substring(0, openBrace));
   1.450 +        if(simpleNamedMethod == null) {
   1.451 +            return null;
   1.452 +        }
   1.453 +
   1.454 +        // Try to get a narrowed dynamic method for the explicit parameter types.
   1.455 +        return simpleNamedMethod.getMethodForExactParamTypes(methodName.substring(openBrace + 1, lastChar));
   1.456 +    }
   1.457 +
   1.458 +    private static final MethodHandle IS_METHOD_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
   1.459 +            boolean.class, MethodHandle.class));
   1.460 +    private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments(
   1.461 +            MethodHandles.constant(Object.class, null), 0, MethodHandle.class);
   1.462 +
   1.463 +    private GuardedInvocationComponent getPropertySetter(CallSiteDescriptor callSiteDescriptor,
   1.464 +            LinkerServices linkerServices, List<String> operations) throws Exception {
   1.465 +        final MethodType type = callSiteDescriptor.getMethodType();
   1.466 +        switch(callSiteDescriptor.getNameTokenCount()) {
   1.467 +            case 2: {
   1.468 +                // Must have three arguments: target object, property name, and property value.
   1.469 +                assertParameterCount(callSiteDescriptor, 3);
   1.470 +
   1.471 +                // What's below is basically:
   1.472 +                //   foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation),
   1.473 +                //     get_setter_handle(type, linkerServices))
   1.474 +                // only with a bunch of method signature adjustments. Basically, retrieve method setter
   1.475 +                // MethodHandle; if it is non-null, invoke it, otherwise either return null, or delegate to next
   1.476 +                // component's invocation.
   1.477 +
   1.478 +                // Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll
   1.479 +                // abbreviate to R(O, N, V) going forward.
   1.480 +                // We want setters that conform to "R(O, V)"
   1.481 +                final MethodType setterType = type.dropParameterTypes(1, 2);
   1.482 +                // Bind property setter handle to the expected setter type and linker services. Type is
   1.483 +                // MethodHandle(Object, String, Object)
   1.484 +                final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0,
   1.485 +                        CallSiteDescriptorFactory.dropParameterTypes(callSiteDescriptor, 1, 2), linkerServices);
   1.486 +
   1.487 +                // Cast getter to MethodHandle(O, N, V)
   1.488 +                final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType(
   1.489 +                        MethodHandle.class));
   1.490 +
   1.491 +                // Handle to invoke the setter R(MethodHandle, O, V)
   1.492 +                final MethodHandle invokeHandle = MethodHandles.exactInvoker(setterType);
   1.493 +                // Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V)
   1.494 +                final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType(
   1.495 +                        1));
   1.496 +                final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
   1.497 +                        linkerServices, operations);
   1.498 +
   1.499 +                final MethodHandle fallbackFolded;
   1.500 +                if(nextComponent == null) {
   1.501 +                    // Object(MethodHandle)->R(MethodHandle, O, N, V); returns constant null
   1.502 +                    fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1,
   1.503 +                            type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class));
   1.504 +                } else {
   1.505 +                    // R(O, N, V)->R(MethodHandle, O, N, V); adapts the next component's invocation to drop the
   1.506 +                    // extra argument resulting from fold
   1.507 +                    fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
   1.508 +                            0, MethodHandle.class);
   1.509 +                }
   1.510 +
   1.511 +                // fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V))
   1.512 +                final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
   1.513 +                            IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
   1.514 +                if(nextComponent == null) {
   1.515 +                    return getClassGuardedInvocationComponent(compositeSetter, type);
   1.516 +                }
   1.517 +                return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
   1.518 +            }
   1.519 +            case 3: {
   1.520 +                // Must have two arguments: target object and property value
   1.521 +                assertParameterCount(callSiteDescriptor, 2);
   1.522 +                final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices,
   1.523 +                        callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), propertySetters);
   1.524 +                // If we have a property setter with this name, this composite operation will always stop here
   1.525 +                if(gi != null) {
   1.526 +                    return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS);
   1.527 +                }
   1.528 +                // If we don't have a property setter with this name, always fall back to the next operation in the
   1.529 +                // composite (if any)
   1.530 +                return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations);
   1.531 +            }
   1.532 +            default: {
   1.533 +                // More than two name components; don't know what to do with it.
   1.534 +                return null;
   1.535 +            }
   1.536 +        }
   1.537 +    }
   1.538 +
   1.539 +    private static final Lookup privateLookup = new Lookup(MethodHandles.lookup());
   1.540 +
   1.541 +    private static final MethodHandle IS_ANNOTATED_METHOD_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
   1.542 +            boolean.class, AnnotatedDynamicMethod.class));
   1.543 +    private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_METHOD = MethodHandles.dropArguments(
   1.544 +            MethodHandles.constant(Object.class, null), 0, AnnotatedDynamicMethod.class);
   1.545 +    private static final MethodHandle GET_ANNOTATED_METHOD = privateLookup.findVirtual(AnnotatedDynamicMethod.class,
   1.546 +            "getTarget", MethodType.methodType(MethodHandle.class, MethodHandles.Lookup.class));
   1.547 +    private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class));
   1.548 +
   1.549 +    private GuardedInvocationComponent getPropertyGetter(CallSiteDescriptor callSiteDescriptor,
   1.550 +            LinkerServices linkerServices, List<String> ops) throws Exception {
   1.551 +        final MethodType type = callSiteDescriptor.getMethodType();
   1.552 +        switch(callSiteDescriptor.getNameTokenCount()) {
   1.553 +            case 2: {
   1.554 +                // Must have exactly two arguments: receiver and name
   1.555 +                assertParameterCount(callSiteDescriptor, 2);
   1.556 +
   1.557 +                // What's below is basically:
   1.558 +                //   foldArguments(guardWithTest(isNotNull, invoke(get_handle), null|nextComponent.invocation), get_getter_handle)
   1.559 +                // only with a bunch of method signature adjustments. Basically, retrieve method getter
   1.560 +                // AnnotatedDynamicMethod; if it is non-null, invoke its "handle" field, otherwise either return null,
   1.561 +                // or delegate to next component's invocation.
   1.562 +
   1.563 +                final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType(
   1.564 +                        AnnotatedDynamicMethod.class));
   1.565 +                final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments(
   1.566 +                        GET_ANNOTATED_METHOD, 1, callSiteDescriptor.getLookup());
   1.567 +                final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0,
   1.568 +                        callSiteBoundMethodGetter);
   1.569 +                // Object(AnnotatedDynamicMethod, Object)->R(AnnotatedDynamicMethod, T0)
   1.570 +                final MethodHandle invokeHandleTyped = linkerServices.asType(callSiteBoundInvoker,
   1.571 +                        MethodType.methodType(type.returnType(), AnnotatedDynamicMethod.class, type.parameterType(0)));
   1.572 +                // Since it's in the target of a fold, drop the unnecessary second argument
   1.573 +                // R(AnnotatedDynamicMethod, T0)->R(AnnotatedDynamicMethod, T0, T1)
   1.574 +                final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2,
   1.575 +                        type.parameterType(1));
   1.576 +                final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
   1.577 +                        linkerServices, ops);
   1.578 +
   1.579 +                final MethodHandle fallbackFolded;
   1.580 +                if(nextComponent == null) {
   1.581 +                    // Object(AnnotatedDynamicMethod)->R(AnnotatedDynamicMethod, T0, T1); returns constant null
   1.582 +                    fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_METHOD, 1,
   1.583 +                            type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedDynamicMethod.class));
   1.584 +                } else {
   1.585 +                    // R(T0, T1)->R(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to drop the
   1.586 +                    // extra argument resulting from fold
   1.587 +                    fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
   1.588 +                            0, AnnotatedDynamicMethod.class);
   1.589 +                }
   1.590 +
   1.591 +                // fold(R(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1))
   1.592 +                final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
   1.593 +                            IS_ANNOTATED_METHOD_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
   1.594 +                if(nextComponent == null) {
   1.595 +                    return getClassGuardedInvocationComponent(compositeGetter, type);
   1.596 +                }
   1.597 +                return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
   1.598 +            }
   1.599 +            case 3: {
   1.600 +                // Must have exactly one argument: receiver
   1.601 +                assertParameterCount(callSiteDescriptor, 1);
   1.602 +                // Fixed name
   1.603 +                final AnnotatedDynamicMethod annGetter = propertyGetters.get(callSiteDescriptor.getNameToken(
   1.604 +                        CallSiteDescriptor.NAME_OPERAND));
   1.605 +                if(annGetter == null) {
   1.606 +                    // We have no such property, always delegate to the next component operation
   1.607 +                    return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops);
   1.608 +                }
   1.609 +                final MethodHandle getter = annGetter.getInvocation(callSiteDescriptor, linkerServices);
   1.610 +                // NOTE: since property getters (not field getters!) are no-arg, we don't have to worry about them being
   1.611 +                // overloaded in a subclass. Therefore, we can discover the most abstract superclass that has the
   1.612 +                // method, and use that as the guard with Guards.isInstance() for a more stably linked call site. If
   1.613 +                // we're linking against a field getter, don't make the assumption.
   1.614 +                // NOTE: No delegation to the next component operation if we have a property with this name, even if its
   1.615 +                // value is null.
   1.616 +                final ValidationType validationType = annGetter.validationType;
   1.617 +                // TODO: we aren't using the type that declares the most generic getter here!
   1.618 +                return new GuardedInvocationComponent(linkerServices.asType(getter, type), getGuard(validationType,
   1.619 +                        type), clazz, validationType);
   1.620 +            }
   1.621 +            default: {
   1.622 +                // Can't do anything with more than 3 name components
   1.623 +                return null;
   1.624 +            }
   1.625 +        }
   1.626 +    }
   1.627 +
   1.628 +    private MethodHandle getGuard(ValidationType validationType, MethodType methodType) {
   1.629 +        switch(validationType) {
   1.630 +            case EXACT_CLASS: {
   1.631 +                return getClassGuard(methodType);
   1.632 +            }
   1.633 +            case INSTANCE_OF: {
   1.634 +                return getAssignableGuard(methodType);
   1.635 +            }
   1.636 +            case IS_ARRAY: {
   1.637 +                return Guards.isArray(0, methodType);
   1.638 +            }
   1.639 +            case NONE: {
   1.640 +                return null;
   1.641 +            }
   1.642 +            default: {
   1.643 +                throw new AssertionError();
   1.644 +            }
   1.645 +        }
   1.646 +    }
   1.647 +
   1.648 +    private static final MethodHandle IS_DYNAMIC_METHOD_NOT_NULL = Guards.asType(Guards.isNotNull(),
   1.649 +            MethodType.methodType(boolean.class, DynamicMethod.class));
   1.650 +    private static final MethodHandle DYNAMIC_METHOD_IDENTITY = MethodHandles.identity(DynamicMethod.class);
   1.651 +
   1.652 +    private GuardedInvocationComponent getMethodGetter(CallSiteDescriptor callSiteDescriptor,
   1.653 +            LinkerServices linkerServices, List<String> ops) throws Exception {
   1.654 +        final MethodType type = callSiteDescriptor.getMethodType();
   1.655 +        switch(callSiteDescriptor.getNameTokenCount()) {
   1.656 +            case 2: {
   1.657 +                // Must have exactly two arguments: receiver and name
   1.658 +                assertParameterCount(callSiteDescriptor, 2);
   1.659 +                final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
   1.660 +                        linkerServices, ops);
   1.661 +                if(nextComponent == null) {
   1.662 +                    // No next component operation; just return a component for this operation.
   1.663 +                    return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type);
   1.664 +                }
   1.665 +
   1.666 +                // What's below is basically:
   1.667 +                // foldArguments(guardWithTest(isNotNull, identity, nextComponent.invocation), getter) only with a
   1.668 +                // bunch of method signature adjustments. Basically, execute method getter; if it returns a non-null
   1.669 +                // DynamicMethod, use identity to return it, otherwise delegate to nextComponent's invocation.
   1.670 +
   1.671 +                final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type.changeReturnType(
   1.672 +                        DynamicMethod.class));
   1.673 +                // Since it is part of the foldArgument() target, it will have extra args that we need to drop.
   1.674 +                final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments(
   1.675 +                        DYNAMIC_METHOD_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0,
   1.676 +                                DynamicMethod.class));
   1.677 +                final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation();
   1.678 +                // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly
   1.679 +                assert nextComponentInvocation.type().equals(type);
   1.680 +                // Since it is part of the foldArgument() target, we have to drop an extra arg it receives.
   1.681 +                final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0,
   1.682 +                        DynamicMethod.class);
   1.683 +                // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get)
   1.684 +                final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
   1.685 +                        IS_DYNAMIC_METHOD_NOT_NULL, returnMethodHandle, nextCombinedInvocation), typedGetter);
   1.686 +
   1.687 +                return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
   1.688 +            }
   1.689 +            case 3: {
   1.690 +                // Must have exactly one argument: receiver
   1.691 +                assertParameterCount(callSiteDescriptor, 1);
   1.692 +                final DynamicMethod method = getDynamicMethod(callSiteDescriptor.getNameToken(
   1.693 +                        CallSiteDescriptor.NAME_OPERAND));
   1.694 +                if(method == null) {
   1.695 +                    // We have no such method, always delegate to the next component
   1.696 +                    return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops);
   1.697 +                }
   1.698 +                // No delegation to the next component of the composite operation; if we have a method with that name,
   1.699 +                // we'll always return it at this point.
   1.700 +                return getClassGuardedInvocationComponent(linkerServices.asType(MethodHandles.dropArguments(
   1.701 +                        MethodHandles.constant(DynamicMethod.class, method), 0, type.parameterType(0)), type), type);
   1.702 +            }
   1.703 +            default: {
   1.704 +                // Can't do anything with more than 3 name components
   1.705 +                return null;
   1.706 +            }
   1.707 +        }
   1.708 +    }
   1.709 +
   1.710 +    private static void assertParameterCount(CallSiteDescriptor descriptor, int paramCount) {
   1.711 +        if(descriptor.getMethodType().parameterCount() != paramCount) {
   1.712 +            throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters.");
   1.713 +        }
   1.714 +    }
   1.715 +
   1.716 +    private static MethodHandle GET_PROPERTY_GETTER_HANDLE = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
   1.717 +            "getPropertyGetterHandle", Object.class, Object.class), 1, Object.class);
   1.718 +    private final MethodHandle getPropertyGetterHandle = GET_PROPERTY_GETTER_HANDLE.bindTo(this);
   1.719 +
   1.720 +    /**
   1.721 +     * @param id the property ID
   1.722 +     * @return the method handle for retrieving the property, or null if the property does not exist
   1.723 +     */
   1.724 +    @SuppressWarnings("unused")
   1.725 +    private Object getPropertyGetterHandle(Object id) {
   1.726 +        return propertyGetters.get(id);
   1.727 +    }
   1.728 +
   1.729 +    // Type is MethodHandle(BeanLinker, MethodType, LinkerServices, Object, String, Object), of which the two "Object"
   1.730 +    // args are dropped; this makes handles with first three args conform to "Object, String, Object" though, which is
   1.731 +    // a typical property setter with variable name signature (target, name, value).
   1.732 +    private static final MethodHandle GET_PROPERTY_SETTER_HANDLE = MethodHandles.dropArguments(MethodHandles.dropArguments(
   1.733 +            privateLookup.findOwnSpecial("getPropertySetterHandle", MethodHandle.class, CallSiteDescriptor.class,
   1.734 +                    LinkerServices.class, Object.class), 3, Object.class), 5, Object.class);
   1.735 +    // Type is MethodHandle(MethodType, LinkerServices, Object, String, Object)
   1.736 +    private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this);
   1.737 +
   1.738 +    @SuppressWarnings("unused")
   1.739 +    private MethodHandle getPropertySetterHandle(CallSiteDescriptor setterDescriptor, LinkerServices linkerServices,
   1.740 +            Object id) {
   1.741 +        return getDynamicMethodInvocation(setterDescriptor, linkerServices, String.valueOf(id), propertySetters);
   1.742 +    }
   1.743 +
   1.744 +    private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
   1.745 +            "getDynamicMethod", DynamicMethod.class, Object.class), 1, Object.class);
   1.746 +    private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this);
   1.747 +
   1.748 +    @SuppressWarnings("unused")
   1.749 +    private DynamicMethod getDynamicMethod(Object name) {
   1.750 +        return getDynamicMethod(String.valueOf(name), methods);
   1.751 +    }
   1.752 +
   1.753 +    /**
   1.754 +     * Returns a dynamic method of the specified name.
   1.755 +     *
   1.756 +     * @param name name of the method
   1.757 +     * @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the
   1.758 +     * method with the specified name does not exist.
   1.759 +     */
   1.760 +    DynamicMethod getDynamicMethod(String name) {
   1.761 +        return getDynamicMethod(name, methods);
   1.762 +    }
   1.763 +
   1.764 +    /**
   1.765 +     * Find the most generic superclass that declares this getter. Since getters have zero args (aside from the
   1.766 +     * receiver), they can't be overloaded, so we're free to link with an instanceof guard for the most generic one,
   1.767 +     * creating more stable call sites.
   1.768 +     * @param getter the getter
   1.769 +     * @return getter with same name, declared on the most generic superclass/interface of the declaring class
   1.770 +     */
   1.771 +    private static Method getMostGenericGetter(Method getter) {
   1.772 +        return getMostGenericGetter(getter.getName(), getter.getReturnType(), getter.getDeclaringClass());
   1.773 +    }
   1.774 +
   1.775 +    private static Method getMostGenericGetter(String name, Class<?> returnType, Class<?> declaringClass) {
   1.776 +        if(declaringClass == null) {
   1.777 +            return null;
   1.778 +        }
   1.779 +        // Prefer interfaces
   1.780 +        for(Class<?> itf: declaringClass.getInterfaces()) {
   1.781 +            final Method itfGetter = getMostGenericGetter(name, returnType, itf);
   1.782 +            if(itfGetter != null) {
   1.783 +                return itfGetter;
   1.784 +            }
   1.785 +        }
   1.786 +        final Method superGetter = getMostGenericGetter(name, returnType, declaringClass.getSuperclass());
   1.787 +        if(superGetter != null) {
   1.788 +            return superGetter;
   1.789 +        }
   1.790 +        if(!CheckRestrictedPackage.isRestrictedClass(declaringClass)) {
   1.791 +            try {
   1.792 +                return declaringClass.getMethod(name);
   1.793 +            } catch(NoSuchMethodException e) {
   1.794 +                // Intentionally ignored, meant to fall through
   1.795 +            }
   1.796 +        }
   1.797 +        return null;
   1.798 +    }
   1.799 +
   1.800 +    private static final class AnnotatedDynamicMethod {
   1.801 +        private final SingleDynamicMethod method;
   1.802 +        /*private*/ final ValidationType validationType;
   1.803 +
   1.804 +        AnnotatedDynamicMethod(SingleDynamicMethod method, ValidationType validationType) {
   1.805 +            this.method = method;
   1.806 +            this.validationType = validationType;
   1.807 +        }
   1.808 +
   1.809 +        MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
   1.810 +            return method.getInvocation(callSiteDescriptor, linkerServices);
   1.811 +        }
   1.812 +
   1.813 +        @SuppressWarnings("unused")
   1.814 +        MethodHandle getTarget(MethodHandles.Lookup lookup) {
   1.815 +            MethodHandle inv = method.getTarget(lookup);
   1.816 +            assert inv != null;
   1.817 +            return inv;
   1.818 +        }
   1.819 +    }
   1.820 +}

mercurial