10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import jdk.internal.misc.CDS;
29 import jdk.internal.misc.Unsafe;
30 import jdk.internal.vm.annotation.ForceInline;
31 import jdk.internal.vm.annotation.Stable;
32 import sun.invoke.util.ValueConversions;
33 import sun.invoke.util.VerifyAccess;
34 import sun.invoke.util.Wrapper;
35
36 import java.util.Arrays;
37 import java.util.Objects;
38 import java.util.function.Function;
39
40 import static java.lang.invoke.LambdaForm.*;
41 import static java.lang.invoke.LambdaForm.Kind.*;
42 import static java.lang.invoke.MethodHandleNatives.Constants.*;
43 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
44 import static java.lang.invoke.MethodHandleStatics.newInternalError;
45 import static java.lang.invoke.MethodTypeForm.*;
46
47 /**
48 * The flavor of method handle which implements a constant reference
49 * to a class member.
116 return new StaticAccessor(mtype, lform, member, true, base, offset);
117 } else {
118 long offset = MethodHandleNatives.objectFieldOffset(member);
119 assert(offset == (int)offset);
120 return new Accessor(mtype, lform, member, true, (int)offset);
121 }
122 }
123 }
124 static DirectMethodHandle make(Class<?> refc, MemberName member) {
125 byte refKind = member.getReferenceKind();
126 if (refKind == REF_invokeSpecial)
127 refKind = REF_invokeVirtual;
128 return make(refKind, refc, member, null /* no callerClass context */);
129 }
130 static DirectMethodHandle make(MemberName member) {
131 if (member.isConstructor())
132 return makeAllocator(member.getDeclaringClass(), member);
133 return make(member.getDeclaringClass(), member);
134 }
135 static DirectMethodHandle makeAllocator(Class<?> instanceClass, MemberName ctor) {
136 assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
137 ctor = ctor.asConstructor();
138 assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
139 MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
140 LambdaForm lform = preparedLambdaForm(ctor);
141 MemberName init = ctor.asSpecial();
142 assert(init.getMethodType().returnType() == void.class);
143 return new Constructor(mtype, lform, ctor, true, init, instanceClass);
144 }
145
146 @Override
147 BoundMethodHandle rebind() {
148 return BoundMethodHandle.makeReinvoker(this);
149 }
150
151 @Override
152 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
153 assert(this.getClass() == DirectMethodHandle.class); // must override in subclasses
154 return new DirectMethodHandle(mt, lf, member, crackable);
155 }
156
157 @Override
158 MethodHandle viewAsType(MethodType newType, boolean strict) {
350 }
351 Class<?> cls = member.getDeclaringClass();
352 if (cls == ValueConversions.class ||
353 cls == MethodHandleImpl.class ||
354 cls == Invokers.class) {
355 // These guys have lots of <clinit> DMH creation but we know
356 // the MHs will not be used until the system is booted.
357 return false;
358 }
359 if (VerifyAccess.isSamePackage(MethodHandle.class, cls) ||
360 VerifyAccess.isSamePackage(ValueConversions.class, cls)) {
361 // It is a system class. It is probably in the process of
362 // being initialized, but we will help it along just to be safe.
363 UNSAFE.ensureClassInitialized(cls);
364 return CDS.needsClassInitBarrier(cls);
365 }
366 return UNSAFE.shouldBeInitialized(cls) || CDS.needsClassInitBarrier(cls);
367 }
368
369 private void ensureInitialized() {
370 if (checkInitialized(member)) {
371 // The coast is clear. Delete the <clinit> barrier.
372 updateForm(new Function<>() {
373 public LambdaForm apply(LambdaForm oldForm) {
374 return (member.isField() ? preparedFieldLambdaForm(member)
375 : preparedLambdaForm(member));
376 }
377 });
378 }
379 }
380 private static boolean checkInitialized(MemberName member) {
381 Class<?> defc = member.getDeclaringClass();
382 UNSAFE.ensureClassInitialized(defc);
383 // Once we get here either defc was fully initialized by another thread, or
384 // defc was already being initialized by the current thread. In the latter case
385 // the barrier must remain. We can detect this simply by checking if initialization
386 // is still needed.
387 return !UNSAFE.shouldBeInitialized(defc);
388 }
389
390 /*non-public*/
391 static void ensureInitialized(Object mh) {
392 ((DirectMethodHandle)mh).ensureInitialized();
393 }
394
395 /** This subclass represents invokespecial instructions. */
396 static final class Special extends DirectMethodHandle {
397 private final Class<?> caller;
398 private Special(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> caller) {
399 super(mtype, form, member, crackable);
400 this.caller = caller;
401 }
402 @Override
403 boolean isInvokeSpecial() {
404 return true;
405 }
406 @Override
407 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
487 return new Constructor(newType, form, member, false, initMethod, instanceClass);
488 }
489 }
490
491 /*non-public*/
492 static Object constructorMethod(Object mh) {
493 Constructor dmh = (Constructor)mh;
494 return dmh.initMethod;
495 }
496
497 /*non-public*/
498 static Object allocateInstance(Object mh) throws InstantiationException {
499 Constructor dmh = (Constructor)mh;
500 return UNSAFE.allocateInstance(dmh.instanceClass);
501 }
502
503 /** This subclass handles non-static field references. */
504 static final class Accessor extends DirectMethodHandle {
505 final Class<?> fieldType;
506 final int fieldOffset;
507 private Accessor(MethodType mtype, LambdaForm form, MemberName member,
508 boolean crackable, int fieldOffset) {
509 super(mtype, form, member, crackable);
510 this.fieldType = member.getFieldType();
511 this.fieldOffset = fieldOffset;
512 }
513
514 @Override Object checkCast(Object obj) {
515 return fieldType.cast(obj);
516 }
517 @Override
518 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
519 return new Accessor(mt, lf, member, crackable, fieldOffset);
520 }
521 @Override
522 MethodHandle viewAsType(MethodType newType, boolean strict) {
523 assert(viewAsTypeChecks(newType, strict));
524 return new Accessor(newType, form, member, false, fieldOffset);
525 }
526 }
527
528 @ForceInline
529 /*non-public*/
530 static long fieldOffset(Object accessorObj) {
531 // Note: We return a long because that is what Unsafe.getObject likes.
581 }
582
583 @ForceInline
584 /*non-public*/
585 static Object staticBase(Object accessorObj) {
586 return ((StaticAccessor)accessorObj).staticBase;
587 }
588
589 @ForceInline
590 /*non-public*/
591 static long staticOffset(Object accessorObj) {
592 return ((StaticAccessor)accessorObj).staticOffset;
593 }
594
595 @ForceInline
596 /*non-public*/
597 static Object checkCast(Object mh, Object obj) {
598 return ((DirectMethodHandle) mh).checkCast(obj);
599 }
600
601 Object checkCast(Object obj) {
602 return member.getMethodType().returnType().cast(obj);
603 }
604
605 // Caching machinery for field accessors:
606 static final byte
607 AF_GETFIELD = 0,
608 AF_PUTFIELD = 1,
609 AF_GETSTATIC = 2,
610 AF_PUTSTATIC = 3,
611 AF_GETSTATIC_INIT = 4,
612 AF_PUTSTATIC_INIT = 5,
613 AF_LIMIT = 6;
614 // Enumerate the different field kinds using Wrapper,
615 // with an extra case added for checked references.
616 static final int
617 FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(),
618 FT_CHECKED_REF = Wrapper.VOID.ordinal(),
619 FT_LIMIT = Wrapper.COUNT;
620 private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
621 return ((formOp * FT_LIMIT * 2)
622 + (isVolatile ? FT_LIMIT : 0)
623 + ftypeKind);
624 }
625 @Stable
626 private static final LambdaForm[] ACCESSOR_FORMS
627 = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
628 static int ftypeKind(Class<?> ftype) {
629 if (ftype.isPrimitive()) {
630 return Wrapper.forPrimitiveType(ftype).ordinal();
631 } else if (ftype.isInterface() || ftype.isAssignableFrom(Object.class)) {
632 // retyping can be done without a cast
633 return FT_UNCHECKED_REF;
634 } else {
635 return FT_CHECKED_REF;
636 }
637 }
638
639 /**
640 * Create a LF which can access the given field.
641 * Cache and share this structure among all fields with
642 * the same basicType and refKind.
643 */
644 private static LambdaForm preparedFieldLambdaForm(MemberName m) {
645 Class<?> ftype = m.getFieldType();
646 boolean isVolatile = m.isVolatile();
647 byte formOp = switch (m.getReferenceKind()) {
648 case REF_getField -> AF_GETFIELD;
649 case REF_putField -> AF_PUTFIELD;
650 case REF_getStatic -> AF_GETSTATIC;
651 case REF_putStatic -> AF_PUTSTATIC;
652 default -> throw new InternalError(m.toString());
653 };
654 if (shouldBeInitialized(m)) {
655 // precompute the barrier-free version:
656 preparedFieldLambdaForm(formOp, isVolatile, ftype);
657 assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
658 (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
659 formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
660 }
661 LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
662 assert(lform.methodType().dropParameterTypes(0, 1)
663 .equals(m.getInvocationType().basicType()))
664 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
665 return lform;
666 }
667 private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, Class<?> ftype) {
668 int ftypeKind = ftypeKind(ftype);
669 int afIndex = afIndex(formOp, isVolatile, ftypeKind);
670 LambdaForm lform = ACCESSOR_FORMS[afIndex];
671 if (lform != null) return lform;
672 lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
673 ACCESSOR_FORMS[afIndex] = lform; // don't bother with a CAS
674 return lform;
675 }
676
677 private static final @Stable Wrapper[] ALL_WRAPPERS = Wrapper.values();
678
679 // Names in kind may overload but differ from their basic type
680 private static Kind getFieldKind(boolean isVolatile, boolean needsInit, boolean needsCast, Wrapper wrapper) {
681 if (isVolatile) {
682 if (needsInit) {
683 return switch (wrapper) {
684 case BYTE -> VOLATILE_FIELD_ACCESS_INIT_B;
685 case CHAR -> VOLATILE_FIELD_ACCESS_INIT_C;
686 case SHORT -> VOLATILE_FIELD_ACCESS_INIT_S;
687 case BOOLEAN -> VOLATILE_FIELD_ACCESS_INIT_Z;
688 default -> needsCast ? VOLATILE_FIELD_ACCESS_INIT_CAST : VOLATILE_FIELD_ACCESS_INIT;
689 };
690 } else {
691 return switch (wrapper) {
692 case BYTE -> VOLATILE_FIELD_ACCESS_B;
693 case CHAR -> VOLATILE_FIELD_ACCESS_C;
694 case SHORT -> VOLATILE_FIELD_ACCESS_S;
695 case BOOLEAN -> VOLATILE_FIELD_ACCESS_Z;
696 default -> needsCast ? VOLATILE_FIELD_ACCESS_CAST : VOLATILE_FIELD_ACCESS;
697 };
698 }
699 } else {
700 if (needsInit) {
701 return switch (wrapper) {
702 case BYTE -> FIELD_ACCESS_INIT_B;
703 case CHAR -> FIELD_ACCESS_INIT_C;
704 case SHORT -> FIELD_ACCESS_INIT_S;
705 case BOOLEAN -> FIELD_ACCESS_INIT_Z;
706 default -> needsCast ? FIELD_ACCESS_INIT_CAST : FIELD_ACCESS_INIT;
707 };
708 } else {
709 return switch (wrapper) {
710 case BYTE -> FIELD_ACCESS_B;
711 case CHAR -> FIELD_ACCESS_C;
712 case SHORT -> FIELD_ACCESS_S;
713 case BOOLEAN -> FIELD_ACCESS_Z;
714 default -> needsCast ? FIELD_ACCESS_CAST : FIELD_ACCESS;
715 };
716 }
717 }
718 }
719
720 private static String unsafeMethodName(boolean isGetter, boolean isVolatile, Wrapper wrapper) {
721 var name = switch (wrapper) {
722 case BOOLEAN -> "Boolean";
723 case BYTE -> "Byte";
724 case CHAR -> "Char";
725 case SHORT -> "Short";
726 case INT -> "Int";
727 case FLOAT -> "Float";
728 case LONG -> "Long";
729 case DOUBLE -> "Double";
730 case OBJECT -> "Reference";
731 case VOID -> throw new InternalError();
732 };
733 var sb = new StringBuilder(3 + name.length() + (isVolatile ? 8 : 0))
734 .append(isGetter ? "get" : "put")
735 .append(name);
736 if (isVolatile) {
737 sb.append("Volatile");
738 }
739 return sb.toString();
740 }
741
742 static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
743 boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1);
744 boolean isStatic = (formOp >= AF_GETSTATIC);
745 boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
746 boolean needsCast = (ftypeKind == FT_CHECKED_REF);
747 Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]);
748 Class<?> ft = fw.primitiveType();
749 assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
750
751 // getObject, putIntVolatile, etc.
752 String unsafeMethodName = unsafeMethodName(isGetter, isVolatile, fw);
753 // isGetter and isStatic is reflected in field type; basic type clash for subwords
754 Kind kind = getFieldKind(isVolatile, needsInit, needsCast, fw);
755
756 MethodType linkerType;
757 if (isGetter)
758 linkerType = MethodType.methodType(ft, Object.class, long.class);
759 else
760 linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
761 MemberName linker = new MemberName(Unsafe.class, unsafeMethodName, linkerType, REF_invokeVirtual);
762 try {
763 linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, LM_TRUSTED,
764 NoSuchMethodException.class);
765 } catch (ReflectiveOperationException ex) {
766 throw newInternalError(ex);
767 }
768
769 // What is the external type of the lambda form?
770 MethodType mtype;
771 if (isGetter)
772 mtype = MethodType.methodType(ft);
773 else
774 mtype = MethodType.methodType(void.class, ft);
775 mtype = mtype.basicType(); // erase short to int, etc.
776 if (!isStatic)
777 mtype = mtype.insertParameterTypes(0, Object.class);
778 final int DMH_THIS = 0;
779 final int ARG_BASE = 1;
780 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
781 // if this is for non-static access, the base pointer is stored at this index:
782 final int OBJ_BASE = isStatic ? -1 : ARG_BASE;
783 // if this is for write access, the value to be written is stored at this index:
784 final int SET_VALUE = isGetter ? -1 : ARG_LIMIT - 1;
785 int nameCursor = ARG_LIMIT;
786 final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any
787 final int F_OFFSET = nameCursor++; // Either static offset or field offset.
788 final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
789 final int U_HOLDER = nameCursor++; // UNSAFE holder
790 final int INIT_BAR = (needsInit ? nameCursor++ : -1);
791 final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1);
792 final int LINKER_CALL = nameCursor++;
793 final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
794 final int RESULT = nameCursor-1; // either the call or the cast
795 Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
796 if (needsInit)
797 names[INIT_BAR] = new Name(getFunction(NF_ensureInitialized), names[DMH_THIS]);
798 if (needsCast && !isGetter)
799 names[PRE_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[SET_VALUE]);
800 Object[] outArgs = new Object[1 + linkerType.parameterCount()];
801 assert(outArgs.length == (isGetter ? 3 : 4));
802 outArgs[0] = names[U_HOLDER] = new Name(getFunction(NF_UNSAFE));
803 if (isStatic) {
804 outArgs[1] = names[F_HOLDER] = new Name(getFunction(NF_staticBase), names[DMH_THIS]);
805 outArgs[2] = names[F_OFFSET] = new Name(getFunction(NF_staticOffset), names[DMH_THIS]);
806 } else {
807 outArgs[1] = names[OBJ_CHECK] = new Name(getFunction(NF_checkBase), names[OBJ_BASE]);
808 outArgs[2] = names[F_OFFSET] = new Name(getFunction(NF_fieldOffset), names[DMH_THIS]);
809 }
810 if (!isGetter) {
811 outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
812 }
813 for (Object a : outArgs) assert(a != null);
814 names[LINKER_CALL] = new Name(linker, outArgs);
815 if (needsCast && isGetter)
816 names[POST_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[LINKER_CALL]);
817 for (Name n : names) assert(n != null);
818
819 LambdaForm form = LambdaForm.create(ARG_LIMIT, names, RESULT, kind);
820
821 if (LambdaForm.debugNames()) {
822 // add some detail to the lambdaForm debugname,
823 // significant only for debugging
824 StringBuilder nameBuilder = new StringBuilder(unsafeMethodName);
825 if (isStatic) {
826 nameBuilder.append("Static");
827 } else {
828 nameBuilder.append("Field");
829 }
830 if (needsCast) {
831 nameBuilder.append("Cast");
832 }
833 if (needsInit) {
834 nameBuilder.append("Init");
835 }
836 LambdaForm.associateWithDebugName(form, nameBuilder.toString());
837 }
838
839 // NF_UNSAFE uses field form, avoid circular dependency in interpreter
840 form.compileToBytecode();
841 return form;
842 }
843
844 /**
845 * Pre-initialized NamedFunctions for bootstrapping purposes.
846 */
847 static final byte NF_internalMemberName = 0,
848 NF_internalMemberNameEnsureInit = 1,
849 NF_ensureInitialized = 2,
850 NF_fieldOffset = 3,
851 NF_checkBase = 4,
852 NF_staticBase = 5,
853 NF_staticOffset = 6,
854 NF_checkCast = 7,
855 NF_allocateInstance = 8,
856 NF_constructorMethod = 9,
857 NF_UNSAFE = 10,
858 NF_checkReceiver = 11,
859 NF_LIMIT = 12;
860
861 private static final @Stable NamedFunction[] NFS = new NamedFunction[NF_LIMIT];
862
863 private static NamedFunction getFunction(byte func) {
864 NamedFunction nf = NFS[func];
865 if (nf != null) {
866 return nf;
867 }
868 // Each nf must be statically invocable or we get tied up in our bootstraps.
869 nf = NFS[func] = createFunction(func);
870 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf));
871 return nf;
872 }
873
874 private static final MethodType OBJ_OBJ_TYPE = MethodType.methodType(Object.class, Object.class);
875
876 private static final MethodType LONG_OBJ_TYPE = MethodType.methodType(long.class, Object.class);
877
878 private static NamedFunction createFunction(byte func) {
879 try {
880 switch (func) {
881 case NF_internalMemberName:
882 return getNamedFunction("internalMemberName", OBJ_OBJ_TYPE);
883 case NF_internalMemberNameEnsureInit:
884 return getNamedFunction("internalMemberNameEnsureInit", OBJ_OBJ_TYPE);
885 case NF_ensureInitialized:
886 return getNamedFunction("ensureInitialized", MethodType.methodType(void.class, Object.class));
887 case NF_fieldOffset:
888 return getNamedFunction("fieldOffset", LONG_OBJ_TYPE);
889 case NF_checkBase:
890 return getNamedFunction("checkBase", OBJ_OBJ_TYPE);
891 case NF_staticBase:
892 return getNamedFunction("staticBase", OBJ_OBJ_TYPE);
893 case NF_staticOffset:
894 return getNamedFunction("staticOffset", LONG_OBJ_TYPE);
895 case NF_checkCast:
896 return getNamedFunction("checkCast", MethodType.methodType(Object.class, Object.class, Object.class));
897 case NF_allocateInstance:
898 return getNamedFunction("allocateInstance", OBJ_OBJ_TYPE);
899 case NF_constructorMethod:
900 return getNamedFunction("constructorMethod", OBJ_OBJ_TYPE);
901 case NF_UNSAFE:
902 MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getStatic);
903 return new NamedFunction(
904 MemberName.getFactory().resolveOrFail(REF_getStatic, member,
905 DirectMethodHandle.class, LM_TRUSTED,
906 NoSuchFieldException.class));
907 case NF_checkReceiver:
908 member = new MemberName(DirectMethodHandle.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual);
909 return new NamedFunction(
910 MemberName.getFactory().resolveOrFail(REF_invokeVirtual, member,
911 DirectMethodHandle.class, LM_TRUSTED,
912 NoSuchMethodException.class));
913 default:
914 throw newInternalError("Unknown function: " + func);
915 }
916 } catch (ReflectiveOperationException ex) {
917 throw newInternalError(ex);
918 }
919 }
920
921 private static NamedFunction getNamedFunction(String name, MethodType type)
922 throws ReflectiveOperationException
923 {
924 MemberName member = new MemberName(DirectMethodHandle.class, name, type, REF_invokeStatic);
925 return new NamedFunction(
926 MemberName.getFactory().resolveOrFail(REF_invokeStatic, member,
927 DirectMethodHandle.class, LM_TRUSTED,
928 NoSuchMethodException.class));
929 }
930
931 static {
932 // The Holder class will contain pre-generated DirectMethodHandles resolved
|
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import jdk.internal.misc.CDS;
29 import jdk.internal.misc.Unsafe;
30 import jdk.internal.value.ValueClass;
31 import jdk.internal.vm.annotation.ForceInline;
32 import jdk.internal.vm.annotation.Stable;
33 import sun.invoke.util.ValueConversions;
34 import sun.invoke.util.VerifyAccess;
35 import sun.invoke.util.Wrapper;
36
37 import java.util.Arrays;
38 import java.util.Objects;
39 import java.util.function.Function;
40
41 import static java.lang.invoke.LambdaForm.*;
42 import static java.lang.invoke.LambdaForm.Kind.*;
43 import static java.lang.invoke.MethodHandleNatives.Constants.*;
44 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
45 import static java.lang.invoke.MethodHandleStatics.newInternalError;
46 import static java.lang.invoke.MethodTypeForm.*;
47
48 /**
49 * The flavor of method handle which implements a constant reference
50 * to a class member.
117 return new StaticAccessor(mtype, lform, member, true, base, offset);
118 } else {
119 long offset = MethodHandleNatives.objectFieldOffset(member);
120 assert(offset == (int)offset);
121 return new Accessor(mtype, lform, member, true, (int)offset);
122 }
123 }
124 }
125 static DirectMethodHandle make(Class<?> refc, MemberName member) {
126 byte refKind = member.getReferenceKind();
127 if (refKind == REF_invokeSpecial)
128 refKind = REF_invokeVirtual;
129 return make(refKind, refc, member, null /* no callerClass context */);
130 }
131 static DirectMethodHandle make(MemberName member) {
132 if (member.isConstructor())
133 return makeAllocator(member.getDeclaringClass(), member);
134 return make(member.getDeclaringClass(), member);
135 }
136 static DirectMethodHandle makeAllocator(Class<?> instanceClass, MemberName ctor) {
137 assert(ctor.isConstructor()) : ctor;
138 ctor = ctor.asConstructor();
139 assert(ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
140 MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
141 LambdaForm lform = preparedLambdaForm(ctor);
142 MemberName init = ctor.asSpecial();
143 assert(init.getMethodType().returnType() == void.class);
144 return new Constructor(mtype, lform, ctor, true, init, instanceClass);
145 }
146
147 @Override
148 BoundMethodHandle rebind() {
149 return BoundMethodHandle.makeReinvoker(this);
150 }
151
152 @Override
153 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
154 assert(this.getClass() == DirectMethodHandle.class); // must override in subclasses
155 return new DirectMethodHandle(mt, lf, member, crackable);
156 }
157
158 @Override
159 MethodHandle viewAsType(MethodType newType, boolean strict) {
351 }
352 Class<?> cls = member.getDeclaringClass();
353 if (cls == ValueConversions.class ||
354 cls == MethodHandleImpl.class ||
355 cls == Invokers.class) {
356 // These guys have lots of <clinit> DMH creation but we know
357 // the MHs will not be used until the system is booted.
358 return false;
359 }
360 if (VerifyAccess.isSamePackage(MethodHandle.class, cls) ||
361 VerifyAccess.isSamePackage(ValueConversions.class, cls)) {
362 // It is a system class. It is probably in the process of
363 // being initialized, but we will help it along just to be safe.
364 UNSAFE.ensureClassInitialized(cls);
365 return CDS.needsClassInitBarrier(cls);
366 }
367 return UNSAFE.shouldBeInitialized(cls) || CDS.needsClassInitBarrier(cls);
368 }
369
370 private void ensureInitialized() {
371 if (checkInitialized()) {
372 // The coast is clear. Delete the <clinit> barrier.
373 updateForm(new Function<>() {
374 public LambdaForm apply(LambdaForm oldForm) {
375 return (member.isField() ? preparedFieldLambdaForm(member)
376 : preparedLambdaForm(member));
377 }
378 });
379 }
380 }
381 private boolean checkInitialized() {
382 Class<?> defc = member.getDeclaringClass();
383 UNSAFE.ensureClassInitialized(defc);
384 // Once we get here either defc was fully initialized by another thread, or
385 // defc was already being initialized by the current thread. In the latter case
386 // the barrier must remain. We can detect this simply by checking if initialization
387 // is still needed.
388 boolean initializingStill = UNSAFE.shouldBeInitialized(defc);
389 if (initializingStill && member.isStrict()) {
390 // while <clinit> is running, we track access to strict static fields
391 UNSAFE.notifyStrictStaticAccess(defc, staticOffset(this), member.isSetter());
392 }
393 return !initializingStill;
394 }
395
396 /*non-public*/
397 static void ensureInitialized(Object mh) {
398 ((DirectMethodHandle)mh).ensureInitialized();
399 }
400
401 /** This subclass represents invokespecial instructions. */
402 static final class Special extends DirectMethodHandle {
403 private final Class<?> caller;
404 private Special(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> caller) {
405 super(mtype, form, member, crackable);
406 this.caller = caller;
407 }
408 @Override
409 boolean isInvokeSpecial() {
410 return true;
411 }
412 @Override
413 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
493 return new Constructor(newType, form, member, false, initMethod, instanceClass);
494 }
495 }
496
497 /*non-public*/
498 static Object constructorMethod(Object mh) {
499 Constructor dmh = (Constructor)mh;
500 return dmh.initMethod;
501 }
502
503 /*non-public*/
504 static Object allocateInstance(Object mh) throws InstantiationException {
505 Constructor dmh = (Constructor)mh;
506 return UNSAFE.allocateInstance(dmh.instanceClass);
507 }
508
509 /** This subclass handles non-static field references. */
510 static final class Accessor extends DirectMethodHandle {
511 final Class<?> fieldType;
512 final int fieldOffset;
513 final int layout;
514 private Accessor(MethodType mtype, LambdaForm form, MemberName member,
515 boolean crackable, int fieldOffset) {
516 super(mtype, form, member, crackable);
517 this.fieldType = member.getFieldType();
518 this.fieldOffset = fieldOffset;
519 this.layout = member.getLayout();
520 }
521
522 @Override Object checkCast(Object obj) {
523 return fieldType.cast(obj);
524 }
525 @Override
526 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
527 return new Accessor(mt, lf, member, crackable, fieldOffset);
528 }
529 @Override
530 MethodHandle viewAsType(MethodType newType, boolean strict) {
531 assert(viewAsTypeChecks(newType, strict));
532 return new Accessor(newType, form, member, false, fieldOffset);
533 }
534 }
535
536 @ForceInline
537 /*non-public*/
538 static long fieldOffset(Object accessorObj) {
539 // Note: We return a long because that is what Unsafe.getObject likes.
589 }
590
591 @ForceInline
592 /*non-public*/
593 static Object staticBase(Object accessorObj) {
594 return ((StaticAccessor)accessorObj).staticBase;
595 }
596
597 @ForceInline
598 /*non-public*/
599 static long staticOffset(Object accessorObj) {
600 return ((StaticAccessor)accessorObj).staticOffset;
601 }
602
603 @ForceInline
604 /*non-public*/
605 static Object checkCast(Object mh, Object obj) {
606 return ((DirectMethodHandle) mh).checkCast(obj);
607 }
608
609 @ForceInline
610 /*non-public*/ static Class<?> fieldType(Object accessorObj) {
611 return ((Accessor) accessorObj).fieldType;
612 }
613
614 @ForceInline
615 static int fieldLayout(Object accessorObj) {
616 return ((Accessor) accessorObj).layout;
617 }
618
619 @ForceInline
620 /*non-public*/ static Class<?> staticFieldType(Object accessorObj) {
621 return ((StaticAccessor) accessorObj).fieldType;
622 }
623
624 Object checkCast(Object obj) {
625 return member.getMethodType().returnType().cast(obj);
626 }
627
628 // Caching machinery for field accessors:
629 static final byte
630 AF_GETFIELD = 0,
631 AF_PUTFIELD = 1,
632 AF_GETSTATIC = 2,
633 AF_PUTSTATIC = 3,
634 AF_GETSTATIC_INIT = 4,
635 AF_PUTSTATIC_INIT = 5,
636 AF_LIMIT = 6;
637 // Enumerate the different field kinds using Wrapper,
638 // with an extra case added for checked references and value field access
639 static final int
640 FT_FIRST_REFERENCE = 8,
641 // Any oop, same sig (Runnable?)
642 FT_UNCHECKED_REF = FT_FIRST_REFERENCE,
643 // Oop with type checks (Number?)
644 FT_CHECKED_REF = FT_FIRST_REFERENCE + 1,
645 // Oop with null checks, (Runnable!)
646 FT_UNCHECKED_NR_REF = FT_FIRST_REFERENCE + 2,
647 // Oop with null and type checks, (Number!)
648 FT_CHECKED_NR_REF = FT_FIRST_REFERENCE + 3,
649 FT_FIRST_FLAT = FT_FIRST_REFERENCE + 4,
650 // nullable flat (must check type), (Integer?)
651 FT_NULLABLE_FLAT = FT_FIRST_FLAT,
652 // Null restricted flat (must check type), (Integer!)
653 FT_NR_FLAT = FT_FIRST_FLAT + 1,
654 FT_LIMIT = FT_FIRST_FLAT + 2;
655
656 static {
657 assert FT_FIRST_REFERENCE == Wrapper.OBJECT.ordinal();
658 }
659
660 private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
661 return ((formOp * FT_LIMIT * 2)
662 + (isVolatile ? FT_LIMIT : 0)
663 + ftypeKind);
664 }
665 @Stable
666 private static final LambdaForm[] ACCESSOR_FORMS
667 = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
668 static int ftypeKind(Class<?> ftype, boolean isFlat, boolean isNullRestricted) {
669 if (ftype.isPrimitive()) {
670 assert !isFlat && !isNullRestricted : ftype;
671 return Wrapper.forPrimitiveType(ftype).ordinal();
672 } else if (ftype.isInterface() || ftype.isAssignableFrom(Object.class)) {
673 assert !isFlat : ftype;
674 // retyping can be done without a cast
675 return isNullRestricted ? FT_UNCHECKED_NR_REF : FT_UNCHECKED_REF;
676 }
677 if (isFlat) {
678 assert ValueClass.isConcreteValueClass(ftype) : ftype;
679 return isNullRestricted ? FT_NR_FLAT : FT_NULLABLE_FLAT;
680 }
681 return isNullRestricted ? FT_CHECKED_NR_REF : FT_CHECKED_REF;
682 }
683
684 /**
685 * Create a LF which can access the given field.
686 * Cache and share this structure among all fields with
687 * the same basicType and refKind.
688 */
689 private static LambdaForm preparedFieldLambdaForm(MemberName m) {
690 Class<?> ftype = m.getFieldType();
691 byte formOp = switch (m.getReferenceKind()) {
692 case REF_getField -> AF_GETFIELD;
693 case REF_putField -> AF_PUTFIELD;
694 case REF_getStatic -> AF_GETSTATIC;
695 case REF_putStatic -> AF_PUTSTATIC;
696 default -> throw new InternalError(m.toString());
697 };
698 if (shouldBeInitialized(m)) {
699 // precompute the barrier-free version:
700 preparedFieldLambdaForm(formOp, m.isVolatile(), m.isFlat(), m.isNullRestricted(), ftype);
701 assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
702 (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
703 formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
704 }
705 LambdaForm lform = preparedFieldLambdaForm(formOp, m.isVolatile(), m.isFlat(), m.isNullRestricted(), ftype);
706 assert(lform.methodType().dropParameterTypes(0, 1)
707 .equals(m.getInvocationType().basicType()))
708 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
709 return lform;
710 }
711
712 private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile,
713 boolean isFlat, boolean isNullRestricted, Class<?> ftype) {
714 int ftypeKind = ftypeKind(ftype, isFlat, isNullRestricted);
715 return preparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
716 }
717
718 private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
719 int afIndex = afIndex(formOp, isVolatile, ftypeKind);
720 LambdaForm lform = ACCESSOR_FORMS[afIndex];
721 if (lform != null) return lform;
722 lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
723 ACCESSOR_FORMS[afIndex] = lform; // don't bother with a CAS
724 return lform;
725 }
726
727 private static final @Stable Wrapper[] ALL_WRAPPERS = Wrapper.values();
728
729 // Names in kind may overload but differ from their basic type
730 private static Kind getFieldKind(boolean isGetter,
731 boolean isVolatile,
732 boolean needsInit,
733 boolean needsCast,
734 boolean isFlat,
735 boolean isNullRestricted,
736 Wrapper wrapper) {
737 if (!wrapper.isOther()) {
738 // primitives
739 assert !isFlat && !isNullRestricted && !needsCast;
740 return switch (wrapper) {
741 case BYTE -> isVolatile
742 ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_B : VOLATILE_FIELD_ACCESS_B)
743 : (needsInit ? FIELD_ACCESS_INIT_B : FIELD_ACCESS_B);
744 case CHAR -> isVolatile
745 ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_C : VOLATILE_FIELD_ACCESS_C)
746 : (needsInit ? FIELD_ACCESS_INIT_C : FIELD_ACCESS_C);
747 case SHORT -> isVolatile
748 ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_S : VOLATILE_FIELD_ACCESS_S)
749 : (needsInit ? FIELD_ACCESS_INIT_S : FIELD_ACCESS_S);
750 case BOOLEAN -> isVolatile
751 ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_Z : VOLATILE_FIELD_ACCESS_Z)
752 : (needsInit ? FIELD_ACCESS_INIT_Z : FIELD_ACCESS_Z);
753 // basic types
754 default -> isVolatile
755 ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT : VOLATILE_FIELD_ACCESS)
756 : (needsInit ? FIELD_ACCESS_INIT : FIELD_ACCESS);
757 };
758 }
759
760 assert !(isGetter && isNullRestricted);
761 if (isVolatile) {
762 if (isFlat) {
763 assert !needsInit && needsCast;
764 return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_FLAT_VALUE : VOLATILE_FIELD_ACCESS_FLAT;
765 } else if (needsCast) {
766 if (needsInit) {
767 return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE_CAST_INIT : VOLATILE_FIELD_ACCESS_INIT_CAST;
768 } else {
769 return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE_CAST : VOLATILE_FIELD_ACCESS_CAST;
770 }
771 } else {
772 if (needsInit) {
773 return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE_INIT : VOLATILE_FIELD_ACCESS_INIT;
774 } else {
775 return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE : VOLATILE_FIELD_ACCESS;
776 }
777 }
778 } else {
779 if (isFlat) {
780 assert !needsInit && needsCast;
781 return isNullRestricted ? PUT_NULL_RESTRICTED_FLAT_VALUE : FIELD_ACCESS_FLAT;
782 } else if (needsCast) {
783 if (needsInit) {
784 return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_CAST_INIT : FIELD_ACCESS_INIT_CAST;
785 } else {
786 return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_CAST : FIELD_ACCESS_CAST;
787 }
788 } else {
789 if (needsInit) {
790 return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_INIT : FIELD_ACCESS_INIT;
791 } else {
792 return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE : FIELD_ACCESS;
793 }
794 }
795 }
796 }
797
798 private static String unsafeMethodName(boolean isGetter,
799 boolean isVolatile,
800 Wrapper wrapper) {
801 var name = switch (wrapper) {
802 case BOOLEAN -> "Boolean";
803 case BYTE -> "Byte";
804 case CHAR -> "Char";
805 case SHORT -> "Short";
806 case INT -> "Int";
807 case FLOAT -> "Float";
808 case LONG -> "Long";
809 case DOUBLE -> "Double";
810 case OBJECT -> "Reference";
811 case VOID -> "FlatValue";
812 };
813 var sb = new StringBuilder(3 + name.length() + (isVolatile ? 8 : 0))
814 .append(isGetter ? "get" : "put")
815 .append(name);
816 if (isVolatile) {
817 sb.append("Volatile");
818 }
819 return sb.toString();
820 }
821
822 static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
823 boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1);
824 boolean isStatic = (formOp >= AF_GETSTATIC);
825 boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
826 boolean isFlat = (ftypeKind >= FT_FIRST_FLAT);
827 boolean isNullRestricted = (ftypeKind == FT_NR_FLAT || ftypeKind == FT_CHECKED_NR_REF || ftypeKind == FT_UNCHECKED_NR_REF);
828 boolean needsCast = (isFlat || ftypeKind == FT_CHECKED_REF || ftypeKind == FT_CHECKED_NR_REF);
829
830 if (isGetter && isNullRestricted) {
831 int newKind = switch (ftypeKind) {
832 case FT_NR_FLAT -> FT_NULLABLE_FLAT;
833 case FT_CHECKED_NR_REF -> FT_CHECKED_REF;
834 case FT_UNCHECKED_NR_REF -> FT_UNCHECKED_REF;
835 default -> throw new InternalError();
836 };
837 return preparedFieldLambdaForm(formOp, isVolatile, newKind);
838 }
839
840 if (isFlat && isStatic)
841 throw new InternalError("Static flat not supported yet");
842
843 // primitives, reference, and void for flat
844 Wrapper fw = ftypeKind < FT_FIRST_REFERENCE ? ALL_WRAPPERS[ftypeKind] :
845 isFlat ? Wrapper.VOID : Wrapper.OBJECT;
846
847 // getObject, putIntVolatile, etc.
848 String unsafeMethodName = unsafeMethodName(isGetter, isVolatile, fw);
849 // isGetter and isStatic is reflected in field type;
850 // flat, NR distinguished
851 // basic type clash for subwords
852 Kind kind = getFieldKind(isGetter, isVolatile, needsInit, needsCast, isFlat, isNullRestricted, fw);
853
854 Class<?> ft = ftypeKind < FT_FIRST_REFERENCE ? fw.primitiveType() : Object.class;
855 MethodType linkerType;
856 if (isGetter) {
857 linkerType = isFlat
858 ? MethodType.methodType(ft, Object.class, long.class, int.class, Class.class)
859 : MethodType.methodType(ft, Object.class, long.class);
860 } else {
861 linkerType = isFlat
862 ? MethodType.methodType(void.class, Object.class, long.class, int.class, Class.class, ft)
863 : MethodType.methodType(void.class, Object.class, long.class, ft);
864 }
865 MemberName linker = new MemberName(Unsafe.class, unsafeMethodName, linkerType, REF_invokeVirtual);
866 try {
867 linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, LM_TRUSTED,
868 NoSuchMethodException.class);
869 } catch (ReflectiveOperationException ex) {
870 throw newInternalError(ex);
871 }
872
873 // What is the external type of the lambda form?
874 MethodType mtype;
875 if (isGetter)
876 mtype = MethodType.methodType(ft);
877 else
878 mtype = MethodType.methodType(void.class, ft);
879 mtype = mtype.basicType(); // erase short to int, etc.
880 if (!isStatic)
881 mtype = mtype.insertParameterTypes(0, Object.class);
882 final int DMH_THIS = 0;
883 final int ARG_BASE = 1;
884 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
885 // if this is for non-static access, the base pointer is stored at this index:
886 final int OBJ_BASE = isStatic ? -1 : ARG_BASE;
887 // if this is for write access, the value to be written is stored at this index:
888 final int SET_VALUE = isGetter ? -1 : ARG_LIMIT - 1;
889 int nameCursor = ARG_LIMIT;
890 final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any
891 final int F_OFFSET = nameCursor++; // Either static offset or field offset.
892 final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
893 final int U_HOLDER = nameCursor++; // UNSAFE holder
894 final int INIT_BAR = (needsInit ? nameCursor++ : -1);
895 final int LAYOUT = (isFlat ? nameCursor++ : -1); // field must be instance
896 final int VALUE_TYPE = (isFlat ? nameCursor++ : -1);
897 final int NULL_CHECK = (isNullRestricted && !isGetter ? nameCursor++ : -1);
898 final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1);
899 final int LINKER_CALL = nameCursor++;
900 final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
901 final int RESULT = nameCursor-1; // either the call, or the cast
902 Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
903 if (needsInit)
904 names[INIT_BAR] = new Name(getFunction(NF_ensureInitialized), names[DMH_THIS]);
905 if (!isGetter) {
906 if (isNullRestricted)
907 names[NULL_CHECK] = new Name(getFunction(NF_nullCheck), names[SET_VALUE]);
908 if (needsCast)
909 names[PRE_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[SET_VALUE]);
910 }
911 Object[] outArgs = new Object[1 + linkerType.parameterCount()];
912 assert (outArgs.length == (isGetter ? 3 : 4) + (isFlat ? 2 : 0));
913 outArgs[0] = names[U_HOLDER] = new Name(getFunction(NF_UNSAFE));
914 if (isStatic) {
915 outArgs[1] = names[F_HOLDER] = new Name(getFunction(NF_staticBase), names[DMH_THIS]);
916 outArgs[2] = names[F_OFFSET] = new Name(getFunction(NF_staticOffset), names[DMH_THIS]);
917 } else {
918 outArgs[1] = names[OBJ_CHECK] = new Name(getFunction(NF_checkBase), names[OBJ_BASE]);
919 outArgs[2] = names[F_OFFSET] = new Name(getFunction(NF_fieldOffset), names[DMH_THIS]);
920 }
921 int x = 3;
922 if (isFlat) {
923 outArgs[x++] = names[LAYOUT] = new Name(getFunction(NF_fieldLayout), names[DMH_THIS]);
924 outArgs[x++] = names[VALUE_TYPE] = isStatic ? new Name(getFunction(NF_staticFieldType), names[DMH_THIS])
925 : new Name(getFunction(NF_fieldType), names[DMH_THIS]);
926 }
927 if (!isGetter) {
928 outArgs[x] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
929 }
930 for (Object a : outArgs) assert(a != null);
931 names[LINKER_CALL] = new Name(linker, outArgs);
932 if (needsCast && isGetter)
933 names[POST_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[LINKER_CALL]);
934 for (Name n : names) assert(n != null);
935
936 LambdaForm form = LambdaForm.create(ARG_LIMIT, names, RESULT, kind);
937
938 if (LambdaForm.debugNames()) {
939 // add some detail to the lambdaForm debugname,
940 // significant only for debugging
941 StringBuilder nameBuilder = new StringBuilder(unsafeMethodName);
942 if (isStatic) {
943 nameBuilder.append("Static");
944 } else {
945 nameBuilder.append("Field");
946 }
947 if (isNullRestricted) {
948 nameBuilder.append("NullRestricted");
949 }
950 if (needsCast) {
951 nameBuilder.append("Cast");
952 }
953 if (needsInit) {
954 nameBuilder.append("Init");
955 }
956 LambdaForm.associateWithDebugName(form, nameBuilder.toString());
957 }
958
959 // NF_UNSAFE uses field form, avoid circular dependency in interpreter
960 form.compileToBytecode();
961 return form;
962 }
963
964 /**
965 * Pre-initialized NamedFunctions for bootstrapping purposes.
966 */
967 static final byte NF_internalMemberName = 0,
968 NF_internalMemberNameEnsureInit = 1,
969 NF_ensureInitialized = 2,
970 NF_fieldOffset = 3,
971 NF_checkBase = 4,
972 NF_staticBase = 5,
973 NF_staticOffset = 6,
974 NF_checkCast = 7,
975 NF_allocateInstance = 8,
976 NF_constructorMethod = 9,
977 NF_UNSAFE = 10,
978 NF_checkReceiver = 11,
979 NF_fieldType = 12,
980 NF_staticFieldType = 13,
981 NF_fieldLayout = 14,
982 NF_nullCheck = 15,
983 NF_LIMIT = 16;
984
985 private static final @Stable NamedFunction[] NFS = new NamedFunction[NF_LIMIT];
986
987 private static NamedFunction getFunction(byte func) {
988 NamedFunction nf = NFS[func];
989 if (nf != null) {
990 return nf;
991 }
992 // Each nf must be statically invocable or we get tied up in our bootstraps.
993 nf = NFS[func] = createFunction(func);
994 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf));
995 return nf;
996 }
997
998 private static final MethodType CLS_OBJ_TYPE = MethodType.methodType(Class.class, Object.class);
999 private static final MethodType INT_OBJ_TYPE = MethodType.methodType(int.class, Object.class);
1000
1001 private static final MethodType OBJ_OBJ_TYPE = MethodType.methodType(Object.class, Object.class);
1002
1003 private static final MethodType LONG_OBJ_TYPE = MethodType.methodType(long.class, Object.class);
1004
1005 private static NamedFunction createFunction(byte func) {
1006 try {
1007 switch (func) {
1008 case NF_internalMemberName:
1009 return getNamedFunction("internalMemberName", OBJ_OBJ_TYPE);
1010 case NF_internalMemberNameEnsureInit:
1011 return getNamedFunction("internalMemberNameEnsureInit", OBJ_OBJ_TYPE);
1012 case NF_ensureInitialized:
1013 return getNamedFunction("ensureInitialized", MethodType.methodType(void.class, Object.class));
1014 case NF_fieldOffset:
1015 return getNamedFunction("fieldOffset", LONG_OBJ_TYPE);
1016 case NF_checkBase:
1017 return getNamedFunction("checkBase", OBJ_OBJ_TYPE);
1018 case NF_staticBase:
1019 return getNamedFunction("staticBase", OBJ_OBJ_TYPE);
1020 case NF_staticOffset:
1021 return getNamedFunction("staticOffset", LONG_OBJ_TYPE);
1022 case NF_checkCast:
1023 return getNamedFunction("checkCast", MethodType.methodType(Object.class, Object.class, Object.class));
1024 case NF_allocateInstance:
1025 return getNamedFunction("allocateInstance", OBJ_OBJ_TYPE);
1026 case NF_constructorMethod:
1027 return getNamedFunction("constructorMethod", OBJ_OBJ_TYPE);
1028 case NF_UNSAFE:
1029 MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getStatic);
1030 return new NamedFunction(
1031 MemberName.getFactory().resolveOrFail(REF_getStatic, member,
1032 DirectMethodHandle.class, LM_TRUSTED,
1033 NoSuchFieldException.class));
1034 case NF_checkReceiver:
1035 member = new MemberName(DirectMethodHandle.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual);
1036 return new NamedFunction(
1037 MemberName.getFactory().resolveOrFail(REF_invokeVirtual, member,
1038 DirectMethodHandle.class, LM_TRUSTED,
1039 NoSuchMethodException.class));
1040 case NF_fieldType:
1041 return getNamedFunction("fieldType", CLS_OBJ_TYPE);
1042 case NF_staticFieldType:
1043 return getNamedFunction("staticFieldType", CLS_OBJ_TYPE);
1044 case NF_nullCheck:
1045 return getNamedFunction("nullCheck", OBJ_OBJ_TYPE);
1046 case NF_fieldLayout:
1047 return getNamedFunction("fieldLayout", INT_OBJ_TYPE);
1048 default:
1049 throw newInternalError("Unknown function: " + func);
1050 }
1051 } catch (ReflectiveOperationException ex) {
1052 throw newInternalError(ex);
1053 }
1054 }
1055
1056 private static NamedFunction getNamedFunction(String name, MethodType type)
1057 throws ReflectiveOperationException
1058 {
1059 MemberName member = new MemberName(DirectMethodHandle.class, name, type, REF_invokeStatic);
1060 return new NamedFunction(
1061 MemberName.getFactory().resolveOrFail(REF_invokeStatic, member,
1062 DirectMethodHandle.class, LM_TRUSTED,
1063 NoSuchMethodException.class));
1064 }
1065
1066 static {
1067 // The Holder class will contain pre-generated DirectMethodHandles resolved
|