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
|