< prev index next >

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

Print this page

  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.misc.CDS;
  29 import jdk.internal.misc.Unsafe;

  30 import jdk.internal.vm.annotation.ForceInline;
  31 import jdk.internal.vm.annotation.Stable;
  32 import sun.invoke.util.ValueConversions;
  33 import sun.invoke.util.VerifyAccess;
  34 import sun.invoke.util.Wrapper;
  35 
  36 import java.util.Arrays;
  37 import java.util.Objects;
  38 import java.util.function.Function;
  39 
  40 import static java.lang.invoke.LambdaForm.*;
  41 import static java.lang.invoke.LambdaForm.Kind.*;
  42 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  43 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  44 import static java.lang.invoke.MethodHandleStatics.newInternalError;
  45 import static java.lang.invoke.MethodTypeForm.*;
  46 
  47 /**
  48  * The flavor of method handle which implements a constant reference
  49  * to a class member.

 116                 return new StaticAccessor(mtype, lform, member, true, base, offset);
 117             } else {
 118                 long offset = MethodHandleNatives.objectFieldOffset(member);
 119                 assert(offset == (int)offset);
 120                 return new Accessor(mtype, lform, member, true, (int)offset);
 121             }
 122         }
 123     }
 124     static DirectMethodHandle make(Class<?> refc, MemberName member) {
 125         byte refKind = member.getReferenceKind();
 126         if (refKind == REF_invokeSpecial)
 127             refKind =  REF_invokeVirtual;
 128         return make(refKind, refc, member, null /* no callerClass context */);
 129     }
 130     static DirectMethodHandle make(MemberName member) {
 131         if (member.isConstructor())
 132             return makeAllocator(member.getDeclaringClass(), member);
 133         return make(member.getDeclaringClass(), member);
 134     }
 135     static DirectMethodHandle makeAllocator(Class<?> instanceClass, MemberName ctor) {
 136         assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
 137         ctor = ctor.asConstructor();
 138         assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
 139         MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
 140         LambdaForm lform = preparedLambdaForm(ctor);
 141         MemberName init = ctor.asSpecial();
 142         assert(init.getMethodType().returnType() == void.class);
 143         return new Constructor(mtype, lform, ctor, true, init, instanceClass);
 144     }
 145 
 146     @Override
 147     BoundMethodHandle rebind() {
 148         return BoundMethodHandle.makeReinvoker(this);
 149     }
 150 
 151     @Override
 152     MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 153         assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
 154         return new DirectMethodHandle(mt, lf, member, crackable);
 155     }
 156 
 157     @Override
 158     MethodHandle viewAsType(MethodType newType, boolean strict) {

 350         }
 351         Class<?> cls = member.getDeclaringClass();
 352         if (cls == ValueConversions.class ||
 353             cls == MethodHandleImpl.class ||
 354             cls == Invokers.class) {
 355             // These guys have lots of <clinit> DMH creation but we know
 356             // the MHs will not be used until the system is booted.
 357             return false;
 358         }
 359         if (VerifyAccess.isSamePackage(MethodHandle.class, cls) ||
 360             VerifyAccess.isSamePackage(ValueConversions.class, cls)) {
 361             // It is a system class.  It is probably in the process of
 362             // being initialized, but we will help it along just to be safe.
 363             UNSAFE.ensureClassInitialized(cls);
 364             return CDS.needsClassInitBarrier(cls);
 365         }
 366         return UNSAFE.shouldBeInitialized(cls) || CDS.needsClassInitBarrier(cls);
 367     }
 368 
 369     private void ensureInitialized() {
 370         if (checkInitialized(member)) {
 371             // The coast is clear.  Delete the <clinit> barrier.
 372             updateForm(new Function<>() {
 373                 public LambdaForm apply(LambdaForm oldForm) {
 374                     return (member.isField() ? preparedFieldLambdaForm(member)
 375                                              : preparedLambdaForm(member));
 376                 }
 377             });
 378         }
 379     }
 380     private static boolean checkInitialized(MemberName member) {
 381         Class<?> defc = member.getDeclaringClass();
 382         UNSAFE.ensureClassInitialized(defc);
 383         // Once we get here either defc was fully initialized by another thread, or
 384         // defc was already being initialized by the current thread. In the latter case
 385         // the barrier must remain. We can detect this simply by checking if initialization
 386         // is still needed.
 387         return !UNSAFE.shouldBeInitialized(defc);





 388     }
 389 
 390     /*non-public*/
 391     static void ensureInitialized(Object mh) {
 392         ((DirectMethodHandle)mh).ensureInitialized();
 393     }
 394 
 395     /** This subclass represents invokespecial instructions. */
 396     static final class Special extends DirectMethodHandle {
 397         private final Class<?> caller;
 398         private Special(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> caller) {
 399             super(mtype, form, member, crackable);
 400             this.caller = caller;
 401         }
 402         @Override
 403         boolean isInvokeSpecial() {
 404             return true;
 405         }
 406         @Override
 407         MethodHandle copyWith(MethodType mt, LambdaForm lf) {

 487             return new Constructor(newType, form, member, false, initMethod, instanceClass);
 488         }
 489     }
 490 
 491     /*non-public*/
 492     static Object constructorMethod(Object mh) {
 493         Constructor dmh = (Constructor)mh;
 494         return dmh.initMethod;
 495     }
 496 
 497     /*non-public*/
 498     static Object allocateInstance(Object mh) throws InstantiationException {
 499         Constructor dmh = (Constructor)mh;
 500         return UNSAFE.allocateInstance(dmh.instanceClass);
 501     }
 502 
 503     /** This subclass handles non-static field references. */
 504     static final class Accessor extends DirectMethodHandle {
 505         final Class<?> fieldType;
 506         final int      fieldOffset;

 507         private Accessor(MethodType mtype, LambdaForm form, MemberName member,
 508                          boolean crackable, int fieldOffset) {
 509             super(mtype, form, member, crackable);
 510             this.fieldType   = member.getFieldType();
 511             this.fieldOffset = fieldOffset;

 512         }
 513 
 514         @Override Object checkCast(Object obj) {
 515             return fieldType.cast(obj);
 516         }
 517         @Override
 518         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 519             return new Accessor(mt, lf, member, crackable, fieldOffset);
 520         }
 521         @Override
 522         MethodHandle viewAsType(MethodType newType, boolean strict) {
 523             assert(viewAsTypeChecks(newType, strict));
 524             return new Accessor(newType, form, member, false, fieldOffset);
 525         }
 526     }
 527 
 528     @ForceInline
 529     /*non-public*/
 530     static long fieldOffset(Object accessorObj) {
 531         // Note: We return a long because that is what Unsafe.getObject likes.

 581     }
 582 
 583     @ForceInline
 584     /*non-public*/
 585     static Object staticBase(Object accessorObj) {
 586         return ((StaticAccessor)accessorObj).staticBase;
 587     }
 588 
 589     @ForceInline
 590     /*non-public*/
 591     static long staticOffset(Object accessorObj) {
 592         return ((StaticAccessor)accessorObj).staticOffset;
 593     }
 594 
 595     @ForceInline
 596     /*non-public*/
 597     static Object checkCast(Object mh, Object obj) {
 598         return ((DirectMethodHandle) mh).checkCast(obj);
 599     }
 600 















 601     Object checkCast(Object obj) {
 602         return member.getMethodType().returnType().cast(obj);
 603     }
 604 
 605     // Caching machinery for field accessors:
 606     static final byte
 607             AF_GETFIELD        = 0,
 608             AF_PUTFIELD        = 1,
 609             AF_GETSTATIC       = 2,
 610             AF_PUTSTATIC       = 3,
 611             AF_GETSTATIC_INIT  = 4,
 612             AF_PUTSTATIC_INIT  = 5,
 613             AF_LIMIT           = 6;
 614     // Enumerate the different field kinds using Wrapper,
 615     // with an extra case added for checked references.
 616     static final int
 617             FT_UNCHECKED_REF   = Wrapper.OBJECT.ordinal(),
 618             FT_CHECKED_REF     = Wrapper.VOID.ordinal(),
 619             FT_LIMIT           = Wrapper.COUNT;

















 620     private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
 621         return ((formOp * FT_LIMIT * 2)
 622                 + (isVolatile ? FT_LIMIT : 0)
 623                 + ftypeKind);
 624     }
 625     @Stable
 626     private static final LambdaForm[] ACCESSOR_FORMS
 627             = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
 628     static int ftypeKind(Class<?> ftype) {
 629         if (ftype.isPrimitive()) {

 630             return Wrapper.forPrimitiveType(ftype).ordinal();
 631         } else if (ftype.isInterface() || ftype.isAssignableFrom(Object.class)) {

 632             // retyping can be done without a cast
 633             return FT_UNCHECKED_REF;
 634         } else {
 635             return FT_CHECKED_REF;


 636         }

 637     }
 638 
 639     /**
 640      * Create a LF which can access the given field.
 641      * Cache and share this structure among all fields with
 642      * the same basicType and refKind.
 643      */
 644     private static LambdaForm preparedFieldLambdaForm(MemberName m) {
 645         Class<?> ftype = m.getFieldType();
 646         boolean isVolatile = m.isVolatile();
 647         byte formOp = switch (m.getReferenceKind()) {
 648             case REF_getField  -> AF_GETFIELD;
 649             case REF_putField  -> AF_PUTFIELD;
 650             case REF_getStatic -> AF_GETSTATIC;
 651             case REF_putStatic -> AF_PUTSTATIC;
 652             default -> throw new InternalError(m.toString());
 653         };
 654         if (shouldBeInitialized(m)) {
 655             // precompute the barrier-free version:
 656             preparedFieldLambdaForm(formOp, isVolatile, ftype);
 657             assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
 658                    (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
 659             formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
 660         }
 661         LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
 662         assert(lform.methodType().dropParameterTypes(0, 1)
 663                 .equals(m.getInvocationType().basicType()))
 664                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 665         return lform;
 666     }
 667     private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, Class<?> ftype) {
 668         int ftypeKind = ftypeKind(ftype);






 669         int afIndex = afIndex(formOp, isVolatile, ftypeKind);
 670         LambdaForm lform = ACCESSOR_FORMS[afIndex];
 671         if (lform != null)  return lform;
 672         lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
 673         ACCESSOR_FORMS[afIndex] = lform;  // don't bother with a CAS
 674         return lform;
 675     }
 676 
 677     private static final @Stable Wrapper[] ALL_WRAPPERS = Wrapper.values();
 678 
 679     // Names in kind may overload but differ from their basic type
 680     private static Kind getFieldKind(boolean isVolatile, boolean needsInit, boolean needsCast, Wrapper wrapper) {






























 681         if (isVolatile) {
 682             if (needsInit) {
 683                 return switch (wrapper) {
 684                     case BYTE -> VOLATILE_FIELD_ACCESS_INIT_B;
 685                     case CHAR -> VOLATILE_FIELD_ACCESS_INIT_C;
 686                     case SHORT -> VOLATILE_FIELD_ACCESS_INIT_S;
 687                     case BOOLEAN -> VOLATILE_FIELD_ACCESS_INIT_Z;
 688                     default -> needsCast ? VOLATILE_FIELD_ACCESS_INIT_CAST : VOLATILE_FIELD_ACCESS_INIT;
 689                 };

 690             } else {
 691                 return switch (wrapper) {
 692                     case BYTE -> VOLATILE_FIELD_ACCESS_B;
 693                     case CHAR -> VOLATILE_FIELD_ACCESS_C;
 694                     case SHORT -> VOLATILE_FIELD_ACCESS_S;
 695                     case BOOLEAN -> VOLATILE_FIELD_ACCESS_Z;
 696                     default -> needsCast ? VOLATILE_FIELD_ACCESS_CAST : VOLATILE_FIELD_ACCESS;
 697                 };
 698             }
 699         } else {
 700             if (needsInit) {
 701                 return switch (wrapper) {
 702                     case BYTE -> FIELD_ACCESS_INIT_B;
 703                     case CHAR -> FIELD_ACCESS_INIT_C;
 704                     case SHORT -> FIELD_ACCESS_INIT_S;
 705                     case BOOLEAN -> FIELD_ACCESS_INIT_Z;
 706                     default -> needsCast ? FIELD_ACCESS_INIT_CAST : FIELD_ACCESS_INIT;
 707                 };

 708             } else {
 709                 return switch (wrapper) {
 710                     case BYTE -> FIELD_ACCESS_B;
 711                     case CHAR -> FIELD_ACCESS_C;
 712                     case SHORT -> FIELD_ACCESS_S;
 713                     case BOOLEAN -> FIELD_ACCESS_Z;
 714                     default -> needsCast ? FIELD_ACCESS_CAST : FIELD_ACCESS;
 715                 };
 716             }
 717         }
 718     }
 719 
 720     private static String unsafeMethodName(boolean isGetter, boolean isVolatile, Wrapper wrapper) {


 721         var name = switch (wrapper) {
 722             case BOOLEAN -> "Boolean";
 723             case BYTE -> "Byte";
 724             case CHAR -> "Char";
 725             case SHORT -> "Short";
 726             case INT -> "Int";
 727             case FLOAT -> "Float";
 728             case LONG -> "Long";
 729             case DOUBLE -> "Double";
 730             case OBJECT -> "Reference";
 731             case VOID -> throw new InternalError();
 732         };
 733         var sb = new StringBuilder(3 + name.length() + (isVolatile ? 8 : 0))
 734                 .append(isGetter ? "get" : "put")
 735                 .append(name);
 736         if (isVolatile) {
 737             sb.append("Volatile");
 738         }
 739         return sb.toString();
 740     }
 741 
 742     static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
 743         boolean isGetter  = (formOp & 1) == (AF_GETFIELD & 1);
 744         boolean isStatic  = (formOp >= AF_GETSTATIC);
 745         boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
 746         boolean needsCast = (ftypeKind == FT_CHECKED_REF);
 747         Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]);
 748         Class<?> ft = fw.primitiveType();
 749         assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
















 750 
 751         // getObject, putIntVolatile, etc.
 752         String unsafeMethodName = unsafeMethodName(isGetter, isVolatile, fw);
 753         // isGetter and isStatic is reflected in field type; basic type clash for subwords
 754         Kind kind = getFieldKind(isVolatile, needsInit, needsCast, fw);


 755 

 756         MethodType linkerType;
 757         if (isGetter)
 758             linkerType = MethodType.methodType(ft, Object.class, long.class);
 759         else
 760             linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);





 761         MemberName linker = new MemberName(Unsafe.class, unsafeMethodName, linkerType, REF_invokeVirtual);
 762         try {
 763             linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, LM_TRUSTED,
 764                                               NoSuchMethodException.class);
 765         } catch (ReflectiveOperationException ex) {
 766             throw newInternalError(ex);
 767         }
 768 
 769         // What is the external type of the lambda form?
 770         MethodType mtype;
 771         if (isGetter)
 772             mtype = MethodType.methodType(ft);
 773         else
 774             mtype = MethodType.methodType(void.class, ft);
 775         mtype = mtype.basicType();  // erase short to int, etc.
 776         if (!isStatic)
 777             mtype = mtype.insertParameterTypes(0, Object.class);
 778         final int DMH_THIS  = 0;
 779         final int ARG_BASE  = 1;
 780         final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
 781         // if this is for non-static access, the base pointer is stored at this index:
 782         final int OBJ_BASE  = isStatic ? -1 : ARG_BASE;
 783         // if this is for write access, the value to be written is stored at this index:
 784         final int SET_VALUE  = isGetter ? -1 : ARG_LIMIT - 1;
 785         int nameCursor = ARG_LIMIT;
 786         final int F_HOLDER  = (isStatic ? nameCursor++ : -1);  // static base if any
 787         final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
 788         final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
 789         final int U_HOLDER  = nameCursor++;  // UNSAFE holder
 790         final int INIT_BAR  = (needsInit ? nameCursor++ : -1);



 791         final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
 792         final int LINKER_CALL = nameCursor++;
 793         final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
 794         final int RESULT    = nameCursor-1;  // either the call or the cast
 795         Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
 796         if (needsInit)
 797             names[INIT_BAR] = new Name(getFunction(NF_ensureInitialized), names[DMH_THIS]);
 798         if (needsCast && !isGetter)
 799             names[PRE_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[SET_VALUE]);




 800         Object[] outArgs = new Object[1 + linkerType.parameterCount()];
 801         assert(outArgs.length == (isGetter ? 3 : 4));
 802         outArgs[0] = names[U_HOLDER] = new Name(getFunction(NF_UNSAFE));
 803         if (isStatic) {
 804             outArgs[1] = names[F_HOLDER]  = new Name(getFunction(NF_staticBase), names[DMH_THIS]);
 805             outArgs[2] = names[F_OFFSET]  = new Name(getFunction(NF_staticOffset), names[DMH_THIS]);
 806         } else {
 807             outArgs[1] = names[OBJ_CHECK] = new Name(getFunction(NF_checkBase), names[OBJ_BASE]);
 808             outArgs[2] = names[F_OFFSET]  = new Name(getFunction(NF_fieldOffset), names[DMH_THIS]);
 809         }






 810         if (!isGetter) {
 811             outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
 812         }
 813         for (Object a : outArgs)  assert(a != null);
 814         names[LINKER_CALL] = new Name(linker, outArgs);
 815         if (needsCast && isGetter)
 816             names[POST_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[LINKER_CALL]);
 817         for (Name n : names)  assert(n != null);
 818 
 819         LambdaForm form = LambdaForm.create(ARG_LIMIT, names, RESULT, kind);
 820 
 821         if (LambdaForm.debugNames()) {
 822             // add some detail to the lambdaForm debugname,
 823             // significant only for debugging
 824             StringBuilder nameBuilder = new StringBuilder(unsafeMethodName);
 825             if (isStatic) {
 826                 nameBuilder.append("Static");
 827             } else {
 828                 nameBuilder.append("Field");
 829             }



 830             if (needsCast) {
 831                 nameBuilder.append("Cast");
 832             }
 833             if (needsInit) {
 834                 nameBuilder.append("Init");
 835             }
 836             LambdaForm.associateWithDebugName(form, nameBuilder.toString());
 837         }
 838 
 839         // NF_UNSAFE uses field form, avoid circular dependency in interpreter
 840         form.compileToBytecode();
 841         return form;
 842     }
 843 
 844     /**
 845      * Pre-initialized NamedFunctions for bootstrapping purposes.
 846      */
 847     static final byte NF_internalMemberName = 0,
 848             NF_internalMemberNameEnsureInit = 1,
 849             NF_ensureInitialized = 2,
 850             NF_fieldOffset = 3,
 851             NF_checkBase = 4,
 852             NF_staticBase = 5,
 853             NF_staticOffset = 6,
 854             NF_checkCast = 7,
 855             NF_allocateInstance = 8,
 856             NF_constructorMethod = 9,
 857             NF_UNSAFE = 10,
 858             NF_checkReceiver = 11,
 859             NF_LIMIT = 12;




 860 
 861     private static final @Stable NamedFunction[] NFS = new NamedFunction[NF_LIMIT];
 862 
 863     private static NamedFunction getFunction(byte func) {
 864         NamedFunction nf = NFS[func];
 865         if (nf != null) {
 866             return nf;
 867         }
 868         // Each nf must be statically invocable or we get tied up in our bootstraps.
 869         nf = NFS[func] = createFunction(func);
 870         assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf));
 871         return nf;
 872     }
 873 



 874     private static final MethodType OBJ_OBJ_TYPE = MethodType.methodType(Object.class, Object.class);
 875 
 876     private static final MethodType LONG_OBJ_TYPE = MethodType.methodType(long.class, Object.class);
 877 
 878     private static NamedFunction createFunction(byte func) {
 879         try {
 880             switch (func) {
 881                 case NF_internalMemberName:
 882                     return getNamedFunction("internalMemberName", OBJ_OBJ_TYPE);
 883                 case NF_internalMemberNameEnsureInit:
 884                     return getNamedFunction("internalMemberNameEnsureInit", OBJ_OBJ_TYPE);
 885                 case NF_ensureInitialized:
 886                     return getNamedFunction("ensureInitialized", MethodType.methodType(void.class, Object.class));
 887                 case NF_fieldOffset:
 888                     return getNamedFunction("fieldOffset", LONG_OBJ_TYPE);
 889                 case NF_checkBase:
 890                     return getNamedFunction("checkBase", OBJ_OBJ_TYPE);
 891                 case NF_staticBase:
 892                     return getNamedFunction("staticBase", OBJ_OBJ_TYPE);
 893                 case NF_staticOffset:
 894                     return getNamedFunction("staticOffset", LONG_OBJ_TYPE);
 895                 case NF_checkCast:
 896                     return getNamedFunction("checkCast", MethodType.methodType(Object.class, Object.class, Object.class));
 897                 case NF_allocateInstance:
 898                     return getNamedFunction("allocateInstance", OBJ_OBJ_TYPE);
 899                 case NF_constructorMethod:
 900                     return getNamedFunction("constructorMethod", OBJ_OBJ_TYPE);
 901                 case NF_UNSAFE:
 902                     MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getStatic);
 903                     return new NamedFunction(
 904                             MemberName.getFactory().resolveOrFail(REF_getStatic, member,
 905                                                                   DirectMethodHandle.class, LM_TRUSTED,
 906                                                                   NoSuchFieldException.class));
 907                 case NF_checkReceiver:
 908                     member = new MemberName(DirectMethodHandle.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual);
 909                     return new NamedFunction(
 910                             MemberName.getFactory().resolveOrFail(REF_invokeVirtual, member,
 911                                                                   DirectMethodHandle.class, LM_TRUSTED,
 912                                                                   NoSuchMethodException.class));








 913                 default:
 914                     throw newInternalError("Unknown function: " + func);
 915             }
 916         } catch (ReflectiveOperationException ex) {
 917             throw newInternalError(ex);
 918         }
 919     }
 920 
 921     private static NamedFunction getNamedFunction(String name, MethodType type)
 922         throws ReflectiveOperationException
 923     {
 924         MemberName member = new MemberName(DirectMethodHandle.class, name, type, REF_invokeStatic);
 925         return new NamedFunction(
 926                 MemberName.getFactory().resolveOrFail(REF_invokeStatic, member,
 927                                                       DirectMethodHandle.class, LM_TRUSTED,
 928                                                       NoSuchMethodException.class));
 929     }
 930 
 931     static {
 932         // The Holder class will contain pre-generated DirectMethodHandles resolved

  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.misc.CDS;
  29 import jdk.internal.misc.Unsafe;
  30 import jdk.internal.value.ValueClass;
  31 import jdk.internal.vm.annotation.ForceInline;
  32 import jdk.internal.vm.annotation.Stable;
  33 import sun.invoke.util.ValueConversions;
  34 import sun.invoke.util.VerifyAccess;
  35 import sun.invoke.util.Wrapper;
  36 
  37 import java.util.Arrays;
  38 import java.util.Objects;
  39 import java.util.function.Function;
  40 
  41 import static java.lang.invoke.LambdaForm.*;
  42 import static java.lang.invoke.LambdaForm.Kind.*;
  43 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  44 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  45 import static java.lang.invoke.MethodHandleStatics.newInternalError;
  46 import static java.lang.invoke.MethodTypeForm.*;
  47 
  48 /**
  49  * The flavor of method handle which implements a constant reference
  50  * to a class member.

 117                 return new StaticAccessor(mtype, lform, member, true, base, offset);
 118             } else {
 119                 long offset = MethodHandleNatives.objectFieldOffset(member);
 120                 assert(offset == (int)offset);
 121                 return new Accessor(mtype, lform, member, true, (int)offset);
 122             }
 123         }
 124     }
 125     static DirectMethodHandle make(Class<?> refc, MemberName member) {
 126         byte refKind = member.getReferenceKind();
 127         if (refKind == REF_invokeSpecial)
 128             refKind =  REF_invokeVirtual;
 129         return make(refKind, refc, member, null /* no callerClass context */);
 130     }
 131     static DirectMethodHandle make(MemberName member) {
 132         if (member.isConstructor())
 133             return makeAllocator(member.getDeclaringClass(), member);
 134         return make(member.getDeclaringClass(), member);
 135     }
 136     static DirectMethodHandle makeAllocator(Class<?> instanceClass, MemberName ctor) {
 137         assert(ctor.isConstructor()) : ctor;
 138         ctor = ctor.asConstructor();
 139         assert(ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
 140         MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
 141         LambdaForm lform = preparedLambdaForm(ctor);
 142         MemberName init = ctor.asSpecial();
 143         assert(init.getMethodType().returnType() == void.class);
 144         return new Constructor(mtype, lform, ctor, true, init, instanceClass);
 145     }
 146 
 147     @Override
 148     BoundMethodHandle rebind() {
 149         return BoundMethodHandle.makeReinvoker(this);
 150     }
 151 
 152     @Override
 153     MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 154         assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
 155         return new DirectMethodHandle(mt, lf, member, crackable);
 156     }
 157 
 158     @Override
 159     MethodHandle viewAsType(MethodType newType, boolean strict) {

 351         }
 352         Class<?> cls = member.getDeclaringClass();
 353         if (cls == ValueConversions.class ||
 354             cls == MethodHandleImpl.class ||
 355             cls == Invokers.class) {
 356             // These guys have lots of <clinit> DMH creation but we know
 357             // the MHs will not be used until the system is booted.
 358             return false;
 359         }
 360         if (VerifyAccess.isSamePackage(MethodHandle.class, cls) ||
 361             VerifyAccess.isSamePackage(ValueConversions.class, cls)) {
 362             // It is a system class.  It is probably in the process of
 363             // being initialized, but we will help it along just to be safe.
 364             UNSAFE.ensureClassInitialized(cls);
 365             return CDS.needsClassInitBarrier(cls);
 366         }
 367         return UNSAFE.shouldBeInitialized(cls) || CDS.needsClassInitBarrier(cls);
 368     }
 369 
 370     private void ensureInitialized() {
 371         if (checkInitialized()) {
 372             // The coast is clear.  Delete the <clinit> barrier.
 373             updateForm(new Function<>() {
 374                 public LambdaForm apply(LambdaForm oldForm) {
 375                     return (member.isField() ? preparedFieldLambdaForm(member)
 376                                              : preparedLambdaForm(member));
 377                 }
 378             });
 379         }
 380     }
 381     private boolean checkInitialized() {
 382         Class<?> defc = member.getDeclaringClass();
 383         UNSAFE.ensureClassInitialized(defc);
 384         // Once we get here either defc was fully initialized by another thread, or
 385         // defc was already being initialized by the current thread. In the latter case
 386         // the barrier must remain. We can detect this simply by checking if initialization
 387         // is still needed.
 388         boolean initializingStill = UNSAFE.shouldBeInitialized(defc);
 389         if (initializingStill && member.isStrict()) {
 390             // while <clinit> is running, we track access to strict static fields
 391             UNSAFE.notifyStrictStaticAccess(defc, staticOffset(this), member.isSetter());
 392         }
 393         return !initializingStill;
 394     }
 395 
 396     /*non-public*/
 397     static void ensureInitialized(Object mh) {
 398         ((DirectMethodHandle)mh).ensureInitialized();
 399     }
 400 
 401     /** This subclass represents invokespecial instructions. */
 402     static final class Special extends DirectMethodHandle {
 403         private final Class<?> caller;
 404         private Special(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> caller) {
 405             super(mtype, form, member, crackable);
 406             this.caller = caller;
 407         }
 408         @Override
 409         boolean isInvokeSpecial() {
 410             return true;
 411         }
 412         @Override
 413         MethodHandle copyWith(MethodType mt, LambdaForm lf) {

 493             return new Constructor(newType, form, member, false, initMethod, instanceClass);
 494         }
 495     }
 496 
 497     /*non-public*/
 498     static Object constructorMethod(Object mh) {
 499         Constructor dmh = (Constructor)mh;
 500         return dmh.initMethod;
 501     }
 502 
 503     /*non-public*/
 504     static Object allocateInstance(Object mh) throws InstantiationException {
 505         Constructor dmh = (Constructor)mh;
 506         return UNSAFE.allocateInstance(dmh.instanceClass);
 507     }
 508 
 509     /** This subclass handles non-static field references. */
 510     static final class Accessor extends DirectMethodHandle {
 511         final Class<?> fieldType;
 512         final int      fieldOffset;
 513         final int      layout;
 514         private Accessor(MethodType mtype, LambdaForm form, MemberName member,
 515                          boolean crackable, int fieldOffset) {
 516             super(mtype, form, member, crackable);
 517             this.fieldType   = member.getFieldType();
 518             this.fieldOffset = fieldOffset;
 519             this.layout = member.getLayout();
 520         }
 521 
 522         @Override Object checkCast(Object obj) {
 523             return fieldType.cast(obj);
 524         }
 525         @Override
 526         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 527             return new Accessor(mt, lf, member, crackable, fieldOffset);
 528         }
 529         @Override
 530         MethodHandle viewAsType(MethodType newType, boolean strict) {
 531             assert(viewAsTypeChecks(newType, strict));
 532             return new Accessor(newType, form, member, false, fieldOffset);
 533         }
 534     }
 535 
 536     @ForceInline
 537     /*non-public*/
 538     static long fieldOffset(Object accessorObj) {
 539         // Note: We return a long because that is what Unsafe.getObject likes.

 589     }
 590 
 591     @ForceInline
 592     /*non-public*/
 593     static Object staticBase(Object accessorObj) {
 594         return ((StaticAccessor)accessorObj).staticBase;
 595     }
 596 
 597     @ForceInline
 598     /*non-public*/
 599     static long staticOffset(Object accessorObj) {
 600         return ((StaticAccessor)accessorObj).staticOffset;
 601     }
 602 
 603     @ForceInline
 604     /*non-public*/
 605     static Object checkCast(Object mh, Object obj) {
 606         return ((DirectMethodHandle) mh).checkCast(obj);
 607     }
 608 
 609     @ForceInline
 610     /*non-public*/ static Class<?> fieldType(Object accessorObj) {
 611         return ((Accessor) accessorObj).fieldType;
 612     }
 613 
 614     @ForceInline
 615     static int fieldLayout(Object accessorObj) {
 616         return ((Accessor) accessorObj).layout;
 617     }
 618 
 619     @ForceInline
 620     /*non-public*/ static Class<?> staticFieldType(Object accessorObj) {
 621         return ((StaticAccessor) accessorObj).fieldType;
 622     }
 623 
 624     Object checkCast(Object obj) {
 625         return member.getMethodType().returnType().cast(obj);
 626     }
 627 
 628     // Caching machinery for field accessors:
 629     static final byte
 630             AF_GETFIELD        = 0,
 631             AF_PUTFIELD        = 1,
 632             AF_GETSTATIC       = 2,
 633             AF_PUTSTATIC       = 3,
 634             AF_GETSTATIC_INIT  = 4,
 635             AF_PUTSTATIC_INIT  = 5,
 636             AF_LIMIT           = 6;
 637     // Enumerate the different field kinds using Wrapper,
 638     // with an extra case added for checked references and value field access
 639     static final int
 640             FT_FIRST_REFERENCE = 8,
 641             // Any oop, same sig (Runnable?)
 642             FT_UNCHECKED_REF    = FT_FIRST_REFERENCE,
 643             // Oop with type checks (Number?)
 644             FT_CHECKED_REF      = FT_FIRST_REFERENCE + 1,
 645             // Oop with null checks, (Runnable!)
 646             FT_UNCHECKED_NR_REF = FT_FIRST_REFERENCE + 2,
 647             // Oop with null and type checks, (Number!)
 648             FT_CHECKED_NR_REF   = FT_FIRST_REFERENCE + 3,
 649             FT_FIRST_FLAT = FT_FIRST_REFERENCE + 4,
 650             // nullable flat (must check type), (Integer?)
 651             FT_NULLABLE_FLAT    = FT_FIRST_FLAT,
 652             // Null restricted flat (must check type), (Integer!)
 653             FT_NR_FLAT          = FT_FIRST_FLAT + 1,
 654             FT_LIMIT            = FT_FIRST_FLAT + 2;
 655 
 656     static {
 657         assert FT_FIRST_REFERENCE == Wrapper.OBJECT.ordinal();
 658     }
 659 
 660     private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
 661         return ((formOp * FT_LIMIT * 2)
 662                 + (isVolatile ? FT_LIMIT : 0)
 663                 + ftypeKind);
 664     }
 665     @Stable
 666     private static final LambdaForm[] ACCESSOR_FORMS
 667             = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
 668     static int ftypeKind(Class<?> ftype, boolean isFlat, boolean isNullRestricted) {
 669         if (ftype.isPrimitive()) {
 670             assert !isFlat && !isNullRestricted : ftype;
 671             return Wrapper.forPrimitiveType(ftype).ordinal();
 672         } else if (ftype.isInterface() || ftype.isAssignableFrom(Object.class)) {
 673             assert !isFlat : ftype;
 674             // retyping can be done without a cast
 675             return isNullRestricted ? FT_UNCHECKED_NR_REF : FT_UNCHECKED_REF;
 676         }
 677         if (isFlat) {
 678             assert ValueClass.isConcreteValueClass(ftype) : ftype;
 679             return isNullRestricted ? FT_NR_FLAT : FT_NULLABLE_FLAT;
 680         }
 681         return isNullRestricted ? FT_CHECKED_NR_REF : FT_CHECKED_REF;
 682     }
 683 
 684     /**
 685      * Create a LF which can access the given field.
 686      * Cache and share this structure among all fields with
 687      * the same basicType and refKind.
 688      */
 689     private static LambdaForm preparedFieldLambdaForm(MemberName m) {
 690         Class<?> ftype = m.getFieldType();

 691         byte formOp = switch (m.getReferenceKind()) {
 692             case REF_getField  -> AF_GETFIELD;
 693             case REF_putField  -> AF_PUTFIELD;
 694             case REF_getStatic -> AF_GETSTATIC;
 695             case REF_putStatic -> AF_PUTSTATIC;
 696             default -> throw new InternalError(m.toString());
 697         };
 698         if (shouldBeInitialized(m)) {
 699             // precompute the barrier-free version:
 700             preparedFieldLambdaForm(formOp, m.isVolatile(), m.isFlat(), m.isNullRestricted(), ftype);
 701             assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
 702                    (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
 703             formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
 704         }
 705         LambdaForm lform = preparedFieldLambdaForm(formOp, m.isVolatile(), m.isFlat(), m.isNullRestricted(), ftype);
 706         assert(lform.methodType().dropParameterTypes(0, 1)
 707                 .equals(m.getInvocationType().basicType()))
 708                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 709         return lform;
 710     }
 711 
 712     private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile,
 713                                                       boolean isFlat, boolean isNullRestricted, Class<?> ftype) {
 714         int ftypeKind = ftypeKind(ftype, isFlat, isNullRestricted);
 715         return preparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
 716     }
 717 
 718     private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
 719         int afIndex = afIndex(formOp, isVolatile, ftypeKind);
 720         LambdaForm lform = ACCESSOR_FORMS[afIndex];
 721         if (lform != null)  return lform;
 722         lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
 723         ACCESSOR_FORMS[afIndex] = lform;  // don't bother with a CAS
 724         return lform;
 725     }
 726 
 727     private static final @Stable Wrapper[] ALL_WRAPPERS = Wrapper.values();
 728 
 729     // Names in kind may overload but differ from their basic type
 730     private static Kind getFieldKind(boolean isGetter,
 731                                      boolean isVolatile,
 732                                      boolean needsInit,
 733                                      boolean needsCast,
 734                                      boolean isFlat,
 735                                      boolean isNullRestricted,
 736                                      Wrapper wrapper) {
 737         if (!wrapper.isOther()) {
 738             // primitives
 739             assert !isFlat && !isNullRestricted && !needsCast;
 740             return switch (wrapper) {
 741                 case BYTE -> isVolatile
 742                         ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_B : VOLATILE_FIELD_ACCESS_B)
 743                         : (needsInit ? FIELD_ACCESS_INIT_B : FIELD_ACCESS_B);
 744                 case CHAR -> isVolatile
 745                         ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_C : VOLATILE_FIELD_ACCESS_C)
 746                         : (needsInit ? FIELD_ACCESS_INIT_C : FIELD_ACCESS_C);
 747                 case SHORT -> isVolatile
 748                         ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_S : VOLATILE_FIELD_ACCESS_S)
 749                         : (needsInit ? FIELD_ACCESS_INIT_S : FIELD_ACCESS_S);
 750                 case BOOLEAN -> isVolatile
 751                         ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_Z : VOLATILE_FIELD_ACCESS_Z)
 752                         : (needsInit ? FIELD_ACCESS_INIT_Z : FIELD_ACCESS_Z);
 753                 // basic types
 754                 default -> isVolatile
 755                         ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT : VOLATILE_FIELD_ACCESS)
 756                         : (needsInit ? FIELD_ACCESS_INIT : FIELD_ACCESS);
 757             };
 758         }
 759 
 760         assert !(isGetter && isNullRestricted);
 761         if (isVolatile) {
 762             if (isFlat) {
 763                 assert !needsInit && needsCast;
 764                 return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_FLAT_VALUE : VOLATILE_FIELD_ACCESS_FLAT;
 765             } else if (needsCast) {
 766                 if (needsInit) {
 767                     return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE_CAST_INIT : VOLATILE_FIELD_ACCESS_INIT_CAST;
 768                 } else {
 769                     return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE_CAST : VOLATILE_FIELD_ACCESS_CAST;
 770                 }
 771             } else {
 772                 if (needsInit) {
 773                     return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE_INIT : VOLATILE_FIELD_ACCESS_INIT;
 774                 } else {
 775                     return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE : VOLATILE_FIELD_ACCESS;
 776                 }


 777             }
 778         } else {
 779             if (isFlat) {
 780                 assert !needsInit && needsCast;
 781                 return isNullRestricted ? PUT_NULL_RESTRICTED_FLAT_VALUE : FIELD_ACCESS_FLAT;
 782             } else if (needsCast) {
 783                 if (needsInit) {
 784                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_CAST_INIT : FIELD_ACCESS_INIT_CAST;
 785                 } else {
 786                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_CAST : FIELD_ACCESS_CAST;
 787                 }
 788             } else {
 789                 if (needsInit) {
 790                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_INIT : FIELD_ACCESS_INIT;
 791                 } else {
 792                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE : FIELD_ACCESS;
 793                 }


 794             }
 795         }
 796     }
 797 
 798     private static String unsafeMethodName(boolean isGetter,
 799                                            boolean isVolatile,
 800                                            Wrapper wrapper) {
 801         var name = switch (wrapper) {
 802             case BOOLEAN -> "Boolean";
 803             case BYTE -> "Byte";
 804             case CHAR -> "Char";
 805             case SHORT -> "Short";
 806             case INT -> "Int";
 807             case FLOAT -> "Float";
 808             case LONG -> "Long";
 809             case DOUBLE -> "Double";
 810             case OBJECT -> "Reference";
 811             case VOID -> "FlatValue";
 812         };
 813         var sb = new StringBuilder(3 + name.length() + (isVolatile ? 8 : 0))
 814                 .append(isGetter ? "get" : "put")
 815                 .append(name);
 816         if (isVolatile) {
 817             sb.append("Volatile");
 818         }
 819         return sb.toString();
 820     }
 821 
 822     static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
 823         boolean isGetter  = (formOp & 1) == (AF_GETFIELD & 1);
 824         boolean isStatic  = (formOp >= AF_GETSTATIC);
 825         boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
 826         boolean isFlat = (ftypeKind >= FT_FIRST_FLAT);
 827         boolean isNullRestricted = (ftypeKind == FT_NR_FLAT || ftypeKind == FT_CHECKED_NR_REF || ftypeKind == FT_UNCHECKED_NR_REF);
 828         boolean needsCast = (isFlat || ftypeKind == FT_CHECKED_REF || ftypeKind == FT_CHECKED_NR_REF);
 829 
 830         if (isGetter && isNullRestricted) {
 831             int newKind = switch (ftypeKind) {
 832                 case FT_NR_FLAT -> FT_NULLABLE_FLAT;
 833                 case FT_CHECKED_NR_REF -> FT_CHECKED_REF;
 834                 case FT_UNCHECKED_NR_REF -> FT_UNCHECKED_REF;
 835                 default -> throw new InternalError();
 836             };
 837             return preparedFieldLambdaForm(formOp, isVolatile, newKind);
 838         }
 839 
 840         if (isFlat && isStatic)
 841             throw new InternalError("Static flat not supported yet");
 842 
 843         // primitives, reference, and void for flat
 844         Wrapper fw = ftypeKind < FT_FIRST_REFERENCE ? ALL_WRAPPERS[ftypeKind] :
 845                 isFlat ? Wrapper.VOID : Wrapper.OBJECT;
 846 
 847         // getObject, putIntVolatile, etc.
 848         String unsafeMethodName = unsafeMethodName(isGetter, isVolatile, fw);
 849         // isGetter and isStatic is reflected in field type;
 850         // flat, NR distinguished
 851         // basic type clash for subwords
 852         Kind kind = getFieldKind(isGetter, isVolatile, needsInit, needsCast, isFlat, isNullRestricted, fw);
 853 
 854         Class<?> ft = ftypeKind < FT_FIRST_REFERENCE ? fw.primitiveType() : Object.class;
 855         MethodType linkerType;
 856         if (isGetter) {
 857             linkerType = isFlat
 858                             ? MethodType.methodType(ft, Object.class, long.class, int.class, Class.class)
 859                             : MethodType.methodType(ft, Object.class, long.class);
 860         } else {
 861             linkerType = isFlat
 862                             ? MethodType.methodType(void.class, Object.class, long.class, int.class, Class.class, ft)
 863                             : MethodType.methodType(void.class, Object.class, long.class, ft);
 864         }
 865         MemberName linker = new MemberName(Unsafe.class, unsafeMethodName, linkerType, REF_invokeVirtual);
 866         try {
 867             linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, LM_TRUSTED,
 868                                               NoSuchMethodException.class);
 869         } catch (ReflectiveOperationException ex) {
 870             throw newInternalError(ex);
 871         }
 872 
 873         // What is the external type of the lambda form?
 874         MethodType mtype;
 875         if (isGetter)
 876             mtype = MethodType.methodType(ft);
 877         else
 878             mtype = MethodType.methodType(void.class, ft);
 879         mtype = mtype.basicType();  // erase short to int, etc.
 880         if (!isStatic)
 881             mtype = mtype.insertParameterTypes(0, Object.class);
 882         final int DMH_THIS  = 0;
 883         final int ARG_BASE  = 1;
 884         final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
 885         // if this is for non-static access, the base pointer is stored at this index:
 886         final int OBJ_BASE  = isStatic ? -1 : ARG_BASE;
 887         // if this is for write access, the value to be written is stored at this index:
 888         final int SET_VALUE  = isGetter ? -1 : ARG_LIMIT - 1;
 889         int nameCursor = ARG_LIMIT;
 890         final int F_HOLDER  = (isStatic ? nameCursor++ : -1);  // static base if any
 891         final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
 892         final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
 893         final int U_HOLDER  = nameCursor++;  // UNSAFE holder
 894         final int INIT_BAR  = (needsInit ? nameCursor++ : -1);
 895         final int LAYOUT = (isFlat ? nameCursor++ : -1); // field must be instance
 896         final int VALUE_TYPE = (isFlat ? nameCursor++ : -1);
 897         final int NULL_CHECK  = (isNullRestricted && !isGetter ? nameCursor++ : -1);
 898         final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
 899         final int LINKER_CALL = nameCursor++;
 900         final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
 901         final int RESULT    = nameCursor-1;  // either the call, or the cast
 902         Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
 903         if (needsInit)
 904             names[INIT_BAR] = new Name(getFunction(NF_ensureInitialized), names[DMH_THIS]);
 905         if (!isGetter) {
 906             if (isNullRestricted)
 907                 names[NULL_CHECK] = new Name(getFunction(NF_nullCheck), names[SET_VALUE]);
 908             if (needsCast)
 909                 names[PRE_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[SET_VALUE]);
 910         }
 911         Object[] outArgs = new Object[1 + linkerType.parameterCount()];
 912         assert (outArgs.length == (isGetter ? 3 : 4) + (isFlat ? 2 : 0));
 913         outArgs[0] = names[U_HOLDER] = new Name(getFunction(NF_UNSAFE));
 914         if (isStatic) {
 915             outArgs[1] = names[F_HOLDER]  = new Name(getFunction(NF_staticBase), names[DMH_THIS]);
 916             outArgs[2] = names[F_OFFSET]  = new Name(getFunction(NF_staticOffset), names[DMH_THIS]);
 917         } else {
 918             outArgs[1] = names[OBJ_CHECK] = new Name(getFunction(NF_checkBase), names[OBJ_BASE]);
 919             outArgs[2] = names[F_OFFSET]  = new Name(getFunction(NF_fieldOffset), names[DMH_THIS]);
 920         }
 921         int x = 3;
 922         if (isFlat) {
 923             outArgs[x++] = names[LAYOUT] = new Name(getFunction(NF_fieldLayout), names[DMH_THIS]);
 924             outArgs[x++] = names[VALUE_TYPE] = isStatic ? new Name(getFunction(NF_staticFieldType), names[DMH_THIS])
 925                                                         : new Name(getFunction(NF_fieldType), names[DMH_THIS]);
 926         }
 927         if (!isGetter) {
 928             outArgs[x] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
 929         }
 930         for (Object a : outArgs)  assert(a != null);
 931         names[LINKER_CALL] = new Name(linker, outArgs);
 932         if (needsCast && isGetter)
 933             names[POST_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[LINKER_CALL]);
 934         for (Name n : names)  assert(n != null);
 935 
 936         LambdaForm form = LambdaForm.create(ARG_LIMIT, names, RESULT, kind);
 937 
 938         if (LambdaForm.debugNames()) {
 939             // add some detail to the lambdaForm debugname,
 940             // significant only for debugging
 941             StringBuilder nameBuilder = new StringBuilder(unsafeMethodName);
 942             if (isStatic) {
 943                 nameBuilder.append("Static");
 944             } else {
 945                 nameBuilder.append("Field");
 946             }
 947             if (isNullRestricted) {
 948                 nameBuilder.append("NullRestricted");
 949             }
 950             if (needsCast) {
 951                 nameBuilder.append("Cast");
 952             }
 953             if (needsInit) {
 954                 nameBuilder.append("Init");
 955             }
 956             LambdaForm.associateWithDebugName(form, nameBuilder.toString());
 957         }
 958 
 959         // NF_UNSAFE uses field form, avoid circular dependency in interpreter
 960         form.compileToBytecode();
 961         return form;
 962     }
 963 
 964     /**
 965      * Pre-initialized NamedFunctions for bootstrapping purposes.
 966      */
 967     static final byte NF_internalMemberName = 0,
 968             NF_internalMemberNameEnsureInit = 1,
 969             NF_ensureInitialized = 2,
 970             NF_fieldOffset = 3,
 971             NF_checkBase = 4,
 972             NF_staticBase = 5,
 973             NF_staticOffset = 6,
 974             NF_checkCast = 7,
 975             NF_allocateInstance = 8,
 976             NF_constructorMethod = 9,
 977             NF_UNSAFE = 10,
 978             NF_checkReceiver = 11,
 979             NF_fieldType = 12,
 980             NF_staticFieldType = 13,
 981             NF_fieldLayout = 14,
 982             NF_nullCheck = 15,
 983             NF_LIMIT = 16;
 984 
 985     private static final @Stable NamedFunction[] NFS = new NamedFunction[NF_LIMIT];
 986 
 987     private static NamedFunction getFunction(byte func) {
 988         NamedFunction nf = NFS[func];
 989         if (nf != null) {
 990             return nf;
 991         }
 992         // Each nf must be statically invocable or we get tied up in our bootstraps.
 993         nf = NFS[func] = createFunction(func);
 994         assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf));
 995         return nf;
 996     }
 997 
 998     private static final MethodType CLS_OBJ_TYPE = MethodType.methodType(Class.class, Object.class);
 999     private static final MethodType INT_OBJ_TYPE = MethodType.methodType(int.class, Object.class);
1000 
1001     private static final MethodType OBJ_OBJ_TYPE = MethodType.methodType(Object.class, Object.class);
1002 
1003     private static final MethodType LONG_OBJ_TYPE = MethodType.methodType(long.class, Object.class);
1004 
1005     private static NamedFunction createFunction(byte func) {
1006         try {
1007             switch (func) {
1008                 case NF_internalMemberName:
1009                     return getNamedFunction("internalMemberName", OBJ_OBJ_TYPE);
1010                 case NF_internalMemberNameEnsureInit:
1011                     return getNamedFunction("internalMemberNameEnsureInit", OBJ_OBJ_TYPE);
1012                 case NF_ensureInitialized:
1013                     return getNamedFunction("ensureInitialized", MethodType.methodType(void.class, Object.class));
1014                 case NF_fieldOffset:
1015                     return getNamedFunction("fieldOffset", LONG_OBJ_TYPE);
1016                 case NF_checkBase:
1017                     return getNamedFunction("checkBase", OBJ_OBJ_TYPE);
1018                 case NF_staticBase:
1019                     return getNamedFunction("staticBase", OBJ_OBJ_TYPE);
1020                 case NF_staticOffset:
1021                     return getNamedFunction("staticOffset", LONG_OBJ_TYPE);
1022                 case NF_checkCast:
1023                     return getNamedFunction("checkCast", MethodType.methodType(Object.class, Object.class, Object.class));
1024                 case NF_allocateInstance:
1025                     return getNamedFunction("allocateInstance", OBJ_OBJ_TYPE);
1026                 case NF_constructorMethod:
1027                     return getNamedFunction("constructorMethod", OBJ_OBJ_TYPE);
1028                 case NF_UNSAFE:
1029                     MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getStatic);
1030                     return new NamedFunction(
1031                             MemberName.getFactory().resolveOrFail(REF_getStatic, member,
1032                                                                   DirectMethodHandle.class, LM_TRUSTED,
1033                                                                   NoSuchFieldException.class));
1034                 case NF_checkReceiver:
1035                     member = new MemberName(DirectMethodHandle.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual);
1036                     return new NamedFunction(
1037                             MemberName.getFactory().resolveOrFail(REF_invokeVirtual, member,
1038                                                                   DirectMethodHandle.class, LM_TRUSTED,
1039                                                                   NoSuchMethodException.class));
1040                 case NF_fieldType:
1041                     return getNamedFunction("fieldType", CLS_OBJ_TYPE);
1042                 case NF_staticFieldType:
1043                     return getNamedFunction("staticFieldType", CLS_OBJ_TYPE);
1044                 case NF_nullCheck:
1045                     return getNamedFunction("nullCheck", OBJ_OBJ_TYPE);
1046                 case NF_fieldLayout:
1047                     return getNamedFunction("fieldLayout", INT_OBJ_TYPE);
1048                 default:
1049                     throw newInternalError("Unknown function: " + func);
1050             }
1051         } catch (ReflectiveOperationException ex) {
1052             throw newInternalError(ex);
1053         }
1054     }
1055 
1056     private static NamedFunction getNamedFunction(String name, MethodType type)
1057         throws ReflectiveOperationException
1058     {
1059         MemberName member = new MemberName(DirectMethodHandle.class, name, type, REF_invokeStatic);
1060         return new NamedFunction(
1061                 MemberName.getFactory().resolveOrFail(REF_invokeStatic, member,
1062                                                       DirectMethodHandle.class, LM_TRUSTED,
1063                                                       NoSuchMethodException.class));
1064     }
1065 
1066     static {
1067         // The Holder class will contain pre-generated DirectMethodHandles resolved
< prev index next >