< prev index next >

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

Print this page
rev 15427 : 8164483: Generate field lambda forms at link time
Reviewed-by: TBD


 470     @ForceInline
 471     /*non-public*/ static Object nullCheck(Object obj) {
 472         return Objects.requireNonNull(obj);
 473     }
 474 
 475     @ForceInline
 476     /*non-public*/ static Object staticBase(Object accessorObj) {
 477         return ((StaticAccessor)accessorObj).staticBase;
 478     }
 479 
 480     @ForceInline
 481     /*non-public*/ static long staticOffset(Object accessorObj) {
 482         return ((StaticAccessor)accessorObj).staticOffset;
 483     }
 484 
 485     @ForceInline
 486     /*non-public*/ static Object checkCast(Object mh, Object obj) {
 487         return ((DirectMethodHandle) mh).checkCast(obj);
 488     }
 489 





 490     Object checkCast(Object obj) {
 491         return member.getReturnType().cast(obj);
 492     }
 493 
 494     // Caching machinery for field accessors:
 495     private static final byte
 496             AF_GETFIELD        = 0,
 497             AF_PUTFIELD        = 1,
 498             AF_GETSTATIC       = 2,
 499             AF_PUTSTATIC       = 3,
 500             AF_GETSTATIC_INIT  = 4,
 501             AF_PUTSTATIC_INIT  = 5,
 502             AF_LIMIT           = 6;
 503     // Enumerate the different field kinds using Wrapper,
 504     // with an extra case added for checked references.
 505     private static final int
 506             FT_LAST_WRAPPER    = Wrapper.COUNT-1,
 507             FT_UNCHECKED_REF   = Wrapper.OBJECT.ordinal(),
 508             FT_CHECKED_REF     = FT_LAST_WRAPPER+1,
 509             FT_LIMIT           = FT_LAST_WRAPPER+2;
 510     private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
 511         return ((formOp * FT_LIMIT * 2)
 512                 + (isVolatile ? FT_LIMIT : 0)
 513                 + ftypeKind);
 514     }
 515     @Stable
 516     private static final LambdaForm[] ACCESSOR_FORMS
 517             = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
 518     private static int ftypeKind(Class<?> ftype) {
 519         if (ftype.isPrimitive())
 520             return Wrapper.forPrimitiveType(ftype).ordinal();
 521         else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
 522             return FT_UNCHECKED_REF;
 523         else
 524             return FT_CHECKED_REF;
 525     }
 526 
 527     /**
 528      * Create a LF which can access the given field.
 529      * Cache and share this structure among all fields with
 530      * the same basicType and refKind.
 531      */
 532     private static LambdaForm preparedFieldLambdaForm(MemberName m) {
 533         Class<?> ftype = m.getFieldType();
 534         boolean isVolatile = m.isVolatile();
 535         byte formOp;
 536         switch (m.getReferenceKind()) {
 537         case REF_getField:      formOp = AF_GETFIELD;    break;
 538         case REF_putField:      formOp = AF_PUTFIELD;    break;


 549         }
 550         LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
 551         maybeCompile(lform, m);
 552         assert(lform.methodType().dropParameterTypes(0, 1)
 553                 .equals(m.getInvocationType().basicType()))
 554                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 555         return lform;
 556     }
 557     private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, Class<?> ftype) {
 558         int ftypeKind = ftypeKind(ftype);
 559         int afIndex = afIndex(formOp, isVolatile, ftypeKind);
 560         LambdaForm lform = ACCESSOR_FORMS[afIndex];
 561         if (lform != null)  return lform;
 562         lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
 563         ACCESSOR_FORMS[afIndex] = lform;  // don't bother with a CAS
 564         return lform;
 565     }
 566 
 567     private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
 568 
 569     private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {

























































 570         boolean isGetter  = (formOp & 1) == (AF_GETFIELD & 1);
 571         boolean isStatic  = (formOp >= AF_GETSTATIC);
 572         boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
 573         boolean needsCast = (ftypeKind == FT_CHECKED_REF);
 574         Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]);
 575         Class<?> ft = fw.primitiveType();
 576         assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
 577 
 578         // getObject, putIntVolatile, etc.
 579         StringBuilder nameBuilder = new StringBuilder();
 580         if (isGetter) {
 581             nameBuilder.append("get");
 582         } else {
 583             nameBuilder.append("put");
 584         }
 585         nameBuilder.append(fw.primitiveSimpleName());
 586         nameBuilder.setCharAt(3, Character.toUpperCase(nameBuilder.charAt(3)));
 587         if (isVolatile) {
 588             nameBuilder.append("Volatile");
 589         }
 590 
 591         MethodType linkerType;
 592         if (isGetter)
 593             linkerType = MethodType.methodType(ft, Object.class, long.class);
 594         else
 595             linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
 596         MemberName linker = new MemberName(Unsafe.class, nameBuilder.toString(), linkerType, REF_invokeVirtual);
 597         try {
 598             linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
 599         } catch (ReflectiveOperationException ex) {
 600             throw newInternalError(ex);
 601         }
 602 
 603         // What is the external type of the lambda form?
 604         MethodType mtype;
 605         if (isGetter)
 606             mtype = MethodType.methodType(ft);
 607         else
 608             mtype = MethodType.methodType(void.class, ft);
 609         mtype = mtype.basicType();  // erase short to int, etc.
 610         if (!isStatic)
 611             mtype = mtype.insertParameterTypes(0, Object.class);
 612         final int DMH_THIS  = 0;
 613         final int ARG_BASE  = 1;
 614         final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
 615         // if this is for non-static access, the base pointer is stored at this index:
 616         final int OBJ_BASE  = isStatic ? -1 : ARG_BASE;
 617         // if this is for write access, the value to be written is stored at this index:
 618         final int SET_VALUE  = isGetter ? -1 : ARG_LIMIT - 1;
 619         int nameCursor = ARG_LIMIT;
 620         final int F_HOLDER  = (isStatic ? nameCursor++ : -1);  // static base if any
 621         final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
 622         final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);

 623         final int INIT_BAR  = (needsInit ? nameCursor++ : -1);
 624         final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
 625         final int LINKER_CALL = nameCursor++;
 626         final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
 627         final int RESULT    = nameCursor-1;  // either the call or the cast
 628         Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
 629         if (needsInit)
 630             names[INIT_BAR] = new Name(NF_ensureInitialized, names[DMH_THIS]);
 631         if (needsCast && !isGetter)
 632             names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
 633         Object[] outArgs = new Object[1 + linkerType.parameterCount()];
 634         assert(outArgs.length == (isGetter ? 3 : 4));
 635         outArgs[0] = UNSAFE;
 636         if (isStatic) {
 637             outArgs[1] = names[F_HOLDER]  = new Name(NF_staticBase, names[DMH_THIS]);
 638             outArgs[2] = names[F_OFFSET]  = new Name(NF_staticOffset, names[DMH_THIS]);
 639         } else {
 640             outArgs[1] = names[OBJ_CHECK] = new Name(NF_checkBase, names[OBJ_BASE]);
 641             outArgs[2] = names[F_OFFSET]  = new Name(NF_fieldOffset, names[DMH_THIS]);
 642         }
 643         if (!isGetter) {
 644             outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
 645         }
 646         for (Object a : outArgs)  assert(a != null);
 647         names[LINKER_CALL] = new Name(linker, outArgs);
 648         if (needsCast && isGetter)
 649             names[POST_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
 650         for (Name n : names)  assert(n != null);
 651         // add some detail to the lambdaForm debugname,
 652         // significant only for debugging

 653         if (isStatic) {
 654             nameBuilder.append("Static");
 655         } else {
 656             nameBuilder.append("Field");
 657         }
 658         if (needsCast)  nameBuilder.append("Cast");
 659         if (needsInit)  nameBuilder.append("Init");


 660         return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);



 661     }
 662 
 663     /**
 664      * Pre-initialized NamedFunctions for bootstrapping purposes.
 665      * Factored in an inner class to delay initialization until first usage.
 666      */
 667     static final NamedFunction
 668             NF_internalMemberName,
 669             NF_internalMemberNameEnsureInit,
 670             NF_ensureInitialized,
 671             NF_fieldOffset,
 672             NF_checkBase,
 673             NF_staticBase,
 674             NF_staticOffset,
 675             NF_checkCast,
 676             NF_allocateInstance,
 677             NF_constructorMethod;

 678     static {
 679         try {
 680             NamedFunction nfs[] = {
 681                     NF_internalMemberName = new NamedFunction(DirectMethodHandle.class
 682                             .getDeclaredMethod("internalMemberName", Object.class)),
 683                     NF_internalMemberNameEnsureInit = new NamedFunction(DirectMethodHandle.class
 684                             .getDeclaredMethod("internalMemberNameEnsureInit", Object.class)),
 685                     NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class
 686                             .getDeclaredMethod("ensureInitialized", Object.class)),
 687                     NF_fieldOffset = new NamedFunction(DirectMethodHandle.class
 688                             .getDeclaredMethod("fieldOffset", Object.class)),
 689                     NF_checkBase = new NamedFunction(DirectMethodHandle.class
 690                             .getDeclaredMethod("checkBase", Object.class)),
 691                     NF_staticBase = new NamedFunction(DirectMethodHandle.class
 692                             .getDeclaredMethod("staticBase", Object.class)),
 693                     NF_staticOffset = new NamedFunction(DirectMethodHandle.class
 694                             .getDeclaredMethod("staticOffset", Object.class)),
 695                     NF_checkCast = new NamedFunction(DirectMethodHandle.class
 696                             .getDeclaredMethod("checkCast", Object.class, Object.class)),
 697                     NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
 698                             .getDeclaredMethod("allocateInstance", Object.class)),
 699                     NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
 700                             .getDeclaredMethod("constructorMethod", Object.class))


 701             };
 702             // Each nf must be statically invocable or we get tied up in our bootstraps.
 703             assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
 704         } catch (ReflectiveOperationException ex) {
 705             throw newInternalError(ex);
 706         }
 707     }
 708 
 709     static {
 710         // The Holder class will contain pre-generated DirectMethodHandles resolved
 711         // speculatively using MemberName.getFactory().resolveOrNull. However, that
 712         // doesn't initialize the class, which subtly breaks inlining etc. By forcing
 713         // initialization of the Holder class we avoid these issues.
 714         UNSAFE.ensureClassInitialized(Holder.class);
 715     }
 716 
 717     /* Placeholder class for DirectMethodHandles generated ahead of time */
 718     final class Holder {}
 719 }


 470     @ForceInline
 471     /*non-public*/ static Object nullCheck(Object obj) {
 472         return Objects.requireNonNull(obj);
 473     }
 474 
 475     @ForceInline
 476     /*non-public*/ static Object staticBase(Object accessorObj) {
 477         return ((StaticAccessor)accessorObj).staticBase;
 478     }
 479 
 480     @ForceInline
 481     /*non-public*/ static long staticOffset(Object accessorObj) {
 482         return ((StaticAccessor)accessorObj).staticOffset;
 483     }
 484 
 485     @ForceInline
 486     /*non-public*/ static Object checkCast(Object mh, Object obj) {
 487         return ((DirectMethodHandle) mh).checkCast(obj);
 488     }
 489 
 490     @ForceInline
 491     /*non-public*/ static Unsafe unsafe() {
 492         return UNSAFE;
 493     }
 494 
 495     Object checkCast(Object obj) {
 496         return member.getReturnType().cast(obj);
 497     }
 498 
 499     // Caching machinery for field accessors:
 500     static final byte
 501             AF_GETFIELD        = 0,
 502             AF_PUTFIELD        = 1,
 503             AF_GETSTATIC       = 2,
 504             AF_PUTSTATIC       = 3,
 505             AF_GETSTATIC_INIT  = 4,
 506             AF_PUTSTATIC_INIT  = 5,
 507             AF_LIMIT           = 6;
 508     // Enumerate the different field kinds using Wrapper,
 509     // with an extra case added for checked references.
 510     static final int
 511             FT_LAST_WRAPPER    = Wrapper.COUNT-1,
 512             FT_UNCHECKED_REF   = Wrapper.OBJECT.ordinal(),
 513             FT_CHECKED_REF     = FT_LAST_WRAPPER+1,
 514             FT_LIMIT           = FT_LAST_WRAPPER+2;
 515     private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
 516         return ((formOp * FT_LIMIT * 2)
 517                 + (isVolatile ? FT_LIMIT : 0)
 518                 + ftypeKind);
 519     }
 520     @Stable
 521     private static final LambdaForm[] ACCESSOR_FORMS
 522             = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
 523     static int ftypeKind(Class<?> ftype) {
 524         if (ftype.isPrimitive())
 525             return Wrapper.forPrimitiveType(ftype).ordinal();
 526         else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
 527             return FT_UNCHECKED_REF;
 528         else
 529             return FT_CHECKED_REF;
 530     }
 531 
 532     /**
 533      * Create a LF which can access the given field.
 534      * Cache and share this structure among all fields with
 535      * the same basicType and refKind.
 536      */
 537     private static LambdaForm preparedFieldLambdaForm(MemberName m) {
 538         Class<?> ftype = m.getFieldType();
 539         boolean isVolatile = m.isVolatile();
 540         byte formOp;
 541         switch (m.getReferenceKind()) {
 542         case REF_getField:      formOp = AF_GETFIELD;    break;
 543         case REF_putField:      formOp = AF_PUTFIELD;    break;


 554         }
 555         LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
 556         maybeCompile(lform, m);
 557         assert(lform.methodType().dropParameterTypes(0, 1)
 558                 .equals(m.getInvocationType().basicType()))
 559                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 560         return lform;
 561     }
 562     private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, Class<?> ftype) {
 563         int ftypeKind = ftypeKind(ftype);
 564         int afIndex = afIndex(formOp, isVolatile, ftypeKind);
 565         LambdaForm lform = ACCESSOR_FORMS[afIndex];
 566         if (lform != null)  return lform;
 567         lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
 568         ACCESSOR_FORMS[afIndex] = lform;  // don't bother with a CAS
 569         return lform;
 570     }
 571 
 572     private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
 573 
 574     private static Kind getFieldKind(boolean isGetter, boolean isVolatile, Wrapper wrapper) {
 575         if (isGetter) {
 576             if (isVolatile) {
 577                 switch (wrapper) {
 578                     case BOOLEAN: return GET_BOOLEAN_VOLATILE;
 579                     case BYTE:    return GET_BYTE_VOLATILE;
 580                     case SHORT:   return GET_SHORT_VOLATILE;
 581                     case CHAR:    return GET_CHAR_VOLATILE;
 582                     case INT:     return GET_INT_VOLATILE;
 583                     case LONG:    return GET_LONG_VOLATILE;
 584                     case FLOAT:   return GET_FLOAT_VOLATILE;
 585                     case DOUBLE:  return GET_DOUBLE_VOLATILE;
 586                     case OBJECT:  return GET_OBJECT_VOLATILE;
 587                 }
 588             } else {
 589                 switch (wrapper) {
 590                     case BOOLEAN: return GET_BOOLEAN;
 591                     case BYTE:    return GET_BYTE;
 592                     case SHORT:   return GET_SHORT;
 593                     case CHAR:    return GET_CHAR;
 594                     case INT:     return GET_INT;
 595                     case LONG:    return GET_LONG;
 596                     case FLOAT:   return GET_FLOAT;
 597                     case DOUBLE:  return GET_DOUBLE;
 598                     case OBJECT:  return GET_OBJECT;
 599                 }
 600             }
 601         } else {
 602             if (isVolatile) {
 603                 switch (wrapper) {
 604                     case BOOLEAN: return PUT_BOOLEAN_VOLATILE;
 605                     case BYTE:    return PUT_BYTE_VOLATILE;
 606                     case SHORT:   return PUT_SHORT_VOLATILE;
 607                     case CHAR:    return PUT_CHAR_VOLATILE;
 608                     case INT:     return PUT_INT_VOLATILE;
 609                     case LONG:    return PUT_LONG_VOLATILE;
 610                     case FLOAT:   return PUT_FLOAT_VOLATILE;
 611                     case DOUBLE:  return PUT_DOUBLE_VOLATILE;
 612                     case OBJECT:  return PUT_OBJECT_VOLATILE;
 613                 }
 614             } else {
 615                 switch (wrapper) {
 616                     case BOOLEAN: return PUT_BOOLEAN;
 617                     case BYTE:    return PUT_BYTE;
 618                     case SHORT:   return PUT_SHORT;
 619                     case CHAR:    return PUT_CHAR;
 620                     case INT:     return PUT_INT;
 621                     case LONG:    return PUT_LONG;
 622                     case FLOAT:   return PUT_FLOAT;
 623                     case DOUBLE:  return PUT_DOUBLE;
 624                     case OBJECT:  return PUT_OBJECT;
 625                 }
 626             }
 627         }
 628         throw new AssertionError("Invalid arguments");
 629     }
 630 
 631     static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
 632         boolean isGetter  = (formOp & 1) == (AF_GETFIELD & 1);
 633         boolean isStatic  = (formOp >= AF_GETSTATIC);
 634         boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
 635         boolean needsCast = (ftypeKind == FT_CHECKED_REF);
 636         Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]);
 637         Class<?> ft = fw.primitiveType();
 638         assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
 639 
 640         // getObject, putIntVolatile, etc.
 641         Kind kind = getFieldKind(isGetter, isVolatile, fw);










 642 
 643         MethodType linkerType;
 644         if (isGetter)
 645             linkerType = MethodType.methodType(ft, Object.class, long.class);
 646         else
 647             linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
 648         MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual);
 649         try {
 650             linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
 651         } catch (ReflectiveOperationException ex) {
 652             throw newInternalError(ex);
 653         }
 654 
 655         // What is the external type of the lambda form?
 656         MethodType mtype;
 657         if (isGetter)
 658             mtype = MethodType.methodType(ft);
 659         else
 660             mtype = MethodType.methodType(void.class, ft);
 661         mtype = mtype.basicType();  // erase short to int, etc.
 662         if (!isStatic)
 663             mtype = mtype.insertParameterTypes(0, Object.class);
 664         final int DMH_THIS  = 0;
 665         final int ARG_BASE  = 1;
 666         final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
 667         // if this is for non-static access, the base pointer is stored at this index:
 668         final int OBJ_BASE  = isStatic ? -1 : ARG_BASE;
 669         // if this is for write access, the value to be written is stored at this index:
 670         final int SET_VALUE  = isGetter ? -1 : ARG_LIMIT - 1;
 671         int nameCursor = ARG_LIMIT;
 672         final int F_HOLDER  = (isStatic ? nameCursor++ : -1);  // static base if any
 673         final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
 674         final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
 675         final int U_HOLDER  = nameCursor++;  // UNSAFE holder
 676         final int INIT_BAR  = (needsInit ? nameCursor++ : -1);
 677         final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
 678         final int LINKER_CALL = nameCursor++;
 679         final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
 680         final int RESULT    = nameCursor-1;  // either the call or the cast
 681         Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
 682         if (needsInit)
 683             names[INIT_BAR] = new Name(NF_ensureInitialized, names[DMH_THIS]);
 684         if (needsCast && !isGetter)
 685             names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
 686         Object[] outArgs = new Object[1 + linkerType.parameterCount()];
 687         assert(outArgs.length == (isGetter ? 3 : 4));
 688         outArgs[0] = names[U_HOLDER] = new Name(NF_unsafe);
 689         if (isStatic) {
 690             outArgs[1] = names[F_HOLDER]  = new Name(NF_staticBase, names[DMH_THIS]);
 691             outArgs[2] = names[F_OFFSET]  = new Name(NF_staticOffset, names[DMH_THIS]);
 692         } else {
 693             outArgs[1] = names[OBJ_CHECK] = new Name(NF_checkBase, names[OBJ_BASE]);
 694             outArgs[2] = names[F_OFFSET]  = new Name(NF_fieldOffset, names[DMH_THIS]);
 695         }
 696         if (!isGetter) {
 697             outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
 698         }
 699         for (Object a : outArgs)  assert(a != null);
 700         names[LINKER_CALL] = new Name(linker, outArgs);
 701         if (needsCast && isGetter)
 702             names[POST_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
 703         for (Name n : names)  assert(n != null);
 704         // add some detail to the lambdaForm debugname,
 705         // significant only for debugging
 706         StringBuilder nameBuilder = new StringBuilder(kind.methodName);
 707         if (isStatic) {
 708             nameBuilder.append("Static");
 709         } else {
 710             nameBuilder.append("Field");
 711         }
 712         if (needsCast)  nameBuilder.append("Cast");
 713         if (needsInit)  nameBuilder.append("Init");
 714         if (needsCast || needsInit) {
 715             // can't use the pre-generated form when casting and/or initializing
 716             return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
 717         } else {
 718             return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT, kind);
 719         }
 720     }
 721 
 722     /**
 723      * Pre-initialized NamedFunctions for bootstrapping purposes.
 724      * Factored in an inner class to delay initialization until first usage.
 725      */
 726     static final NamedFunction
 727             NF_internalMemberName,
 728             NF_internalMemberNameEnsureInit,
 729             NF_ensureInitialized,
 730             NF_fieldOffset,
 731             NF_checkBase,
 732             NF_staticBase,
 733             NF_staticOffset,
 734             NF_checkCast,
 735             NF_allocateInstance,
 736             NF_constructorMethod,
 737             NF_unsafe;
 738     static {
 739         try {
 740             NamedFunction nfs[] = {
 741                     NF_internalMemberName = new NamedFunction(DirectMethodHandle.class
 742                             .getDeclaredMethod("internalMemberName", Object.class)),
 743                     NF_internalMemberNameEnsureInit = new NamedFunction(DirectMethodHandle.class
 744                             .getDeclaredMethod("internalMemberNameEnsureInit", Object.class)),
 745                     NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class
 746                             .getDeclaredMethod("ensureInitialized", Object.class)),
 747                     NF_fieldOffset = new NamedFunction(DirectMethodHandle.class
 748                             .getDeclaredMethod("fieldOffset", Object.class)),
 749                     NF_checkBase = new NamedFunction(DirectMethodHandle.class
 750                             .getDeclaredMethod("checkBase", Object.class)),
 751                     NF_staticBase = new NamedFunction(DirectMethodHandle.class
 752                             .getDeclaredMethod("staticBase", Object.class)),
 753                     NF_staticOffset = new NamedFunction(DirectMethodHandle.class
 754                             .getDeclaredMethod("staticOffset", Object.class)),
 755                     NF_checkCast = new NamedFunction(DirectMethodHandle.class
 756                             .getDeclaredMethod("checkCast", Object.class, Object.class)),
 757                     NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
 758                             .getDeclaredMethod("allocateInstance", Object.class)),
 759                     NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
 760                             .getDeclaredMethod("constructorMethod", Object.class)),
 761                     NF_unsafe = new NamedFunction(DirectMethodHandle.class
 762                             .getDeclaredMethod("unsafe"))
 763             };
 764             // Each nf must be statically invocable or we get tied up in our bootstraps.
 765             assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
 766         } catch (ReflectiveOperationException ex) {
 767             throw newInternalError(ex);
 768         }
 769     }
 770 
 771     static {
 772         // The Holder class will contain pre-generated DirectMethodHandles resolved
 773         // speculatively using MemberName.getFactory().resolveOrNull. However, that
 774         // doesn't initialize the class, which subtly breaks inlining etc. By forcing
 775         // initialization of the Holder class we avoid these issues.
 776         UNSAFE.ensureClassInitialized(Holder.class);
 777     }
 778 
 779     /* Placeholder class for DirectMethodHandles generated ahead of time */
 780     final class Holder {}
 781 }
< prev index next >