< 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.AOTSafeClassInitializer;
  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

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

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





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

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

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

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

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















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

















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

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

 635             // retyping can be done without a cast
 636             return FT_UNCHECKED_REF;
 637         } else {
 638             return FT_CHECKED_REF;


 639         }

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






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






























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

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

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


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
















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


 758 

 759         MethodType linkerType;
 760         if (isGetter)
 761             linkerType = MethodType.methodType(ft, Object.class, long.class);
 762         else
 763             linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);





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



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




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






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



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




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



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








 916                 default:
 917                     throw newInternalError("Unknown function: " + func);
 918             }
 919         } catch (ReflectiveOperationException ex) {
 920             throw newInternalError(ex);
 921         }
 922     }
 923 
 924     private static NamedFunction getNamedFunction(String name, MethodType type)
 925         throws ReflectiveOperationException
 926     {
 927         MemberName member = new MemberName(DirectMethodHandle.class, name, type, REF_invokeStatic);
 928         return new NamedFunction(
 929                 MemberName.getFactory().resolveOrFail(REF_invokeStatic, member,
 930                                                       DirectMethodHandle.class, LM_TRUSTED,
 931                                                       NoSuchMethodException.class));
 932     }
 933 
 934     static {
 935         // 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.AOTSafeClassInitializer;
  32 import jdk.internal.vm.annotation.ForceInline;
  33 import jdk.internal.vm.annotation.Stable;
  34 import sun.invoke.util.ValueConversions;
  35 import sun.invoke.util.VerifyAccess;
  36 import sun.invoke.util.Wrapper;
  37 
  38 import java.util.Arrays;
  39 import java.util.Objects;
  40 import java.util.function.Function;
  41 
  42 import static java.lang.invoke.LambdaForm.*;
  43 import static java.lang.invoke.LambdaForm.Kind.*;
  44 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  45 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  46 import static java.lang.invoke.MethodHandleStatics.newInternalError;
  47 import static java.lang.invoke.MethodTypeForm.*;
  48 
  49 /**
  50  * The flavor of method handle which implements a constant reference

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

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

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

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

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


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


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