< prev index next >

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

Print this page

 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) {

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

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

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















 608     Object checkCast(Object obj) {
 609         return member.getMethodType().returnType().cast(obj);
 610     }
 611 
 612     // Caching machinery for field accessors:
 613     static final byte
 614             AF_GETFIELD        = 0,
 615             AF_PUTFIELD        = 1,
 616             AF_GETSTATIC       = 2,
 617             AF_PUTSTATIC       = 3,
 618             AF_GETSTATIC_INIT  = 4,
 619             AF_PUTSTATIC_INIT  = 5,
 620             AF_LIMIT           = 6;
 621     // Enumerate the different field kinds using Wrapper,
 622     // with an extra case added for checked references.
 623     static final int
 624             FT_LAST_WRAPPER    = Wrapper.COUNT-1,
 625             FT_UNCHECKED_REF   = Wrapper.OBJECT.ordinal(),
 626             FT_CHECKED_REF     = FT_LAST_WRAPPER+1,
 627             FT_LIMIT           = FT_LAST_WRAPPER+2;
 628     private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {

 629         return ((formOp * FT_LIMIT * 2)
 630                 + (isVolatile ? FT_LIMIT : 0)


 631                 + ftypeKind);
 632     }
 633     @Stable
 634     private static final LambdaForm[] ACCESSOR_FORMS
 635             = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
 636     static int ftypeKind(Class<?> ftype) {
 637         if (ftype.isPrimitive()) {
 638             return Wrapper.forPrimitiveType(ftype).ordinal();
 639         } else if (ftype.isInterface() || ftype.isAssignableFrom(Object.class)) {
 640             // retyping can be done without a cast
 641             return FT_UNCHECKED_REF;
 642         } else {
 643             return FT_CHECKED_REF;
 644         }
 645     }
 646 
 647     /**
 648      * Create a LF which can access the given field.
 649      * Cache and share this structure among all fields with
 650      * the same basicType and refKind.
 651      */
 652     private static LambdaForm preparedFieldLambdaForm(MemberName m) {
 653         Class<?> ftype = m.getFieldType();
 654         boolean isVolatile = m.isVolatile();
 655         byte formOp = switch (m.getReferenceKind()) {
 656             case REF_getField  -> AF_GETFIELD;
 657             case REF_putField  -> AF_PUTFIELD;
 658             case REF_getStatic -> AF_GETSTATIC;
 659             case REF_putStatic -> AF_PUTSTATIC;
 660             default -> throw new InternalError(m.toString());
 661         };
 662         if (shouldBeInitialized(m)) {
 663             // precompute the barrier-free version:
 664             preparedFieldLambdaForm(formOp, isVolatile, ftype);
 665             assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
 666                    (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
 667             formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
 668         }
 669         LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
 670         maybeCompile(lform, m);
 671         assert(lform.methodType().dropParameterTypes(0, 1)
 672                 .equals(m.getInvocationType().basicType()))
 673                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 674         return lform;
 675     }
 676     private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, Class<?> ftype) {


 677         int ftypeKind = ftypeKind(ftype);
 678         int afIndex = afIndex(formOp, isVolatile, ftypeKind);
 679         LambdaForm lform = ACCESSOR_FORMS[afIndex];
 680         if (lform != null)  return lform;
 681         lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
 682         ACCESSOR_FORMS[afIndex] = lform;  // don't bother with a CAS
 683         return lform;
 684     }
 685 
 686     private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
 687 
 688     private static Kind getFieldKind(boolean isGetter, boolean isVolatile, Wrapper wrapper) {
 689         if (isGetter) {
 690             if (isVolatile) {
 691                 switch (wrapper) {
 692                     case BOOLEAN: return GET_BOOLEAN_VOLATILE;
 693                     case BYTE:    return GET_BYTE_VOLATILE;
 694                     case SHORT:   return GET_SHORT_VOLATILE;
 695                     case CHAR:    return GET_CHAR_VOLATILE;
 696                     case INT:     return GET_INT_VOLATILE;
 697                     case LONG:    return GET_LONG_VOLATILE;
 698                     case FLOAT:   return GET_FLOAT_VOLATILE;
 699                     case DOUBLE:  return GET_DOUBLE_VOLATILE;
 700                     case OBJECT:  return GET_REFERENCE_VOLATILE;
 701                 }
 702             } else {
 703                 switch (wrapper) {
 704                     case BOOLEAN: return GET_BOOLEAN;
 705                     case BYTE:    return GET_BYTE;
 706                     case SHORT:   return GET_SHORT;
 707                     case CHAR:    return GET_CHAR;
 708                     case INT:     return GET_INT;
 709                     case LONG:    return GET_LONG;
 710                     case FLOAT:   return GET_FLOAT;
 711                     case DOUBLE:  return GET_DOUBLE;
 712                     case OBJECT:  return GET_REFERENCE;
 713                 }
 714             }
 715         } else {
 716             if (isVolatile) {
 717                 switch (wrapper) {
 718                     case BOOLEAN: return PUT_BOOLEAN_VOLATILE;
 719                     case BYTE:    return PUT_BYTE_VOLATILE;
 720                     case SHORT:   return PUT_SHORT_VOLATILE;
 721                     case CHAR:    return PUT_CHAR_VOLATILE;
 722                     case INT:     return PUT_INT_VOLATILE;
 723                     case LONG:    return PUT_LONG_VOLATILE;
 724                     case FLOAT:   return PUT_FLOAT_VOLATILE;
 725                     case DOUBLE:  return PUT_DOUBLE_VOLATILE;
 726                     case OBJECT:  return PUT_REFERENCE_VOLATILE;
 727                 }
 728             } else {
 729                 switch (wrapper) {
 730                     case BOOLEAN: return PUT_BOOLEAN;
 731                     case BYTE:    return PUT_BYTE;
 732                     case SHORT:   return PUT_SHORT;
 733                     case CHAR:    return PUT_CHAR;
 734                     case INT:     return PUT_INT;
 735                     case LONG:    return PUT_LONG;
 736                     case FLOAT:   return PUT_FLOAT;
 737                     case DOUBLE:  return PUT_DOUBLE;
 738                     case OBJECT:  return PUT_REFERENCE;
 739                 }
 740             }
 741         }
 742         throw new AssertionError("Invalid arguments");
 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         Kind kind = getFieldKind(isGetter, isVolatile, fw);
 756 
 757         MethodType linkerType;
 758         if (isGetter)
 759             linkerType = MethodType.methodType(ft, Object.class, long.class);
 760         else
 761             linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);





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



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




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







 811         if (!isGetter) {
 812             outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
 813         }
 814         for (Object a : outArgs)  assert(a != null);
 815         names[LINKER_CALL] = new Name(linker, outArgs);
 816         if (needsCast && isGetter)
 817             names[POST_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[LINKER_CALL]);
 818         for (Name n : names)  assert(n != null);
 819 
 820         LambdaForm form;
 821         if (needsCast || needsInit) {
 822             // can't use the pre-generated form when casting and/or initializing
 823             form = LambdaForm.create(ARG_LIMIT, names, RESULT);
 824         } else {
 825             form = LambdaForm.create(ARG_LIMIT, names, RESULT, kind);
 826         }
 827 
 828         if (LambdaForm.debugNames()) {
 829             // add some detail to the lambdaForm debugname,
 830             // significant only for debugging
 831             StringBuilder nameBuilder = new StringBuilder(kind.methodName);
 832             if (isStatic) {

 843             LambdaForm.associateWithDebugName(form, nameBuilder.toString());
 844         }
 845         return form;
 846     }
 847 
 848     /**
 849      * Pre-initialized NamedFunctions for bootstrapping purposes.
 850      */
 851     static final byte NF_internalMemberName = 0,
 852             NF_internalMemberNameEnsureInit = 1,
 853             NF_ensureInitialized = 2,
 854             NF_fieldOffset = 3,
 855             NF_checkBase = 4,
 856             NF_staticBase = 5,
 857             NF_staticOffset = 6,
 858             NF_checkCast = 7,
 859             NF_allocateInstance = 8,
 860             NF_constructorMethod = 9,
 861             NF_UNSAFE = 10,
 862             NF_checkReceiver = 11,
 863             NF_LIMIT = 12;




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



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








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

 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;
 137         ctor = ctor.asConstructor();
 138         assert(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) {

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

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

 674         byte formOp = switch (m.getReferenceKind()) {
 675             case REF_getField  -> AF_GETFIELD;
 676             case REF_putField  -> AF_PUTFIELD;
 677             case REF_getStatic -> AF_GETSTATIC;
 678             case REF_putStatic -> AF_PUTSTATIC;
 679             default -> throw new InternalError(m.toString());
 680         };
 681         if (shouldBeInitialized(m)) {
 682             // precompute the barrier-free version:
 683             preparedFieldLambdaForm(formOp, m.isVolatile(), m.isFlat(), m.isNullRestricted(), ftype);
 684             assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
 685                    (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
 686             formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
 687         }
 688         LambdaForm lform = preparedFieldLambdaForm(formOp, m.isVolatile(), m.isFlat(), m.isNullRestricted(), ftype);
 689         maybeCompile(lform, m);
 690         assert(lform.methodType().dropParameterTypes(0, 1)
 691                 .equals(m.getInvocationType().basicType()))
 692                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 693         return lform;
 694     }
 695 
 696     private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile,
 697                                                       boolean isFlat, boolean isNullRestricted, Class<?> ftype) {
 698         int ftypeKind = ftypeKind(ftype);
 699         int afIndex = afIndex(formOp, isVolatile, isFlat, isNullRestricted, ftypeKind);
 700         LambdaForm lform = ACCESSOR_FORMS[afIndex];
 701         if (lform != null)  return lform;
 702         lform = makePreparedFieldLambdaForm(formOp, isVolatile,isFlat, isNullRestricted, ftypeKind);
 703         ACCESSOR_FORMS[afIndex] = lform;  // don't bother with a CAS
 704         return lform;
 705     }
 706 
 707     private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
 708 
 709     private static Kind getFieldKind(boolean isGetter, boolean isVolatile, boolean isFlat, Wrapper wrapper) {
 710         if (isGetter) {
 711             if (isVolatile) {
 712                 switch (wrapper) {
 713                     case BOOLEAN: return GET_BOOLEAN_VOLATILE;
 714                     case BYTE:    return GET_BYTE_VOLATILE;
 715                     case SHORT:   return GET_SHORT_VOLATILE;
 716                     case CHAR:    return GET_CHAR_VOLATILE;
 717                     case INT:     return GET_INT_VOLATILE;
 718                     case LONG:    return GET_LONG_VOLATILE;
 719                     case FLOAT:   return GET_FLOAT_VOLATILE;
 720                     case DOUBLE:  return GET_DOUBLE_VOLATILE;
 721                     case OBJECT:  return isFlat ? GET_FLAT_VALUE_VOLATILE : GET_REFERENCE_VOLATILE;
 722                 }
 723             } else {
 724                 switch (wrapper) {
 725                     case BOOLEAN: return GET_BOOLEAN;
 726                     case BYTE:    return GET_BYTE;
 727                     case SHORT:   return GET_SHORT;
 728                     case CHAR:    return GET_CHAR;
 729                     case INT:     return GET_INT;
 730                     case LONG:    return GET_LONG;
 731                     case FLOAT:   return GET_FLOAT;
 732                     case DOUBLE:  return GET_DOUBLE;
 733                     case OBJECT:  return isFlat ? GET_FLAT_VALUE : GET_REFERENCE;
 734                 }
 735             }
 736         } else {
 737             if (isVolatile) {
 738                 switch (wrapper) {
 739                     case BOOLEAN: return PUT_BOOLEAN_VOLATILE;
 740                     case BYTE:    return PUT_BYTE_VOLATILE;
 741                     case SHORT:   return PUT_SHORT_VOLATILE;
 742                     case CHAR:    return PUT_CHAR_VOLATILE;
 743                     case INT:     return PUT_INT_VOLATILE;
 744                     case LONG:    return PUT_LONG_VOLATILE;
 745                     case FLOAT:   return PUT_FLOAT_VOLATILE;
 746                     case DOUBLE:  return PUT_DOUBLE_VOLATILE;
 747                     case OBJECT:  return isFlat ? PUT_FLAT_VALUE_VOLATILE : PUT_REFERENCE_VOLATILE;
 748                 }
 749             } else {
 750                 switch (wrapper) {
 751                     case BOOLEAN: return PUT_BOOLEAN;
 752                     case BYTE:    return PUT_BYTE;
 753                     case SHORT:   return PUT_SHORT;
 754                     case CHAR:    return PUT_CHAR;
 755                     case INT:     return PUT_INT;
 756                     case LONG:    return PUT_LONG;
 757                     case FLOAT:   return PUT_FLOAT;
 758                     case DOUBLE:  return PUT_DOUBLE;
 759                     case OBJECT:  return isFlat ? PUT_FLAT_VALUE : PUT_REFERENCE;
 760                 }
 761             }
 762         }
 763         throw new AssertionError("Invalid arguments");
 764     }
 765 
 766     /** invoked by GenerateJLIClassesHelper */
 767     static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftype) {
 768         return makePreparedFieldLambdaForm(formOp, isVolatile, false, false, ftype);
 769     }
 770 
 771     private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile,
 772                                                           boolean isFlat, boolean isNullRestricted, int ftypeKind) {
 773         boolean isGetter  = (formOp & 1) == (AF_GETFIELD & 1);
 774         boolean isStatic  = (formOp >= AF_GETSTATIC);
 775         boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
 776         boolean needsCast = (ftypeKind == FT_CHECKED_REF || ftypeKind == FT_CHECKED_VALUE);
 777         Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]);
 778         Class<?> ft = fw.primitiveType();
 779         assert(needsCast ? true : ftypeKind(ft) == ftypeKind);
 780 
 781         // getObject, putIntVolatile, etc.
 782         Kind kind = getFieldKind(isGetter, isVolatile, isFlat, fw);
 783 
 784         MethodType linkerType;
 785         if (isGetter) {
 786             linkerType = isFlat
 787                             ? MethodType.methodType(ft, Object.class, long.class, int.class, Class.class)
 788                             : MethodType.methodType(ft, Object.class, long.class);
 789         } else {
 790             linkerType = isFlat
 791                             ? MethodType.methodType(void.class, Object.class, long.class, int.class, Class.class, ft)
 792                             : MethodType.methodType(void.class, Object.class, long.class, ft);
 793         }
 794         MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual);
 795         try {
 796             linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, LM_TRUSTED,
 797                                               NoSuchMethodException.class);
 798         } catch (ReflectiveOperationException ex) {
 799             throw newInternalError(ex);
 800         }
 801 
 802         // What is the external type of the lambda form?
 803         MethodType mtype;
 804         if (isGetter)
 805             mtype = MethodType.methodType(ft);
 806         else
 807             mtype = MethodType.methodType(void.class, ft);
 808         mtype = mtype.basicType();  // erase short to int, etc.
 809         if (!isStatic)
 810             mtype = mtype.insertParameterTypes(0, Object.class);
 811         final int DMH_THIS  = 0;
 812         final int ARG_BASE  = 1;
 813         final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
 814         // if this is for non-static access, the base pointer is stored at this index:
 815         final int OBJ_BASE  = isStatic ? -1 : ARG_BASE;
 816         // if this is for write access, the value to be written is stored at this index:
 817         final int SET_VALUE  = isGetter ? -1 : ARG_LIMIT - 1;
 818         int nameCursor = ARG_LIMIT;
 819         final int F_HOLDER  = (isStatic ? nameCursor++ : -1);  // static base if any
 820         final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
 821         final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
 822         final int U_HOLDER  = nameCursor++;  // UNSAFE holder
 823         final int INIT_BAR  = (needsInit ? nameCursor++ : -1);
 824         final int LAYOUT = (isFlat ? nameCursor++ : -1); // field must be instance
 825         final int VALUE_TYPE = (isFlat ? nameCursor++ : -1);
 826         final int NULL_CHECK  = (isNullRestricted && !isGetter ? nameCursor++ : -1);
 827         final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
 828         final int LINKER_CALL = nameCursor++;
 829         final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
 830         final int RESULT    = nameCursor-1;  // either the call, or the cast
 831         Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
 832         if (needsInit)
 833             names[INIT_BAR] = new Name(getFunction(NF_ensureInitialized), names[DMH_THIS]);
 834         if (!isGetter) {
 835             if (isNullRestricted)
 836                 names[NULL_CHECK] = new Name(getFunction(NF_nullCheck), names[SET_VALUE]);
 837             if (needsCast)
 838                 names[PRE_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[SET_VALUE]);
 839         }
 840         Object[] outArgs = new Object[1 + linkerType.parameterCount()];
 841         assert (outArgs.length == (isGetter ? 3 : 4) + (isFlat ? 2 : 0));
 842         outArgs[0] = names[U_HOLDER] = new Name(getFunction(NF_UNSAFE));
 843         if (isStatic) {
 844             outArgs[1] = names[F_HOLDER]  = new Name(getFunction(NF_staticBase), names[DMH_THIS]);
 845             outArgs[2] = names[F_OFFSET]  = new Name(getFunction(NF_staticOffset), names[DMH_THIS]);
 846         } else {
 847             outArgs[1] = names[OBJ_CHECK] = new Name(getFunction(NF_checkBase), names[OBJ_BASE]);
 848             outArgs[2] = names[F_OFFSET]  = new Name(getFunction(NF_fieldOffset), names[DMH_THIS]);
 849         }
 850         int x = 3;
 851         if (isFlat) {
 852             assert !isStatic : "static field is flat form requested";
 853             outArgs[x++] = names[LAYOUT] = new Name(getFunction(NF_fieldLayout), names[DMH_THIS]);
 854             outArgs[x++] = names[VALUE_TYPE] = isStatic ? new Name(getFunction(NF_staticFieldType), names[DMH_THIS])
 855                                                         : new Name(getFunction(NF_fieldType), names[DMH_THIS]);
 856         }
 857         if (!isGetter) {
 858             outArgs[x] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
 859         }
 860         for (Object a : outArgs)  assert(a != null);
 861         names[LINKER_CALL] = new Name(linker, outArgs);
 862         if (needsCast && isGetter)
 863             names[POST_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[LINKER_CALL]);
 864         for (Name n : names)  assert(n != null);
 865 
 866         LambdaForm form;
 867         if (needsCast || needsInit) {
 868             // can't use the pre-generated form when casting and/or initializing
 869             form = LambdaForm.create(ARG_LIMIT, names, RESULT);
 870         } else {
 871             form = LambdaForm.create(ARG_LIMIT, names, RESULT, kind);
 872         }
 873 
 874         if (LambdaForm.debugNames()) {
 875             // add some detail to the lambdaForm debugname,
 876             // significant only for debugging
 877             StringBuilder nameBuilder = new StringBuilder(kind.methodName);
 878             if (isStatic) {

 889             LambdaForm.associateWithDebugName(form, nameBuilder.toString());
 890         }
 891         return form;
 892     }
 893 
 894     /**
 895      * Pre-initialized NamedFunctions for bootstrapping purposes.
 896      */
 897     static final byte NF_internalMemberName = 0,
 898             NF_internalMemberNameEnsureInit = 1,
 899             NF_ensureInitialized = 2,
 900             NF_fieldOffset = 3,
 901             NF_checkBase = 4,
 902             NF_staticBase = 5,
 903             NF_staticOffset = 6,
 904             NF_checkCast = 7,
 905             NF_allocateInstance = 8,
 906             NF_constructorMethod = 9,
 907             NF_UNSAFE = 10,
 908             NF_checkReceiver = 11,
 909             NF_fieldType = 12,
 910             NF_staticFieldType = 13,
 911             NF_fieldLayout = 14,
 912             NF_nullCheck = 15,
 913             NF_LIMIT = 16;
 914 
 915     private static final @Stable NamedFunction[] NFS = new NamedFunction[NF_LIMIT];
 916 
 917     private static NamedFunction getFunction(byte func) {
 918         NamedFunction nf = NFS[func];
 919         if (nf != null) {
 920             return nf;
 921         }
 922         // Each nf must be statically invocable or we get tied up in our bootstraps.
 923         nf = NFS[func] = createFunction(func);
 924         assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf));
 925         return nf;
 926     }
 927 
 928     private static final MethodType CLS_OBJ_TYPE = MethodType.methodType(Class.class, Object.class);
 929     private static final MethodType INT_OBJ_TYPE = MethodType.methodType(int.class, Object.class);
 930 
 931     private static final MethodType OBJ_OBJ_TYPE = MethodType.methodType(Object.class, Object.class);
 932 
 933     private static final MethodType LONG_OBJ_TYPE = MethodType.methodType(long.class, Object.class);
 934 
 935     private static NamedFunction createFunction(byte func) {
 936         try {
 937             switch (func) {
 938                 case NF_internalMemberName:
 939                     return getNamedFunction("internalMemberName", OBJ_OBJ_TYPE);
 940                 case NF_internalMemberNameEnsureInit:
 941                     return getNamedFunction("internalMemberNameEnsureInit", OBJ_OBJ_TYPE);
 942                 case NF_ensureInitialized:
 943                     return getNamedFunction("ensureInitialized", MethodType.methodType(void.class, Object.class));
 944                 case NF_fieldOffset:
 945                     return getNamedFunction("fieldOffset", LONG_OBJ_TYPE);
 946                 case NF_checkBase:
 947                     return getNamedFunction("checkBase", OBJ_OBJ_TYPE);
 948                 case NF_staticBase:
 949                     return getNamedFunction("staticBase", OBJ_OBJ_TYPE);
 950                 case NF_staticOffset:
 951                     return getNamedFunction("staticOffset", LONG_OBJ_TYPE);
 952                 case NF_checkCast:
 953                     return getNamedFunction("checkCast", MethodType.methodType(Object.class, Object.class, Object.class));
 954                 case NF_allocateInstance:
 955                     return getNamedFunction("allocateInstance", OBJ_OBJ_TYPE);
 956                 case NF_constructorMethod:
 957                     return getNamedFunction("constructorMethod", OBJ_OBJ_TYPE);
 958                 case NF_UNSAFE:
 959                     MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getStatic);
 960                     return new NamedFunction(
 961                             MemberName.getFactory().resolveOrFail(REF_getStatic, member,
 962                                                                   DirectMethodHandle.class, LM_TRUSTED,
 963                                                                   NoSuchFieldException.class));
 964                 case NF_checkReceiver:
 965                     member = new MemberName(DirectMethodHandle.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual);
 966                     return new NamedFunction(
 967                             MemberName.getFactory().resolveOrFail(REF_invokeVirtual, member,
 968                                                                   DirectMethodHandle.class, LM_TRUSTED,
 969                                                                   NoSuchMethodException.class));
 970                 case NF_fieldType:
 971                     return getNamedFunction("fieldType", CLS_OBJ_TYPE);
 972                 case NF_staticFieldType:
 973                     return getNamedFunction("staticFieldType", CLS_OBJ_TYPE);
 974                 case NF_nullCheck:
 975                     return getNamedFunction("nullCheck", OBJ_OBJ_TYPE);
 976                 case NF_fieldLayout:
 977                     return getNamedFunction("fieldLayout", INT_OBJ_TYPE);
 978                 default:
 979                     throw newInternalError("Unknown function: " + func);
 980             }
 981         } catch (ReflectiveOperationException ex) {
 982             throw newInternalError(ex);
 983         }
 984     }
 985 
 986     private static NamedFunction getNamedFunction(String name, MethodType type)
 987         throws ReflectiveOperationException
 988     {
 989         MemberName member = new MemberName(DirectMethodHandle.class, name, type, REF_invokeStatic);
 990         return new NamedFunction(
 991                 MemberName.getFactory().resolveOrFail(REF_invokeStatic, member,
 992                                                       DirectMethodHandle.class, LM_TRUSTED,
 993                                                       NoSuchMethodException.class));
 994     }
 995 
 996     static {
 997         // The Holder class will contain pre-generated DirectMethodHandles resolved
< prev index next >