1 /*
   2  * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import jdk.internal.ref.CleanerFactory;
  29 import jdk.internal.reflect.ConstantPool;
  30 import sun.invoke.util.Wrapper;
  31 
  32 import java.lang.constant.ClassDesc;
  33 import java.lang.constant.MethodTypeDesc;
  34 import java.lang.invoke.AbstractBootstrapCallInfo.TypeView;
  35 import java.lang.invoke.BootstrapMethodInvoker.VM_BSCI;
  36 import java.lang.invoke.MethodHandles.Lookup;
  37 import java.lang.reflect.Field;
  38 import java.util.Arrays;
  39 
  40 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  41 import static java.lang.invoke.MethodHandleStatics.TRACE_METHOD_LINKAGE;
  42 import static java.lang.invoke.MethodHandleStatics.TRACE_RESOLVE;
  43 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  44 
  45 /**
  46  * The JVM interface for the method handles package is all here.
  47  * This is an interface internal and private to an implementation of JSR 292.
  48  * <em>This class is not part of the JSR 292 standard.</em>
  49  * @author jrose
  50  */
  51 class MethodHandleNatives {
  52 
  53     private MethodHandleNatives() { } // static only
  54 
  55     /// MemberName support
  56 
  57     static native void init(MemberName self, Object ref);
  58     static native void expand(MemberName self);
  59     static native MemberName resolve(MemberName self, Class<?> caller,
  60             boolean speculativeResolve) throws LinkageError, ClassNotFoundException;
  61     static native int getMembers(Class<?> defc, String matchName, String matchSig,
  62             int matchFlags, Class<?> caller, int skip, MemberName[] results);
  63 
  64     /// Field layout queries parallel to jdk.internal.misc.Unsafe:
  65     static native long objectFieldOffset(MemberName self);  // e.g., returns vmindex
  66     static native long staticFieldOffset(MemberName self);  // e.g., returns vmindex
  67     static native Object staticFieldBase(MemberName self);  // e.g., returns clazz
  68     static native Object getMemberVMInfo(MemberName self);  // returns {vmindex,vmtarget}
  69 
  70     /// CallSite support
  71 
  72     /** Tell the JVM that we need to change the target of a CallSite. */
  73     static native void setCallSiteTargetNormal(CallSite site, MethodHandle target);
  74     static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target);
  75 
  76     /** Represents a context to track nmethod dependencies on CallSite instance target. */
  77     static class CallSiteContext implements Runnable {
  78         //@Injected JVM_nmethodBucket* vmdependencies;
  79 
  80         static CallSiteContext make(CallSite cs) {
  81             final CallSiteContext newContext = new CallSiteContext();
  82             // CallSite instance is tracked by a Cleanable which clears native
  83             // structures allocated for CallSite context. Though the CallSite can
  84             // become unreachable, its Context is retained by the Cleanable instance
  85             // (which is referenced from Cleaner instance which is referenced from
  86             // CleanerFactory class) until cleanup is performed.
  87             CleanerFactory.cleaner().register(cs, newContext);
  88             return newContext;
  89         }
  90 
  91         @Override
  92         public void run() {
  93             MethodHandleNatives.clearCallSiteContext(this);
  94         }
  95     }
  96 
  97     /** Invalidate all recorded nmethods. */
  98     private static native void clearCallSiteContext(CallSiteContext context);
  99 
 100     private static native void registerNatives();
 101     static {
 102         registerNatives();
 103     }
 104 
 105     /**
 106      * Compile-time constants go here. This collection exists not only for
 107      * reference from clients, but also for ensuring the VM and JDK agree on the
 108      * values of these constants (see {@link #verifyConstants()}).
 109      */
 110     static class Constants {
 111         Constants() { } // static only
 112 
 113         static final int
 114             MN_IS_METHOD           = 0x00010000, // method (not constructor)
 115             MN_IS_CONSTRUCTOR      = 0x00020000, // constructor
 116             MN_IS_FIELD            = 0x00040000, // field
 117             MN_IS_TYPE             = 0x00080000, // nested type
 118             MN_CALLER_SENSITIVE    = 0x00100000, // @CallerSensitive annotation detected
 119             MN_REFERENCE_KIND_SHIFT = 24, // refKind
 120             MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
 121             // The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:
 122             MN_SEARCH_SUPERCLASSES = 0x00100000,
 123             MN_SEARCH_INTERFACES   = 0x00200000;
 124 
 125         /**
 126          * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries.
 127          */
 128         static final byte
 129             REF_NONE                    = 0,  // null value
 130             REF_getField                = 1,
 131             REF_getStatic               = 2,
 132             REF_putField                = 3,
 133             REF_putStatic               = 4,
 134             REF_invokeVirtual           = 5,
 135             REF_invokeStatic            = 6,
 136             REF_invokeSpecial           = 7,
 137             REF_newInvokeSpecial        = 8,
 138             REF_invokeInterface         = 9,
 139             REF_LIMIT                  = 10;
 140 
 141         /**
 142          * Flag values which affect the copying of bootstrap static arguments.
 143          */
 144         static final byte BAR_IFPRESENT = 0, BAR_FORCE = 1, BAR_SYMREF = 2;
 145     }
 146 
 147     static boolean refKindIsValid(int refKind) {
 148         return (refKind > REF_NONE && refKind < REF_LIMIT);
 149     }
 150     static boolean refKindIsField(byte refKind) {
 151         assert(refKindIsValid(refKind));
 152         return (refKind <= REF_putStatic);
 153     }
 154     static boolean refKindIsGetter(byte refKind) {
 155         assert(refKindIsValid(refKind));
 156         return (refKind <= REF_getStatic);
 157     }
 158     static boolean refKindIsSetter(byte refKind) {
 159         return refKindIsField(refKind) && !refKindIsGetter(refKind);
 160     }
 161     static boolean refKindIsMethod(byte refKind) {
 162         return !refKindIsField(refKind) && (refKind != REF_newInvokeSpecial);
 163     }
 164     static boolean refKindIsConstructor(byte refKind) {
 165         return (refKind == REF_newInvokeSpecial);
 166     }
 167     static boolean refKindHasReceiver(byte refKind) {
 168         assert(refKindIsValid(refKind));
 169         return (refKind & 1) != 0;
 170     }
 171     static boolean refKindIsStatic(byte refKind) {
 172         return !refKindHasReceiver(refKind) && (refKind != REF_newInvokeSpecial);
 173     }
 174     static boolean refKindDoesDispatch(byte refKind) {
 175         assert(refKindIsValid(refKind));
 176         return (refKind == REF_invokeVirtual ||
 177                 refKind == REF_invokeInterface);
 178     }
 179     static {
 180         final int HR_MASK = ((1 << REF_getField) |
 181                              (1 << REF_putField) |
 182                              (1 << REF_invokeVirtual) |
 183                              (1 << REF_invokeSpecial) |
 184                              (1 << REF_invokeInterface)
 185                             );
 186         for (byte refKind = REF_NONE+1; refKind < REF_LIMIT; refKind++) {
 187             assert(refKindHasReceiver(refKind) == (((1<<refKind) & HR_MASK) != 0)) : refKind;
 188         }
 189     }
 190     static String refKindName(byte refKind) {
 191         assert(refKindIsValid(refKind));
 192         switch (refKind) {
 193         case REF_getField:          return "getField";
 194         case REF_getStatic:         return "getStatic";
 195         case REF_putField:          return "putField";
 196         case REF_putStatic:         return "putStatic";
 197         case REF_invokeVirtual:     return "invokeVirtual";
 198         case REF_invokeStatic:      return "invokeStatic";
 199         case REF_invokeSpecial:     return "invokeSpecial";
 200         case REF_newInvokeSpecial:  return "newInvokeSpecial";
 201         case REF_invokeInterface:   return "invokeInterface";
 202         default:                    return "REF_???";
 203         }
 204     }
 205 
 206     private static native int getNamedCon(int which, Object[] name);
 207     static boolean verifyConstants() {
 208         // This code requires ADVERTISE_CON_VALUES to be turned on
 209         // in methodHandles.cpp, which is usually only true in debug builds.
 210         // If that is not the case, then getNamedCon returns nothing and
 211         // the loop body never runs.
 212         Object[] box = { null };
 213         for (int i = 0; ; i++) {
 214             box[0] = null;
 215             int vmval = getNamedCon(i, box);
 216             if (box[0] == null)  break;
 217             String name = (String) box[0];
 218             try {
 219                 Field con = Constants.class.getDeclaredField(name);
 220                 int jval = con.getInt(null);
 221                 if (TRACE_RESOLVE) {
 222                     System.out.println("[CON_RESOLVE] " + name + " = " + vmval);
 223                 }
 224                 if (jval == vmval)  continue;
 225                 String err = (name+": JVM has "+vmval+" while Java has "+jval);
 226                 throw new InternalError(err);
 227             } catch (NoSuchFieldException | IllegalAccessException ex) {
 228                 String err = (name+": JVM has "+vmval+" which Java does not define");
 229                 // ignore exotic ops the JVM cares about; we just wont issue them
 230                 //System.err.println("warning: "+err);
 231                 continue;
 232             }
 233         }
 234         return true;
 235     }
 236     static {
 237         if (TRACE_RESOLVE) {
 238             boolean ok = verifyConstants();
 239             assert(ok);
 240         } else {
 241             assert(verifyConstants());
 242         }
 243     }
 244 
 245     // Up-calls from the JVM.
 246     // These must NOT be public.
 247 
 248     /**
 249      * All bootstrap method invocations funnel through this single method.
 250      * A large subset of the values of the JVM's BootstrapInfo structure is
 251      * made available here, basically everything that can be easily computed
 252      * without a detectable side effect or exception.  The callee is
 253      * invited to call back the JVM for more information.
 254      */
 255     static Object bootstrapMethodHelper(ConstantPool pool,
 256                                         int bssIndex,
 257                                         int indyIndex,
 258                                         int argc,
 259                                         MethodHandle bsm,
 260                                         String name,
 261                                         Object type,  // Class or MethodType or String
 262                                         int[] argIndexes,
 263                                         Object[] argValues,
 264                                         Object request,
 265                                         Object[] appendixResult) {
 266         assert((appendixResult != null) == (indyIndex != 0));
 267         assert(request == (indyIndex == 0 ? null : CallSite.class));
 268         // Special case:  If the bsm does not begin with Lookup, *and*
 269         // it is a CallSite request (i.e., legacy from Java 7), then
 270         // forcibly convert the leading type to Lookup.
 271         if (request == CallSite.class && BootstrapMethodInvoker.isExpressionBSM(bsm)) {
 272             bsm = BootstrapMethodInvoker.forceLookupParameter(bsm);
 273             assert(!BootstrapMethodInvoker.isExpressionBSM(bsm));  // properly wrapped
 274         }
 275         // Make a full-power lookup into the CP (a privileged operation).
 276         Lookup lookup = IMPL_LOOKUP.in(pool.getHolder());
 277         // Process the type:  { field, method } x { resolved, string }
 278         TypeView<Class<?>>   ftype = null;
 279         TypeView<MethodType> mtype = null;
 280         if (type instanceof MethodType) {
 281             mtype = new TypeView<>((MethodType)type);
 282         } else if (type instanceof Class<?>) {
 283             ftype = new TypeView<>((Class<?>)type);
 284         } else {
 285             // JVM was not able to resolve the type.  Keep the ball rolling.
 286             String desc = (String) type;
 287             if (desc.startsWith("("))
 288                 mtype = new TypeView<>(MethodTypeDesc.ofDescriptor(desc), lookup);
 289             else
 290                 ftype = new TypeView<>(ClassDesc.ofDescriptor(desc), lookup);
 291         }
 292         // If VM is pushing up argument values, use them.  Otherwise make a fresh buffer.
 293         if (argValues == null) {
 294             argValues = new Object[argc];
 295         } else {
 296             assert(argValues.length == argc);
 297             // The JVM resolves CONSTANT_Integer CP items without calling Integer.valueOf.
 298             BootstrapMethodInvoker.maybeReBoxElements(argValues);
 299         }
 300         // Make a BSCI wrapper for all of this state.
 301         VM_BSCI<?> bsci;
 302         // (The following if/then/else is required to make the generic types match up.)
 303         if (ftype != null)
 304             bsci = new VM_BSCI<>(pool, bssIndex, indyIndex, bsm, name, ftype, argValues);
 305         else
 306             bsci = new VM_BSCI<>(pool, bssIndex, indyIndex, bsm, name, mtype, argValues);
 307         // If VM is passing up argument indexes, accept that also.
 308         if (argIndexes != null)  bsci.setArgIndexes(argIndexes);
 309         // Finish the job by invoking the fresh BSCI under the Lookup:
 310         if (!TRACE_METHOD_LINKAGE) {
 311             Object res = BootstrapMethodInvoker.invoke(lookup, bsci);
 312             if (appendixResult == null) {
 313                 return res;
 314             }
 315             return encodeBindingViaAppendix(bsci, res, appendixResult);
 316         }
 317 
 318         // Tracing logic follows:
 319         String linkWhat = "[TRACE_METHOD_LINKAGE] link"
 320                         + ((request == null) ? "DynamicConstant"
 321                            : request instanceof Class ? ((Class<?>)request).getSimpleName()
 322                            : request);
 323         System.out.println(linkWhat+" "+bsci.toString());
 324         try {
 325             Object res = BootstrapMethodInvoker.invoke(lookup, bsci);
 326             if (appendixResult == null) {
 327                 System.out.println(linkWhat+" => "+res);                return res;
 328             }
 329             MemberName mem = encodeBindingViaAppendix(bsci, res, appendixResult);
 330             System.out.println(linkWhat+" => "+res+" => "+mem+" + "+appendixResult[0]);
 331             return mem;
 332         } catch (Throwable ex) {
 333             ex.printStackTrace(); // print now in case exception is swallowed
 334             System.out.println(linkWhat+" => throw "+ex);
 335             throw ex;
 336         }
 337     }
 338 
 339     // Follow-up step to bootstrapMethodHelper, when an appendix was provided.
 340     // The basic result was a specific behavior; factor it (for the VM's sake)
 341     // into a generic chunk of argument shuffling plus a datum.
 342     static MemberName encodeBindingViaAppendix(BootstrapCallInfo<?> bsci, Object binding, Object[] appendixResult) {
 343         MethodType type = (MethodType) bsci.invocationType();
 344         MemberName result;
 345         MethodType resultType;
 346         Object appendix;
 347         if (binding instanceof ConstantCallSite) {
 348             ConstantCallSite ccs = (ConstantCallSite) binding;
 349             result = Invokers.linkToTargetMethod(type);
 350             appendix = ccs.getTarget();
 351             resultType = ((MethodHandle) appendix).type();
 352         } else if (binding instanceof CallSite) {
 353             result = Invokers.linkToCallSiteMethod(type);
 354             appendix = binding;
 355             resultType = ((CallSite) appendix).type();
 356         } else if (binding instanceof MethodHandle) {
 357             result = Invokers.linkToTargetMethod(type);
 358             appendix = binding;
 359             resultType = ((MethodHandle) appendix).type();
 360         } else {
 361             throw new InternalError("should not get here: "+binding+":"+binding.getClass().getName());
 362         }
 363         // Double-check the function type also.
 364         if (!resultType.equals(type)) {
 365             throw new InternalError("should not get here: "+binding+type);
 366         }
 367         // After type checking, give the JVM the two bits it needs
 368         // to implement the call site:  A behavior method, and a cookie.
 369         appendixResult[0] = appendix;
 370         return result;
 371     }
 372 
 373     /**
 374      * The JVM wants a pointer to a MethodType.  Oblige it by finding or creating one.
 375      */
 376     static MethodType findMethodHandleType(Class<?> rtype, Class<?>[] ptypes) {
 377         return MethodType.makeImpl(rtype, ptypes, true);
 378     }
 379 
 380     /**
 381      * The JVM wants to link a call site that requires a dynamic type check.
 382      * Name is a type-checking invoker, invokeExact or invoke.
 383      * Return a JVM method (MemberName) to handle the invoking.
 384      * The method assumes the following arguments on the stack:
 385      * 0: the method handle being invoked
 386      * 1-N: the arguments to the method handle invocation
 387      * N+1: an optional, implicitly added argument (typically the given MethodType)
 388      * <p>
 389      * The nominal method at such a call site is an instance of
 390      * a signature-polymorphic method (see @PolymorphicSignature).
 391      * Such method instances are user-visible entities which are
 392      * "split" from the generic placeholder method in {@code MethodHandle}.
 393      * (Note that the placeholder method is not identical with any of
 394      * its instances.  If invoked reflectively, is guaranteed to throw an
 395      * {@code UnsupportedOperationException}.)
 396      * If the signature-polymorphic method instance is ever reified,
 397      * it appears as a "copy" of the original placeholder
 398      * (a native final member of {@code MethodHandle}) except
 399      * that its type descriptor has shape required by the instance,
 400      * and the method instance is <em>not</em> varargs.
 401      * The method instance is also marked synthetic, since the
 402      * method (by definition) does not appear in Java source code.
 403      * <p>
 404      * The JVM is allowed to reify this method as instance metadata.
 405      * For example, {@code invokeBasic} is always reified.
 406      * But the JVM may instead call {@code linkMethod}.
 407      * If the result is an * ordered pair of a {@code (method, appendix)},
 408      * the method gets all the arguments (0..N inclusive)
 409      * plus the appendix (N+1), and uses the appendix to complete the call.
 410      * In this way, one reusable method (called a "linker method")
 411      * can perform the function of any number of polymorphic instance
 412      * methods.
 413      * <p>
 414      * Linker methods are allowed to be weakly typed, with any or
 415      * all references rewritten to {@code Object} and any primitives
 416      * (except {@code long}/{@code float}/{@code double})
 417      * rewritten to {@code int}.
 418      * A linker method is trusted to return a strongly typed result,
 419      * according to the specific method type descriptor of the
 420      * signature-polymorphic instance it is emulating.
 421      * This can involve (as necessary) a dynamic check using
 422      * data extracted from the appendix argument.
 423      * <p>
 424      * The JVM does not inspect the appendix, other than to pass
 425      * it verbatim to the linker method at every call.
 426      * This means that the JDK runtime has wide latitude
 427      * for choosing the shape of each linker method and its
 428      * corresponding appendix.
 429      * Linker methods should be generated from {@code LambdaForm}s
 430      * so that they do not become visible on stack traces.
 431      * <p>
 432      * The {@code linkMethod} call is free to omit the appendix
 433      * (returning null) and instead emulate the required function
 434      * completely in the linker method.
 435      * As a corner case, if N==255, no appendix is possible.
 436      * In this case, the method returned must be custom-generated to
 437      * to perform any needed type checking.
 438      * <p>
 439      * If the JVM does not reify a method at a call site, but instead
 440      * calls {@code linkMethod}, the corresponding call represented
 441      * in the bytecodes may mention a valid method which is not
 442      * representable with a {@code MemberName}.
 443      * Therefore, use cases for {@code linkMethod} tend to correspond to
 444      * special cases in reflective code such as {@code findVirtual}
 445      * or {@code revealDirect}.
 446      */
 447     static MemberName linkMethod(Class<?> callerClass, int refKind,
 448                                  Class<?> defc, String name, Object type,
 449                                  Object[] appendixResult) {
 450         if (!TRACE_METHOD_LINKAGE)
 451             return linkMethodImpl(callerClass, refKind, defc, name, type, appendixResult);
 452         return linkMethodTracing(callerClass, refKind, defc, name, type, appendixResult);
 453     }
 454     static MemberName linkMethodImpl(Class<?> callerClass, int refKind,
 455                                      Class<?> defc, String name, Object type,
 456                                      Object[] appendixResult) {
 457         try {
 458             if (refKind == REF_invokeVirtual) {
 459                 if (defc == MethodHandle.class) {
 460                     return Invokers.methodHandleInvokeLinkerMethod(
 461                             name, fixMethodType(callerClass, type), appendixResult);
 462                 } else if (defc == VarHandle.class) {
 463                     return varHandleOperationLinkerMethod(
 464                             name, fixMethodType(callerClass, type), appendixResult);
 465                 }
 466             }
 467         } catch (Error e) {
 468             // Pass through an Error, including say StackOverflowError or
 469             // OutOfMemoryError
 470             throw e;
 471         } catch (Throwable ex) {
 472             // Wrap anything else in LinkageError
 473             throw new LinkageError(ex.getMessage(), ex);
 474         }
 475         throw new LinkageError("no such method "+defc.getName()+"."+name+type);
 476     }
 477 
 478     private static MethodType fixMethodType(Class<?> callerClass, Object type) {
 479         if (type instanceof MethodType)
 480             return (MethodType) type;
 481         else
 482             return MethodType.fromDescriptor((String)type, callerClass.getClassLoader());
 483     }
 484     // Tracing logic:
 485     static MemberName linkMethodTracing(Class<?> callerClass, int refKind,
 486                                         Class<?> defc, String name, Object type,
 487                                         Object[] appendixResult) {
 488         System.out.println("linkMethod "+defc.getName()+"."+
 489                            name+type+"/"+Integer.toHexString(refKind));
 490         try {
 491             MemberName res = linkMethodImpl(callerClass, refKind, defc, name, type, appendixResult);
 492             System.out.println("linkMethod => "+res+" + "+appendixResult[0]);
 493             return res;
 494         } catch (Throwable ex) {
 495             System.out.println("linkMethod => throw "+ex);
 496             throw ex;
 497         }
 498     }
 499 
 500     /**
 501      * Obtain the method to link to the VarHandle operation.
 502      * This method is located here and not in Invokers to avoid
 503      * intializing that and other classes early on in VM bootup.
 504      */
 505     private static MemberName varHandleOperationLinkerMethod(String name,
 506                                                              MethodType mtype,
 507                                                              Object[] appendixResult) {
 508         // Get the signature method type
 509         final MethodType sigType = mtype.basicType();
 510 
 511         // Get the access kind from the method name
 512         VarHandle.AccessMode ak;
 513         try {
 514             ak = VarHandle.AccessMode.valueFromMethodName(name);
 515         } catch (IllegalArgumentException e) {
 516             throw MethodHandleStatics.newInternalError(e);
 517         }
 518 
 519         // Create the appendix descriptor constant
 520         VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
 521         appendixResult[0] = ad;
 522 
 523         if (MethodHandleStatics.VAR_HANDLE_GUARDS) {
 524             // If not polymorphic in the return type, such as the compareAndSet
 525             // methods that return boolean
 526             Class<?> guardReturnType = sigType.returnType();
 527             if (ak.at.isMonomorphicInReturnType) {
 528                 if (ak.at.returnType != mtype.returnType()) {
 529                     // The caller contains a different return type than that
 530                     // defined by the method
 531                     throw newNoSuchMethodErrorOnVarHandle(name, mtype);
 532                 }
 533                 // Adjust the return type of the signature method type
 534                 guardReturnType = ak.at.returnType;
 535             }
 536 
 537             // Get the guard method type for linking
 538             final Class<?>[] guardParams = new Class<?>[sigType.parameterCount() + 2];
 539             // VarHandle at start
 540             guardParams[0] = VarHandle.class;
 541             for (int i = 0; i < sigType.parameterCount(); i++) {
 542                 guardParams[i + 1] = sigType.parameterType(i);
 543             }
 544             // Access descriptor at end
 545             guardParams[guardParams.length - 1] = VarHandle.AccessDescriptor.class;
 546             MethodType guardType = MethodType.makeImpl(guardReturnType, guardParams, true);
 547 
 548             MemberName linker = new MemberName(
 549                     VarHandleGuards.class, getVarHandleGuardMethodName(guardType),
 550                     guardType, REF_invokeStatic);
 551 
 552             linker = MemberName.getFactory().resolveOrNull(REF_invokeStatic, linker,
 553                                                            VarHandleGuards.class);
 554             if (linker != null) {
 555                 return linker;
 556             }
 557             // Fall back to lambda form linkage if guard method is not available
 558             // TODO Optionally log fallback ?
 559         }
 560         return Invokers.varHandleInvokeLinkerMethod(ak, mtype);
 561     }
 562     static String getVarHandleGuardMethodName(MethodType guardType) {
 563         String prefix = "guard_";
 564         StringBuilder sb = new StringBuilder(prefix.length() + guardType.parameterCount());
 565 
 566         sb.append(prefix);
 567         for (int i = 1; i < guardType.parameterCount() - 1; i++) {
 568             Class<?> pt = guardType.parameterType(i);
 569             sb.append(getCharType(pt));
 570         }
 571         sb.append('_').append(getCharType(guardType.returnType()));
 572         return sb.toString();
 573     }
 574     static char getCharType(Class<?> pt) {
 575         return Wrapper.forBasicType(pt).basicTypeChar();
 576     }
 577     static NoSuchMethodError newNoSuchMethodErrorOnVarHandle(String name, MethodType mtype) {
 578         return new NoSuchMethodError("VarHandle." + name + mtype);
 579     }
 580 
 581     /**
 582      * The JVM is resolving a CONSTANT_MethodHandle CP entry.  And it wants our help.
 583      * It will make an up-call to this method.  (Do not change the name or signature.)
 584      * The type argument is a Class for field requests and a MethodType for non-fields.
 585      * <p>
 586      * Recent versions of the JVM may also pass a resolved MemberName for the type.
 587      * In that case, the name is ignored and may be null.
 588      */
 589     static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
 590                                                  Class<?> defc, String name, Object type) {
 591         try {
 592             Lookup lookup = IMPL_LOOKUP.in(callerClass);
 593             assert(refKindIsValid(refKind));
 594             return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type);
 595         } catch (ReflectiveOperationException ex) {
 596             throw mapLookupExceptionToError(ex);
 597         }
 598     }
 599 
 600     /**
 601      * Map a reflective exception to a linkage error.
 602      */
 603     static LinkageError mapLookupExceptionToError(ReflectiveOperationException ex) {
 604         LinkageError err;
 605         if (ex instanceof IllegalAccessException) {
 606             Throwable cause = ex.getCause();
 607             if (cause instanceof AbstractMethodError) {
 608                 return (AbstractMethodError) cause;
 609             } else {
 610                 err = new IllegalAccessError(ex.getMessage());
 611             }
 612         } else if (ex instanceof NoSuchMethodException) {
 613             err = new NoSuchMethodError(ex.getMessage());
 614         } else if (ex instanceof NoSuchFieldException) {
 615             err = new NoSuchFieldError(ex.getMessage());
 616         } else {
 617             err = new IncompatibleClassChangeError();
 618         }
 619         return initCauseFrom(err, ex);
 620     }
 621 
 622     /**
 623      * Use best possible cause for err.initCause(), substituting the
 624      * cause for err itself if the cause has the same (or better) type.
 625      */
 626     static <E extends Error> E initCauseFrom(E err, Exception ex) {
 627         Throwable th = ex.getCause();
 628         @SuppressWarnings("unchecked")
 629         final Class<E> Eclass = (Class<E>) err.getClass();
 630         if (Eclass.isInstance(th))
 631            return Eclass.cast(th);
 632         err.initCause(th == null ? ex : th);
 633         return err;
 634     }
 635 
 636     /**
 637      * Is this method a caller-sensitive method?
 638      * I.e., does it call Reflection.getCallerClass or a similar method
 639      * to ask about the identity of its caller?
 640      */
 641     static boolean isCallerSensitive(MemberName mem) {
 642         if (!mem.isInvocable())  return false;  // fields are not caller sensitive
 643 
 644         return mem.isCallerSensitive() || canBeCalledVirtual(mem);
 645     }
 646 
 647     static boolean canBeCalledVirtual(MemberName mem) {
 648         assert(mem.isInvocable());
 649         switch (mem.getName()) {
 650         case "getContextClassLoader":
 651             return canBeCalledVirtual(mem, java.lang.Thread.class);
 652         }
 653         return false;
 654     }
 655 
 656     static boolean canBeCalledVirtual(MemberName symbolicRef, Class<?> definingClass) {
 657         Class<?> symbolicRefClass = symbolicRef.getDeclaringClass();
 658         if (symbolicRefClass == definingClass)  return true;
 659         if (symbolicRef.isStatic() || symbolicRef.isPrivate())  return false;
 660         return (definingClass.isAssignableFrom(symbolicRefClass) ||  // Msym overrides Mdef
 661                 symbolicRefClass.isInterface());                     // Mdef implements Msym
 662     }
 663 }