src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
changeset 48826 c4d9d1b08e2e
parent 47216 71c04702a3d5
child 48827 8772acd913e5
equal deleted inserted replaced
48825:ef8a98bc71f8 48826:c4d9d1b08e2e
    63 
    63 
    64     /** Tell the JVM that we need to change the target of a CallSite. */
    64     /** Tell the JVM that we need to change the target of a CallSite. */
    65     static native void setCallSiteTargetNormal(CallSite site, MethodHandle target);
    65     static native void setCallSiteTargetNormal(CallSite site, MethodHandle target);
    66     static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target);
    66     static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target);
    67 
    67 
       
    68     static native void copyOutBootstrapArguments(Class<?> caller, int[] indexInfo,
       
    69                                                  int start, int end,
       
    70                                                  Object[] buf, int pos,
       
    71                                                  boolean resolve,
       
    72                                                  Object ifNotAvailable);
       
    73 
    68     /** Represents a context to track nmethod dependencies on CallSite instance target. */
    74     /** Represents a context to track nmethod dependencies on CallSite instance target. */
    69     static class CallSiteContext implements Runnable {
    75     static class CallSiteContext implements Runnable {
    70         //@Injected JVM_nmethodBucket* vmdependencies;
    76         //@Injected JVM_nmethodBucket* vmdependencies;
    71 
    77 
    72         static CallSiteContext make(CallSite cs) {
    78         static CallSiteContext make(CallSite cs) {
   226 
   232 
   227     /**
   233     /**
   228      * The JVM is linking an invokedynamic instruction.  Create a reified call site for it.
   234      * The JVM is linking an invokedynamic instruction.  Create a reified call site for it.
   229      */
   235      */
   230     static MemberName linkCallSite(Object callerObj,
   236     static MemberName linkCallSite(Object callerObj,
       
   237                                    int indexInCP,
   231                                    Object bootstrapMethodObj,
   238                                    Object bootstrapMethodObj,
   232                                    Object nameObj, Object typeObj,
   239                                    Object nameObj, Object typeObj,
   233                                    Object staticArguments,
   240                                    Object staticArguments,
   234                                    Object[] appendixResult) {
   241                                    Object[] appendixResult) {
   235         MethodHandle bootstrapMethod = (MethodHandle)bootstrapMethodObj;
   242         MethodHandle bootstrapMethod = (MethodHandle)bootstrapMethodObj;
   266                                           String name, MethodType type,
   273                                           String name, MethodType type,
   267                                           Object staticArguments,
   274                                           Object staticArguments,
   268                                           Object[] appendixResult) {
   275                                           Object[] appendixResult) {
   269         Object bsmReference = bootstrapMethod.internalMemberName();
   276         Object bsmReference = bootstrapMethod.internalMemberName();
   270         if (bsmReference == null)  bsmReference = bootstrapMethod;
   277         if (bsmReference == null)  bsmReference = bootstrapMethod;
   271         Object staticArglist = (staticArguments instanceof Object[] ?
   278         String staticArglist = staticArglistForTrace(staticArguments);
   272                                 java.util.Arrays.asList((Object[]) staticArguments) :
       
   273                                 staticArguments);
       
   274         System.out.println("linkCallSite "+caller.getName()+" "+
   279         System.out.println("linkCallSite "+caller.getName()+" "+
   275                            bsmReference+" "+
   280                            bsmReference+" "+
   276                            name+type+"/"+staticArglist);
   281                            name+type+"/"+staticArglist);
   277         try {
   282         try {
   278             MemberName res = linkCallSiteImpl(caller, bootstrapMethod, name, type,
   283             MemberName res = linkCallSiteImpl(caller, bootstrapMethod, name, type,
   279                                               staticArguments, appendixResult);
   284                                               staticArguments, appendixResult);
   280             System.out.println("linkCallSite => "+res+" + "+appendixResult[0]);
   285             System.out.println("linkCallSite => "+res+" + "+appendixResult[0]);
   281             return res;
   286             return res;
   282         } catch (Throwable ex) {
   287         } catch (Throwable ex) {
       
   288             ex.printStackTrace(); // print now in case exception is swallowed
   283             System.out.println("linkCallSite => throw "+ex);
   289             System.out.println("linkCallSite => throw "+ex);
   284             throw ex;
   290             throw ex;
   285         }
   291         }
       
   292     }
       
   293 
       
   294     // this implements the upcall from the JVM, MethodHandleNatives.linkDynamicConstant:
       
   295     static Object linkDynamicConstant(Object callerObj,
       
   296                                       int indexInCP,
       
   297                                       Object bootstrapMethodObj,
       
   298                                       Object nameObj, Object typeObj,
       
   299                                       Object staticArguments) {
       
   300         MethodHandle bootstrapMethod = (MethodHandle)bootstrapMethodObj;
       
   301         Class<?> caller = (Class<?>)callerObj;
       
   302         String name = nameObj.toString().intern();
       
   303         Class<?> type = (Class<?>)typeObj;
       
   304         if (!TRACE_METHOD_LINKAGE)
       
   305             return linkDynamicConstantImpl(caller, bootstrapMethod, name, type, staticArguments);
       
   306         return linkDynamicConstantTracing(caller, bootstrapMethod, name, type, staticArguments);
       
   307     }
       
   308 
       
   309     static Object linkDynamicConstantImpl(Class<?> caller,
       
   310                                           MethodHandle bootstrapMethod,
       
   311                                           String name, Class<?> type,
       
   312                                           Object staticArguments) {
       
   313         return DynamicConstant.makeConstant(bootstrapMethod, name, type, staticArguments, caller);
       
   314     }
       
   315 
       
   316     private static String staticArglistForTrace(Object staticArguments) {
       
   317         if (staticArguments instanceof Object[])
       
   318             return "BSA="+java.util.Arrays.asList((Object[]) staticArguments);
       
   319         if (staticArguments instanceof int[])
       
   320             return "BSA@"+java.util.Arrays.toString((int[]) staticArguments);
       
   321         if (staticArguments == null)
       
   322             return "BSA0=null";
       
   323         return "BSA1="+staticArguments;
       
   324     }
       
   325 
       
   326     // Tracing logic:
       
   327     static Object linkDynamicConstantTracing(Class<?> caller,
       
   328                                              MethodHandle bootstrapMethod,
       
   329                                              String name, Class<?> type,
       
   330                                              Object staticArguments) {
       
   331         Object bsmReference = bootstrapMethod.internalMemberName();
       
   332         if (bsmReference == null)  bsmReference = bootstrapMethod;
       
   333         String staticArglist = staticArglistForTrace(staticArguments);
       
   334         System.out.println("linkDynamicConstant "+caller.getName()+" "+
       
   335                            bsmReference+" "+
       
   336                            name+type+"/"+staticArglist);
       
   337         try {
       
   338             Object res = linkDynamicConstantImpl(caller, bootstrapMethod, name, type, staticArguments);
       
   339             System.out.println("linkDynamicConstantImpl => "+res);
       
   340             return res;
       
   341         } catch (Throwable ex) {
       
   342             ex.printStackTrace(); // print now in case exception is swallowed
       
   343             System.out.println("linkDynamicConstant => throw "+ex);
       
   344             throw ex;
       
   345         }
       
   346     }
       
   347 
       
   348     /** The JVM is requesting pull-mode bootstrap when it provides
       
   349      *  a tuple of the form int[]{ argc, vmindex }.
       
   350      *  The BSM is expected to call back to the JVM using the caller
       
   351      *  class and vmindex to resolve the static arguments.
       
   352      */
       
   353     static boolean staticArgumentsPulled(Object staticArguments) {
       
   354         return staticArguments instanceof int[];
       
   355     }
       
   356 
       
   357     /** A BSM runs in pull-mode if and only if its sole arguments
       
   358      * are (Lookup, BootstrapCallInfo), or can be converted pairwise
       
   359      * to those types, and it is not of variable arity.
       
   360      * Excluding error cases, we can just test that the arity is a constant 2.
       
   361      *
       
   362      * NOTE: This method currently returns false, since pulling is not currently
       
   363      * exposed to a BSM. When pull mode is supported the method block will be
       
   364      * replaced with currently commented out code.
       
   365      */
       
   366     static boolean isPullModeBSM(MethodHandle bsm) {
       
   367         return false;
       
   368 //        return bsm.type().parameterCount() == 2 && !bsm.isVarargsCollector();
   286     }
   369     }
   287 
   370 
   288     /**
   371     /**
   289      * The JVM wants a pointer to a MethodType.  Oblige it by finding or creating one.
   372      * The JVM wants a pointer to a MethodType.  Oblige it by finding or creating one.
   290      */
   373      */
   504                                                  Class<?> defc, String name, Object type) {
   587                                                  Class<?> defc, String name, Object type) {
   505         try {
   588         try {
   506             Lookup lookup = IMPL_LOOKUP.in(callerClass);
   589             Lookup lookup = IMPL_LOOKUP.in(callerClass);
   507             assert(refKindIsValid(refKind));
   590             assert(refKindIsValid(refKind));
   508             return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type);
   591             return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type);
   509         } catch (IllegalAccessException ex) {
   592         } catch (ReflectiveOperationException ex) {
       
   593             throw mapLookupExceptionToError(ex);
       
   594         }
       
   595     }
       
   596 
       
   597     /**
       
   598      * Map a reflective exception to a linkage error.
       
   599      */
       
   600     static LinkageError mapLookupExceptionToError(ReflectiveOperationException ex) {
       
   601         LinkageError err;
       
   602         if (ex instanceof IllegalAccessException) {
   510             Throwable cause = ex.getCause();
   603             Throwable cause = ex.getCause();
   511             if (cause instanceof AbstractMethodError) {
   604             if (cause instanceof AbstractMethodError) {
   512                 throw (AbstractMethodError) cause;
   605                 return (AbstractMethodError) cause;
   513             } else {
   606             } else {
   514                 Error err = new IllegalAccessError(ex.getMessage());
   607                 err = new IllegalAccessError(ex.getMessage());
   515                 throw initCauseFrom(err, ex);
       
   516             }
   608             }
   517         } catch (NoSuchMethodException ex) {
   609         } else if (ex instanceof NoSuchMethodException) {
   518             Error err = new NoSuchMethodError(ex.getMessage());
   610             err = new NoSuchMethodError(ex.getMessage());
   519             throw initCauseFrom(err, ex);
   611         } else if (ex instanceof NoSuchFieldException) {
   520         } catch (NoSuchFieldException ex) {
   612             err = new NoSuchFieldError(ex.getMessage());
   521             Error err = new NoSuchFieldError(ex.getMessage());
   613         } else {
   522             throw initCauseFrom(err, ex);
   614             err = new IncompatibleClassChangeError();
   523         } catch (ReflectiveOperationException ex) {
   615         }
   524             Error err = new IncompatibleClassChangeError();
   616         return initCauseFrom(err, ex);
   525             throw initCauseFrom(err, ex);
       
   526         }
       
   527     }
   617     }
   528 
   618 
   529     /**
   619     /**
   530      * Use best possible cause for err.initCause(), substituting the
   620      * Use best possible cause for err.initCause(), substituting the
   531      * cause for err itself if the cause has the same (or better) type.
   621      * cause for err itself if the cause has the same (or better) type.
   532      */
   622      */
   533     private static Error initCauseFrom(Error err, Exception ex) {
   623     static <E extends Error> E initCauseFrom(E err, Exception ex) {
   534         Throwable th = ex.getCause();
   624         Throwable th = ex.getCause();
   535         if (err.getClass().isInstance(th))
   625         @SuppressWarnings("unchecked")
   536            return (Error) th;
   626         final Class<E> Eclass = (Class<E>) err.getClass();
       
   627         if (Eclass.isInstance(th))
       
   628            return Eclass.cast(th);
   537         err.initCause(th == null ? ex : th);
   629         err.initCause(th == null ? ex : th);
   538         return err;
   630         return err;
   539     }
   631     }
   540 
   632 
   541     /**
   633     /**