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