jdk/src/share/classes/java/lang/invoke/Invokers.java
changeset 13610 28122b96858e
parent 13423 17843fff200d
child 14089 0a41b980d62a
equal deleted inserted replaced
13460:c7aa5cca1c01 13610:28122b96858e
    72 
    72 
    73     /*non-public*/ MethodHandle exactInvoker() {
    73     /*non-public*/ MethodHandle exactInvoker() {
    74         MethodHandle invoker = exactInvoker;
    74         MethodHandle invoker = exactInvoker;
    75         if (invoker != null)  return invoker;
    75         if (invoker != null)  return invoker;
    76         MethodType mtype = targetType;
    76         MethodType mtype = targetType;
    77         LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_EX_INVOKER);
    77         MethodType invokerType = mtype.invokerType();
    78         invoker = BoundMethodHandle.bindSingle(mtype.invokerType(), lform, mtype);
    78         LambdaForm lform;
       
    79         final int MTYPE_ARG_APPENDED = 1;  // argument count for appended mtype value
       
    80         if (mtype.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY - MTYPE_ARG_APPENDED) {
       
    81             lform = invokeForm(mtype, false, MethodTypeForm.LF_EX_INVOKER);
       
    82             invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype);
       
    83         } else {
       
    84             // At maximum arity, we cannot afford an extra mtype argument,
       
    85             // so build a fully customized (non-cached) invoker form.
       
    86             lform = invokeForm(mtype, true, MethodTypeForm.LF_EX_INVOKER);
       
    87             invoker = SimpleMethodHandle.make(invokerType, lform);
       
    88         }
    79         assert(checkInvoker(invoker));
    89         assert(checkInvoker(invoker));
    80         exactInvoker = invoker;
    90         exactInvoker = invoker;
    81         return invoker;
    91         return invoker;
    82     }
    92     }
    83 
    93 
    84     /*non-public*/ MethodHandle generalInvoker() {
    94     /*non-public*/ MethodHandle generalInvoker() {
    85         MethodHandle invoker = generalInvoker;
    95         MethodHandle invoker = generalInvoker;
    86         if (invoker != null)  return invoker;
    96         if (invoker != null)  return invoker;
    87         MethodType mtype = targetType;
    97         MethodType mtype = targetType;
    88         prepareForGenericCall(mtype);
    98         MethodType invokerType = mtype.invokerType();
    89         LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_GEN_INVOKER);
    99         LambdaForm lform;
    90         invoker = BoundMethodHandle.bindSingle(mtype.invokerType(), lform, mtype);
   100         final int MTYPE_ARG_APPENDED = 1;  // argument count for appended mtype value
       
   101         assert(GENERIC_INVOKER_SLOP >= MTYPE_ARG_APPENDED);
       
   102         if (mtype.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY - GENERIC_INVOKER_SLOP) {
       
   103             prepareForGenericCall(mtype);
       
   104             lform = invokeForm(mtype, false, MethodTypeForm.LF_GEN_INVOKER);
       
   105             invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype);
       
   106         } else {
       
   107             // At maximum arity, we cannot afford an extra mtype argument,
       
   108             // so build a fully customized (non-cached) invoker form.
       
   109             lform = invokeForm(mtype, true, MethodTypeForm.LF_GEN_INVOKER);
       
   110             invoker = SimpleMethodHandle.make(invokerType, lform);
       
   111         }
    91         assert(checkInvoker(invoker));
   112         assert(checkInvoker(invoker));
    92         generalInvoker = invoker;
   113         generalInvoker = invoker;
    93         return invoker;
   114         return invoker;
    94     }
   115     }
    95 
   116 
   100         assert(checkInvoker(invoker));
   121         assert(checkInvoker(invoker));
   101         return invoker;
   122         return invoker;
   102     }
   123     }
   103 
   124 
   104     static MemberName invokeBasicMethod(MethodType type) {
   125     static MemberName invokeBasicMethod(MethodType type) {
       
   126         type = type.basicType();
   105         String name = "invokeBasic";
   127         String name = "invokeBasic";
   106         try {
   128         try {
   107             //Lookup.findVirtual(MethodHandle.class, name, type);
   129             //Lookup.findVirtual(MethodHandle.class, name, type);
   108             return IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, MethodHandle.class, name, type);
   130             return IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, MethodHandle.class, name, type);
   109 
   131 
   133     }
   155     }
   134 
   156 
   135     /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) {
   157     /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) {
   136         MethodHandle vaInvoker = spreadInvokers[leadingArgCount];
   158         MethodHandle vaInvoker = spreadInvokers[leadingArgCount];
   137         if (vaInvoker != null)  return vaInvoker;
   159         if (vaInvoker != null)  return vaInvoker;
   138         MethodHandle gInvoker = generalInvoker();
       
   139         int spreadArgCount = targetType.parameterCount() - leadingArgCount;
   160         int spreadArgCount = targetType.parameterCount() - leadingArgCount;
   140         vaInvoker = gInvoker.asSpreader(Object[].class, spreadArgCount);
   161         MethodType spreadInvokerType = targetType
       
   162             .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class);
       
   163         if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) {
       
   164             // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a)
       
   165             // where ginvoker.invoke(mh, a*) => mh.invoke(a*).
       
   166             MethodHandle genInvoker = generalInvoker();
       
   167             vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount);
       
   168         } else {
       
   169             // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]).
       
   170             // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a)
       
   171             // where filter(mh) == mh.asSpreader(Object[], spreadArgCount)
       
   172             MethodHandle arrayInvoker = MethodHandles.exactInvoker(spreadInvokerType);
       
   173             MethodHandle makeSpreader;
       
   174             try {
       
   175                 makeSpreader = IMPL_LOOKUP
       
   176                     .findVirtual(MethodHandle.class, "asSpreader",
       
   177                         MethodType.methodType(MethodHandle.class, Class.class, int.class));
       
   178             } catch (ReflectiveOperationException ex) {
       
   179                 throw new InternalError(ex);
       
   180             }
       
   181             makeSpreader = MethodHandles.insertArguments(makeSpreader, 1, Object[].class, spreadArgCount);
       
   182             vaInvoker = MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader);
       
   183         }
       
   184         assert(vaInvoker.type().equals(spreadInvokerType.invokerType()));
   141         spreadInvokers[leadingArgCount] = vaInvoker;
   185         spreadInvokers[leadingArgCount] = vaInvoker;
   142         return vaInvoker;
   186         return vaInvoker;
   143     }
   187     }
   144 
   188 
   145     /*non-public*/ MethodHandle varargsInvoker() {
   189     /*non-public*/ MethodHandle varargsInvoker() {
   169             try {
   213             try {
   170                 THROW_UCS = invoker = IMPL_LOOKUP
   214                 THROW_UCS = invoker = IMPL_LOOKUP
   171                     .findStatic(CallSite.class, "uninitializedCallSite",
   215                     .findStatic(CallSite.class, "uninitializedCallSite",
   172                                 MethodType.methodType(Empty.class));
   216                                 MethodType.methodType(Empty.class));
   173             } catch (ReflectiveOperationException ex) {
   217             } catch (ReflectiveOperationException ex) {
   174                 throw new RuntimeException(ex);
   218                 throw new InternalError(ex);
   175             }
   219             }
   176         }
   220         }
   177         invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType()));
   221         invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType()));
   178         invoker = invoker.dropArguments(targetType, 0, targetType.parameterCount());
   222         invoker = invoker.dropArguments(targetType, 0, targetType.parameterCount());
   179         assert(invoker.type().equals(targetType));
   223         assert(invoker.type().equals(targetType));
   183 
   227 
   184     public String toString() {
   228     public String toString() {
   185         return "Invokers"+targetType;
   229         return "Invokers"+targetType;
   186     }
   230     }
   187 
   231 
   188     private static MethodType fixMethodType(Class<?> callerClass, Object type) {
   232     static MemberName exactInvokerMethod(MethodType mtype, Object[] appendixResult) {
   189         if (type instanceof MethodType)
   233         LambdaForm lform;
   190             return (MethodType) type;
   234         final int MTYPE_ARG_APPENDED = 1;  // argument count for appended mtype value
   191         else
   235         if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MTYPE_ARG_APPENDED) {
   192             return MethodType.fromMethodDescriptorString((String)type, callerClass.getClassLoader());
   236             lform = invokeForm(mtype, false, MethodTypeForm.LF_EX_LINKER);
   193     }
   237             appendixResult[0] = mtype;
   194 
   238         } else {
   195     static MemberName exactInvokerMethod(Class<?> callerClass, Object type, Object[] appendixResult) {
   239             lform = invokeForm(mtype, true, MethodTypeForm.LF_EX_LINKER);
   196         MethodType mtype = fixMethodType(callerClass, type);
   240         }
   197         LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_EX_LINKER);
       
   198         appendixResult[0] = mtype;
       
   199         return lform.vmentry;
   241         return lform.vmentry;
   200     }
   242     }
   201 
   243 
   202     static MemberName genericInvokerMethod(Class<?> callerClass, Object type, Object[] appendixResult) {
   244     static MemberName genericInvokerMethod(MethodType mtype, Object[] appendixResult) {
   203         MethodType mtype = fixMethodType(callerClass, type);
   245         LambdaForm lform;
   204         LambdaForm lform = invokeForm(mtype, MethodTypeForm.LF_GEN_LINKER);
   246         final int MTYPE_ARG_APPENDED = 1;  // argument count for appended mtype value
   205         prepareForGenericCall(mtype);
   247         if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - (MTYPE_ARG_APPENDED + GENERIC_INVOKER_SLOP)) {
   206         appendixResult[0] = mtype;
   248             lform = invokeForm(mtype, false, MethodTypeForm.LF_GEN_LINKER);
       
   249             appendixResult[0] = mtype;
       
   250             prepareForGenericCall(mtype);
       
   251         } else {
       
   252             lform = invokeForm(mtype, true, MethodTypeForm.LF_GEN_LINKER);
       
   253         }
   207         return lform.vmentry;
   254         return lform.vmentry;
   208     }
   255     }
   209 
   256 
   210     private static LambdaForm invokeForm(MethodType mtype, int which) {
   257     private static LambdaForm invokeForm(MethodType mtype, boolean customized, int which) {
   211         mtype = mtype.basicType();  // normalize Z to I, String to Object, etc.
   258         boolean isCached;
       
   259         if (!customized) {
       
   260             mtype = mtype.basicType();  // normalize Z to I, String to Object, etc.
       
   261             isCached = true;
       
   262         } else {
       
   263             isCached = false;  // maybe cache if mtype == mtype.basicType()
       
   264         }
   212         boolean isLinker, isGeneric;
   265         boolean isLinker, isGeneric;
   213         String debugName;
   266         String debugName;
   214         switch (which) {
   267         switch (which) {
   215         case MethodTypeForm.LF_EX_LINKER:   isLinker = true;  isGeneric = false; debugName = "invokeExact_MT"; break;
   268         case MethodTypeForm.LF_EX_LINKER:   isLinker = true;  isGeneric = false; debugName = "invokeExact_MT"; break;
   216         case MethodTypeForm.LF_EX_INVOKER:  isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
   269         case MethodTypeForm.LF_EX_INVOKER:  isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
   217         case MethodTypeForm.LF_GEN_LINKER:  isLinker = true;  isGeneric = true;  debugName = "invoke_MT"; break;
   270         case MethodTypeForm.LF_GEN_LINKER:  isLinker = true;  isGeneric = true;  debugName = "invoke_MT"; break;
   218         case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true;  debugName = "invoker"; break;
   271         case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true;  debugName = "invoker"; break;
   219         default: throw new InternalError();
   272         default: throw new InternalError();
   220         }
   273         }
   221         LambdaForm lform = mtype.form().cachedLambdaForm(which);
   274         LambdaForm lform;
   222         if (lform != null)  return lform;
   275         if (isCached) {
       
   276             lform = mtype.form().cachedLambdaForm(which);
       
   277             if (lform != null)  return lform;
       
   278         }
   223         // exactInvokerForm (Object,Object)Object
   279         // exactInvokerForm (Object,Object)Object
   224         //   link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
   280         //   link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
   225         final int THIS_MH      = 0;
   281         final int THIS_MH      = 0;
   226         final int CALL_MH      = THIS_MH + (isLinker ? 0 : 1);
   282         final int CALL_MH      = THIS_MH + (isLinker ? 0 : 1);
   227         final int ARG_BASE     = CALL_MH + 1;
   283         final int ARG_BASE     = CALL_MH + 1;
   228         final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
   284         final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
   229         final int INARG_LIMIT  = OUTARG_LIMIT + (isLinker ? 1 : 0);
   285         final int INARG_LIMIT  = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
   230         int nameCursor = OUTARG_LIMIT;
   286         int nameCursor = OUTARG_LIMIT;
   231         final int MTYPE_ARG    = nameCursor++;  // might be last in-argument
   287         final int MTYPE_ARG    = customized ? -1 : nameCursor++;  // might be last in-argument
   232         final int CHECK_TYPE   = nameCursor++;
   288         final int CHECK_TYPE   = nameCursor++;
   233         final int LINKER_CALL  = nameCursor++;
   289         final int LINKER_CALL  = nameCursor++;
   234         MethodType invokerFormType = mtype.invokerType();
   290         MethodType invokerFormType = mtype.invokerType();
   235         if (isLinker) {
   291         if (isLinker) {
   236             invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
   292             if (!customized)
       
   293                 invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
   237         } else {
   294         } else {
   238             invokerFormType = invokerFormType.invokerType();
   295             invokerFormType = invokerFormType.invokerType();
   239         }
   296         }
   240         Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
   297         Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
   241         assert(names.length == nameCursor);
   298         assert(names.length == nameCursor)
       
   299                 : Arrays.asList(mtype, customized, which, nameCursor, names.length);
   242         if (MTYPE_ARG >= INARG_LIMIT) {
   300         if (MTYPE_ARG >= INARG_LIMIT) {
   243             assert(names[MTYPE_ARG] == null);
   301             assert(names[MTYPE_ARG] == null);
   244             names[MTYPE_ARG] = BoundMethodHandle.getSpeciesData("L").getterName(names[THIS_MH], 0);
   302             names[MTYPE_ARG] = BoundMethodHandle.getSpeciesData("L").getterName(names[THIS_MH], 0);
   245             // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
   303             // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
   246         }
   304         }
   247 
   305 
   248         // Make the final call.  If isGeneric, then prepend the result of type checking.
   306         // Make the final call.  If isGeneric, then prepend the result of type checking.
   249         MethodType outCallType;
   307         MethodType outCallType;
   250         Object[] outArgs;
   308         Object[] outArgs;
       
   309         Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
   251         if (!isGeneric) {
   310         if (!isGeneric) {
   252             names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], names[MTYPE_ARG]);
   311             names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
   253             // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
   312             // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
   254             outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
   313             outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
   255             outCallType = mtype;
   314             outCallType = mtype;
   256         } else {
   315         } else if (customized) {
   257             names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], names[MTYPE_ARG]);
   316             names[CHECK_TYPE] = new Name(NF_asType, names[CALL_MH], mtypeArg);
       
   317             // mh.invokeGeneric(a*):R =>
       
   318             //  let mt=TYPEOF(a*:R), tmh=asType(mh, mt);
       
   319             //    tmh.invokeBasic(a*)
       
   320             outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
       
   321             outCallType = mtype;
       
   322         } else {
       
   323             names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
   258             // mh.invokeGeneric(a*):R =>
   324             // mh.invokeGeneric(a*):R =>
   259             //  let mt=TYPEOF(a*:R), gamh=checkGenericType(mh, mt);
   325             //  let mt=TYPEOF(a*:R), gamh=checkGenericType(mh, mt);
   260             //    gamh.invokeBasic(mt, mh, a*)
   326             //    gamh.invokeBasic(mt, mh, a*)
   261             final int PREPEND_GAMH = 0, PREPEND_MT = 1, PREPEND_COUNT = 2;
   327             final int PREPEND_GAMH = 0, PREPEND_MT = 1, PREPEND_COUNT = 2;
       
   328             assert(GENERIC_INVOKER_SLOP == PREPEND_COUNT);
   262             outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
   329             outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
   263             // prepend arguments:
   330             // prepend arguments:
   264             System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
   331             System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
   265             outArgs[PREPEND_GAMH] = names[CHECK_TYPE];
   332             outArgs[PREPEND_GAMH] = names[CHECK_TYPE];
   266             outArgs[PREPEND_MT] = names[MTYPE_ARG];
   333             outArgs[PREPEND_MT] = mtypeArg;
   267             outCallType = mtype.insertParameterTypes(0, MethodType.class, MethodHandle.class);
   334             outCallType = mtype.insertParameterTypes(0, MethodType.class, MethodHandle.class);
   268         }
   335         }
   269         names[LINKER_CALL] = new Name(invokeBasicMethod(outCallType), outArgs);
   336         names[LINKER_CALL] = new Name(invokeBasicMethod(outCallType), outArgs);
   270         lform = new LambdaForm(debugName, INARG_LIMIT, names);
   337         lform = new LambdaForm(debugName, INARG_LIMIT, names);
   271         if (isLinker)
   338         if (isLinker)
   272             lform.compileToBytecode();  // JVM needs a real methodOop
   339             lform.compileToBytecode();  // JVM needs a real methodOop
   273         lform = mtype.form().setCachedLambdaForm(which, lform);
   340         if (isCached)
       
   341             lform = mtype.form().setCachedLambdaForm(which, lform);
   274         return lform;
   342         return lform;
   275     }
   343     }
       
   344     private static final int GENERIC_INVOKER_SLOP = 2;  // used elsewhere to avoid arity problems
   276 
   345 
   277     /*non-public*/ static
   346     /*non-public*/ static
   278     WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
   347     WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
   279         // FIXME: merge with JVM logic for throwing WMTE
   348         // FIXME: merge with JVM logic for throwing WMTE
   280         return new WrongMethodTypeException("expected "+expected+" but found "+actual);
   349         return new WrongMethodTypeException("expected "+expected+" but found "+actual);
   368     }
   437     }
   369 
   438 
   370     // Local constant functions:
   439     // Local constant functions:
   371     private static final NamedFunction NF_checkExactType;
   440     private static final NamedFunction NF_checkExactType;
   372     private static final NamedFunction NF_checkGenericType;
   441     private static final NamedFunction NF_checkGenericType;
       
   442     private static final NamedFunction NF_asType;
   373     private static final NamedFunction NF_getCallSiteTarget;
   443     private static final NamedFunction NF_getCallSiteTarget;
   374     static {
   444     static {
   375         try {
   445         try {
   376             NF_checkExactType = new NamedFunction(Invokers.class
   446             NF_checkExactType = new NamedFunction(Invokers.class
   377                     .getDeclaredMethod("checkExactType", Object.class, Object.class));
   447                     .getDeclaredMethod("checkExactType", Object.class, Object.class));
   378             NF_checkGenericType = new NamedFunction(Invokers.class
   448             NF_checkGenericType = new NamedFunction(Invokers.class
   379                     .getDeclaredMethod("checkGenericType", Object.class, Object.class));
   449                     .getDeclaredMethod("checkGenericType", Object.class, Object.class));
       
   450             NF_asType = new NamedFunction(MethodHandle.class
       
   451                     .getDeclaredMethod("asType", MethodType.class));
   380             NF_getCallSiteTarget = new NamedFunction(Invokers.class
   452             NF_getCallSiteTarget = new NamedFunction(Invokers.class
   381                     .getDeclaredMethod("getCallSiteTarget", Object.class));
   453                     .getDeclaredMethod("getCallSiteTarget", Object.class));
   382             NF_checkExactType.resolve();
   454             NF_checkExactType.resolve();
   383             NF_checkGenericType.resolve();
   455             NF_checkGenericType.resolve();
   384             NF_getCallSiteTarget.resolve();
   456             NF_getCallSiteTarget.resolve();