src/java.base/share/classes/java/lang/invoke/Invokers.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/java.base/share/classes/java/lang/invoke

src/java.base/share/classes/java/lang/invoke/Invokers.java

Print this page
rev 11258 : 8069591: Customize LambdaForms which are invoked using MH.invoke/invokeExact
Reviewed-by: ?


 230         case MethodTypeForm.LF_EX_INVOKER:  isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
 231         case MethodTypeForm.LF_GEN_LINKER:  isLinker = true;  isGeneric = true;  debugName = "invoke_MT"; break;
 232         case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true;  debugName = "invoker"; break;
 233         default: throw new InternalError();
 234         }
 235         LambdaForm lform;
 236         if (isCached) {
 237             lform = mtype.form().cachedLambdaForm(which);
 238             if (lform != null)  return lform;
 239         }
 240         // exactInvokerForm (Object,Object)Object
 241         //   link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
 242         final int THIS_MH      = 0;
 243         final int CALL_MH      = THIS_MH + (isLinker ? 0 : 1);
 244         final int ARG_BASE     = CALL_MH + 1;
 245         final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
 246         final int INARG_LIMIT  = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
 247         int nameCursor = OUTARG_LIMIT;
 248         final int MTYPE_ARG    = customized ? -1 : nameCursor++;  // might be last in-argument
 249         final int CHECK_TYPE   = nameCursor++;

 250         final int LINKER_CALL  = nameCursor++;
 251         MethodType invokerFormType = mtype.invokerType();
 252         if (isLinker) {
 253             if (!customized)
 254                 invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
 255         } else {
 256             invokerFormType = invokerFormType.invokerType();
 257         }
 258         Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
 259         assert(names.length == nameCursor)
 260                 : Arrays.asList(mtype, customized, which, nameCursor, names.length);
 261         if (MTYPE_ARG >= INARG_LIMIT) {
 262             assert(names[MTYPE_ARG] == null);
 263             BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
 264             names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
 265             NamedFunction getter = speciesData.getterFunction(0);
 266             names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
 267             // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
 268         }
 269 
 270         // Make the final call.  If isGeneric, then prepend the result of type checking.
 271         MethodType outCallType = mtype.basicType();
 272         Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
 273         Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
 274         if (!isGeneric) {
 275             names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
 276             // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
 277         } else {
 278             names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
 279             // mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
 280             outArgs[0] = names[CHECK_TYPE];
 281         }



 282         names[LINKER_CALL] = new Name(outCallType, outArgs);
 283         lform = new LambdaForm(debugName, INARG_LIMIT, names);
 284         if (isLinker)
 285             lform.compileToBytecode();  // JVM needs a real methodOop
 286         if (isCached)
 287             lform = mtype.form().setCachedLambdaForm(which, lform);
 288         return lform;
 289     }
 290 
 291     /*non-public*/ static
 292     WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
 293         // FIXME: merge with JVM logic for throwing WMTE
 294         return new WrongMethodTypeException("expected "+expected+" but found "+actual);
 295     }
 296 
 297     /** Static definition of MethodHandle.invokeExact checking code. */
 298     /*non-public*/ static
 299     @ForceInline
 300     void checkExactType(Object mhObj, Object expectedObj) {
 301         MethodHandle mh = (MethodHandle) mhObj;


 369         // (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
 370         final int PREPEND_MH = 0, PREPEND_COUNT = 1;
 371         Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
 372         // prepend MH argument:
 373         System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
 374         outArgs[PREPEND_MH] = names[CALL_MH];
 375         names[LINKER_CALL] = new Name(mtype, outArgs);
 376         lform = new LambdaForm((skipCallSite ? "linkToTargetMethod" : "linkToCallSite"), INARG_LIMIT, names);
 377         lform.compileToBytecode();  // JVM needs a real methodOop
 378         lform = mtype.form().setCachedLambdaForm(which, lform);
 379         return lform;
 380     }
 381 
 382     /** Static definition of MethodHandle.invokeGeneric checking code. */
 383     /*non-public*/ static
 384     @ForceInline
 385     Object getCallSiteTarget(Object site) {
 386         return ((CallSite)site).getTarget();
 387     }
 388 


















 389     // Local constant functions:
 390     private static final NamedFunction
 391         NF_checkExactType,
 392         NF_checkGenericType,
 393         NF_getCallSiteTarget;

 394     static {
 395         try {
 396             NamedFunction nfs[] = {
 397                 NF_checkExactType = new NamedFunction(Invokers.class
 398                         .getDeclaredMethod("checkExactType", Object.class, Object.class)),
 399                 NF_checkGenericType = new NamedFunction(Invokers.class
 400                         .getDeclaredMethod("checkGenericType", Object.class, Object.class)),
 401                 NF_getCallSiteTarget = new NamedFunction(Invokers.class
 402                         .getDeclaredMethod("getCallSiteTarget", Object.class))


 403             };
 404             for (NamedFunction nf : nfs) {
 405                 // Each nf must be statically invocable or we get tied up in our bootstraps.
 406                 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
 407                 nf.resolve();
 408             }
 409         } catch (ReflectiveOperationException ex) {
 410             throw newInternalError(ex);
 411         }
 412     }
 413 
 414     private static class Lazy {
 415         private static final MethodHandle MH_asSpreader;
 416 
 417         static {
 418             try {
 419                 MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader",
 420                         MethodType.methodType(MethodHandle.class, Class.class, int.class));
 421             } catch (ReflectiveOperationException ex) {
 422                 throw newInternalError(ex);


 230         case MethodTypeForm.LF_EX_INVOKER:  isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
 231         case MethodTypeForm.LF_GEN_LINKER:  isLinker = true;  isGeneric = true;  debugName = "invoke_MT"; break;
 232         case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true;  debugName = "invoker"; break;
 233         default: throw new InternalError();
 234         }
 235         LambdaForm lform;
 236         if (isCached) {
 237             lform = mtype.form().cachedLambdaForm(which);
 238             if (lform != null)  return lform;
 239         }
 240         // exactInvokerForm (Object,Object)Object
 241         //   link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
 242         final int THIS_MH      = 0;
 243         final int CALL_MH      = THIS_MH + (isLinker ? 0 : 1);
 244         final int ARG_BASE     = CALL_MH + 1;
 245         final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
 246         final int INARG_LIMIT  = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
 247         int nameCursor = OUTARG_LIMIT;
 248         final int MTYPE_ARG    = customized ? -1 : nameCursor++;  // might be last in-argument
 249         final int CHECK_TYPE   = nameCursor++;
 250         final int CHECK_CUSTOM = (CUSTOMIZE_THRESHOLD >= 0) ? nameCursor++ : -1;
 251         final int LINKER_CALL  = nameCursor++;
 252         MethodType invokerFormType = mtype.invokerType();
 253         if (isLinker) {
 254             if (!customized)
 255                 invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
 256         } else {
 257             invokerFormType = invokerFormType.invokerType();
 258         }
 259         Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
 260         assert(names.length == nameCursor)
 261                 : Arrays.asList(mtype, customized, which, nameCursor, names.length);
 262         if (MTYPE_ARG >= INARG_LIMIT) {
 263             assert(names[MTYPE_ARG] == null);
 264             BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
 265             names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
 266             NamedFunction getter = speciesData.getterFunction(0);
 267             names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
 268             // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
 269         }
 270 
 271         // Make the final call.  If isGeneric, then prepend the result of type checking.
 272         MethodType outCallType = mtype.basicType();
 273         Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
 274         Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
 275         if (!isGeneric) {
 276             names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
 277             // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
 278         } else {
 279             names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
 280             // mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
 281             outArgs[0] = names[CHECK_TYPE];
 282         }
 283         if (CHECK_CUSTOM != -1) {
 284             names[CHECK_CUSTOM] = new Name(NF_checkCustomized, names[CALL_MH]);
 285         }
 286         names[LINKER_CALL] = new Name(outCallType, outArgs);
 287         lform = new LambdaForm(debugName, INARG_LIMIT, names);
 288         if (isLinker)
 289             lform.compileToBytecode();  // JVM needs a real methodOop
 290         if (isCached)
 291             lform = mtype.form().setCachedLambdaForm(which, lform);
 292         return lform;
 293     }
 294 
 295     /*non-public*/ static
 296     WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
 297         // FIXME: merge with JVM logic for throwing WMTE
 298         return new WrongMethodTypeException("expected "+expected+" but found "+actual);
 299     }
 300 
 301     /** Static definition of MethodHandle.invokeExact checking code. */
 302     /*non-public*/ static
 303     @ForceInline
 304     void checkExactType(Object mhObj, Object expectedObj) {
 305         MethodHandle mh = (MethodHandle) mhObj;


 373         // (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
 374         final int PREPEND_MH = 0, PREPEND_COUNT = 1;
 375         Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
 376         // prepend MH argument:
 377         System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
 378         outArgs[PREPEND_MH] = names[CALL_MH];
 379         names[LINKER_CALL] = new Name(mtype, outArgs);
 380         lform = new LambdaForm((skipCallSite ? "linkToTargetMethod" : "linkToCallSite"), INARG_LIMIT, names);
 381         lform.compileToBytecode();  // JVM needs a real methodOop
 382         lform = mtype.form().setCachedLambdaForm(which, lform);
 383         return lform;
 384     }
 385 
 386     /** Static definition of MethodHandle.invokeGeneric checking code. */
 387     /*non-public*/ static
 388     @ForceInline
 389     Object getCallSiteTarget(Object site) {
 390         return ((CallSite)site).getTarget();
 391     }
 392 
 393     /*non-public*/ static
 394     @ForceInline
 395     void checkCustomized(MethodHandle mh) {
 396         if (mh.form.customized == null) {
 397             maybeCustomize(mh);
 398         }
 399     }
 400 
 401     /*non-public*/ static
 402     @DontInline
 403     void maybeCustomize(MethodHandle mh) {
 404         if (mh.customizationCount >= CUSTOMIZE_THRESHOLD) {
 405             mh.customize();
 406         } else {
 407             mh.customizationCount += 1;
 408         }
 409     }
 410 
 411     // Local constant functions:
 412     private static final NamedFunction
 413         NF_checkExactType,
 414         NF_checkGenericType,
 415         NF_getCallSiteTarget,
 416         NF_checkCustomized;
 417     static {
 418         try {
 419             NamedFunction nfs[] = {
 420                 NF_checkExactType = new NamedFunction(Invokers.class
 421                         .getDeclaredMethod("checkExactType", Object.class, Object.class)),
 422                 NF_checkGenericType = new NamedFunction(Invokers.class
 423                         .getDeclaredMethod("checkGenericType", Object.class, Object.class)),
 424                 NF_getCallSiteTarget = new NamedFunction(Invokers.class
 425                         .getDeclaredMethod("getCallSiteTarget", Object.class)),
 426                 NF_checkCustomized = new NamedFunction(Invokers.class
 427                         .getDeclaredMethod("checkCustomized", MethodHandle.class))
 428             };
 429             for (NamedFunction nf : nfs) {
 430                 // Each nf must be statically invocable or we get tied up in our bootstraps.
 431                 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
 432                 nf.resolve();
 433             }
 434         } catch (ReflectiveOperationException ex) {
 435             throw newInternalError(ex);
 436         }
 437     }
 438 
 439     private static class Lazy {
 440         private static final MethodHandle MH_asSpreader;
 441 
 442         static {
 443             try {
 444                 MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader",
 445                         MethodType.methodType(MethodHandle.class, Class.class, int.class));
 446             } catch (ReflectiveOperationException ex) {
 447                 throw newInternalError(ex);
src/java.base/share/classes/java/lang/invoke/Invokers.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File