470 @ForceInline
471 /*non-public*/ static Object nullCheck(Object obj) {
472 return Objects.requireNonNull(obj);
473 }
474
475 @ForceInline
476 /*non-public*/ static Object staticBase(Object accessorObj) {
477 return ((StaticAccessor)accessorObj).staticBase;
478 }
479
480 @ForceInline
481 /*non-public*/ static long staticOffset(Object accessorObj) {
482 return ((StaticAccessor)accessorObj).staticOffset;
483 }
484
485 @ForceInline
486 /*non-public*/ static Object checkCast(Object mh, Object obj) {
487 return ((DirectMethodHandle) mh).checkCast(obj);
488 }
489
490 Object checkCast(Object obj) {
491 return member.getReturnType().cast(obj);
492 }
493
494 // Caching machinery for field accessors:
495 private static final byte
496 AF_GETFIELD = 0,
497 AF_PUTFIELD = 1,
498 AF_GETSTATIC = 2,
499 AF_PUTSTATIC = 3,
500 AF_GETSTATIC_INIT = 4,
501 AF_PUTSTATIC_INIT = 5,
502 AF_LIMIT = 6;
503 // Enumerate the different field kinds using Wrapper,
504 // with an extra case added for checked references.
505 private static final int
506 FT_LAST_WRAPPER = Wrapper.COUNT-1,
507 FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(),
508 FT_CHECKED_REF = FT_LAST_WRAPPER+1,
509 FT_LIMIT = FT_LAST_WRAPPER+2;
510 private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
511 return ((formOp * FT_LIMIT * 2)
512 + (isVolatile ? FT_LIMIT : 0)
513 + ftypeKind);
514 }
515 @Stable
516 private static final LambdaForm[] ACCESSOR_FORMS
517 = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
518 private static int ftypeKind(Class<?> ftype) {
519 if (ftype.isPrimitive())
520 return Wrapper.forPrimitiveType(ftype).ordinal();
521 else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
522 return FT_UNCHECKED_REF;
523 else
524 return FT_CHECKED_REF;
525 }
526
527 /**
528 * Create a LF which can access the given field.
529 * Cache and share this structure among all fields with
530 * the same basicType and refKind.
531 */
532 private static LambdaForm preparedFieldLambdaForm(MemberName m) {
533 Class<?> ftype = m.getFieldType();
534 boolean isVolatile = m.isVolatile();
535 byte formOp;
536 switch (m.getReferenceKind()) {
537 case REF_getField: formOp = AF_GETFIELD; break;
538 case REF_putField: formOp = AF_PUTFIELD; break;
549 }
550 LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
551 maybeCompile(lform, m);
552 assert(lform.methodType().dropParameterTypes(0, 1)
553 .equals(m.getInvocationType().basicType()))
554 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
555 return lform;
556 }
557 private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, Class<?> ftype) {
558 int ftypeKind = ftypeKind(ftype);
559 int afIndex = afIndex(formOp, isVolatile, ftypeKind);
560 LambdaForm lform = ACCESSOR_FORMS[afIndex];
561 if (lform != null) return lform;
562 lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
563 ACCESSOR_FORMS[afIndex] = lform; // don't bother with a CAS
564 return lform;
565 }
566
567 private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
568
569 private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
570 boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1);
571 boolean isStatic = (formOp >= AF_GETSTATIC);
572 boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
573 boolean needsCast = (ftypeKind == FT_CHECKED_REF);
574 Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]);
575 Class<?> ft = fw.primitiveType();
576 assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
577
578 // getObject, putIntVolatile, etc.
579 StringBuilder nameBuilder = new StringBuilder();
580 if (isGetter) {
581 nameBuilder.append("get");
582 } else {
583 nameBuilder.append("put");
584 }
585 nameBuilder.append(fw.primitiveSimpleName());
586 nameBuilder.setCharAt(3, Character.toUpperCase(nameBuilder.charAt(3)));
587 if (isVolatile) {
588 nameBuilder.append("Volatile");
589 }
590
591 MethodType linkerType;
592 if (isGetter)
593 linkerType = MethodType.methodType(ft, Object.class, long.class);
594 else
595 linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
596 MemberName linker = new MemberName(Unsafe.class, nameBuilder.toString(), linkerType, REF_invokeVirtual);
597 try {
598 linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
599 } catch (ReflectiveOperationException ex) {
600 throw newInternalError(ex);
601 }
602
603 // What is the external type of the lambda form?
604 MethodType mtype;
605 if (isGetter)
606 mtype = MethodType.methodType(ft);
607 else
608 mtype = MethodType.methodType(void.class, ft);
609 mtype = mtype.basicType(); // erase short to int, etc.
610 if (!isStatic)
611 mtype = mtype.insertParameterTypes(0, Object.class);
612 final int DMH_THIS = 0;
613 final int ARG_BASE = 1;
614 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
615 // if this is for non-static access, the base pointer is stored at this index:
616 final int OBJ_BASE = isStatic ? -1 : ARG_BASE;
617 // if this is for write access, the value to be written is stored at this index:
618 final int SET_VALUE = isGetter ? -1 : ARG_LIMIT - 1;
619 int nameCursor = ARG_LIMIT;
620 final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any
621 final int F_OFFSET = nameCursor++; // Either static offset or field offset.
622 final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
623 final int INIT_BAR = (needsInit ? nameCursor++ : -1);
624 final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1);
625 final int LINKER_CALL = nameCursor++;
626 final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
627 final int RESULT = nameCursor-1; // either the call or the cast
628 Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
629 if (needsInit)
630 names[INIT_BAR] = new Name(NF_ensureInitialized, names[DMH_THIS]);
631 if (needsCast && !isGetter)
632 names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
633 Object[] outArgs = new Object[1 + linkerType.parameterCount()];
634 assert(outArgs.length == (isGetter ? 3 : 4));
635 outArgs[0] = UNSAFE;
636 if (isStatic) {
637 outArgs[1] = names[F_HOLDER] = new Name(NF_staticBase, names[DMH_THIS]);
638 outArgs[2] = names[F_OFFSET] = new Name(NF_staticOffset, names[DMH_THIS]);
639 } else {
640 outArgs[1] = names[OBJ_CHECK] = new Name(NF_checkBase, names[OBJ_BASE]);
641 outArgs[2] = names[F_OFFSET] = new Name(NF_fieldOffset, names[DMH_THIS]);
642 }
643 if (!isGetter) {
644 outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
645 }
646 for (Object a : outArgs) assert(a != null);
647 names[LINKER_CALL] = new Name(linker, outArgs);
648 if (needsCast && isGetter)
649 names[POST_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
650 for (Name n : names) assert(n != null);
651 // add some detail to the lambdaForm debugname,
652 // significant only for debugging
653 if (isStatic) {
654 nameBuilder.append("Static");
655 } else {
656 nameBuilder.append("Field");
657 }
658 if (needsCast) nameBuilder.append("Cast");
659 if (needsInit) nameBuilder.append("Init");
660 return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
661 }
662
663 /**
664 * Pre-initialized NamedFunctions for bootstrapping purposes.
665 * Factored in an inner class to delay initialization until first usage.
666 */
667 static final NamedFunction
668 NF_internalMemberName,
669 NF_internalMemberNameEnsureInit,
670 NF_ensureInitialized,
671 NF_fieldOffset,
672 NF_checkBase,
673 NF_staticBase,
674 NF_staticOffset,
675 NF_checkCast,
676 NF_allocateInstance,
677 NF_constructorMethod;
678 static {
679 try {
680 NamedFunction nfs[] = {
681 NF_internalMemberName = new NamedFunction(DirectMethodHandle.class
682 .getDeclaredMethod("internalMemberName", Object.class)),
683 NF_internalMemberNameEnsureInit = new NamedFunction(DirectMethodHandle.class
684 .getDeclaredMethod("internalMemberNameEnsureInit", Object.class)),
685 NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class
686 .getDeclaredMethod("ensureInitialized", Object.class)),
687 NF_fieldOffset = new NamedFunction(DirectMethodHandle.class
688 .getDeclaredMethod("fieldOffset", Object.class)),
689 NF_checkBase = new NamedFunction(DirectMethodHandle.class
690 .getDeclaredMethod("checkBase", Object.class)),
691 NF_staticBase = new NamedFunction(DirectMethodHandle.class
692 .getDeclaredMethod("staticBase", Object.class)),
693 NF_staticOffset = new NamedFunction(DirectMethodHandle.class
694 .getDeclaredMethod("staticOffset", Object.class)),
695 NF_checkCast = new NamedFunction(DirectMethodHandle.class
696 .getDeclaredMethod("checkCast", Object.class, Object.class)),
697 NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
698 .getDeclaredMethod("allocateInstance", Object.class)),
699 NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
700 .getDeclaredMethod("constructorMethod", Object.class))
701 };
702 // Each nf must be statically invocable or we get tied up in our bootstraps.
703 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
704 } catch (ReflectiveOperationException ex) {
705 throw newInternalError(ex);
706 }
707 }
708
709 static {
710 // The Holder class will contain pre-generated DirectMethodHandles resolved
711 // speculatively using MemberName.getFactory().resolveOrNull. However, that
712 // doesn't initialize the class, which subtly breaks inlining etc. By forcing
713 // initialization of the Holder class we avoid these issues.
714 UNSAFE.ensureClassInitialized(Holder.class);
715 }
716
717 /* Placeholder class for DirectMethodHandles generated ahead of time */
718 final class Holder {}
719 }
|
470 @ForceInline
471 /*non-public*/ static Object nullCheck(Object obj) {
472 return Objects.requireNonNull(obj);
473 }
474
475 @ForceInline
476 /*non-public*/ static Object staticBase(Object accessorObj) {
477 return ((StaticAccessor)accessorObj).staticBase;
478 }
479
480 @ForceInline
481 /*non-public*/ static long staticOffset(Object accessorObj) {
482 return ((StaticAccessor)accessorObj).staticOffset;
483 }
484
485 @ForceInline
486 /*non-public*/ static Object checkCast(Object mh, Object obj) {
487 return ((DirectMethodHandle) mh).checkCast(obj);
488 }
489
490 @ForceInline
491 /*non-public*/ static Unsafe unsafe() {
492 return UNSAFE;
493 }
494
495 Object checkCast(Object obj) {
496 return member.getReturnType().cast(obj);
497 }
498
499 // Caching machinery for field accessors:
500 static final byte
501 AF_GETFIELD = 0,
502 AF_PUTFIELD = 1,
503 AF_GETSTATIC = 2,
504 AF_PUTSTATIC = 3,
505 AF_GETSTATIC_INIT = 4,
506 AF_PUTSTATIC_INIT = 5,
507 AF_LIMIT = 6;
508 // Enumerate the different field kinds using Wrapper,
509 // with an extra case added for checked references.
510 static final int
511 FT_LAST_WRAPPER = Wrapper.COUNT-1,
512 FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(),
513 FT_CHECKED_REF = FT_LAST_WRAPPER+1,
514 FT_LIMIT = FT_LAST_WRAPPER+2;
515 private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
516 return ((formOp * FT_LIMIT * 2)
517 + (isVolatile ? FT_LIMIT : 0)
518 + ftypeKind);
519 }
520 @Stable
521 private static final LambdaForm[] ACCESSOR_FORMS
522 = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
523 static int ftypeKind(Class<?> ftype) {
524 if (ftype.isPrimitive())
525 return Wrapper.forPrimitiveType(ftype).ordinal();
526 else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
527 return FT_UNCHECKED_REF;
528 else
529 return FT_CHECKED_REF;
530 }
531
532 /**
533 * Create a LF which can access the given field.
534 * Cache and share this structure among all fields with
535 * the same basicType and refKind.
536 */
537 private static LambdaForm preparedFieldLambdaForm(MemberName m) {
538 Class<?> ftype = m.getFieldType();
539 boolean isVolatile = m.isVolatile();
540 byte formOp;
541 switch (m.getReferenceKind()) {
542 case REF_getField: formOp = AF_GETFIELD; break;
543 case REF_putField: formOp = AF_PUTFIELD; break;
554 }
555 LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
556 maybeCompile(lform, m);
557 assert(lform.methodType().dropParameterTypes(0, 1)
558 .equals(m.getInvocationType().basicType()))
559 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
560 return lform;
561 }
562 private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, Class<?> ftype) {
563 int ftypeKind = ftypeKind(ftype);
564 int afIndex = afIndex(formOp, isVolatile, ftypeKind);
565 LambdaForm lform = ACCESSOR_FORMS[afIndex];
566 if (lform != null) return lform;
567 lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
568 ACCESSOR_FORMS[afIndex] = lform; // don't bother with a CAS
569 return lform;
570 }
571
572 private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
573
574 private static Kind getFieldKind(boolean isGetter, boolean isVolatile, Wrapper wrapper) {
575 if (isGetter) {
576 if (isVolatile) {
577 switch (wrapper) {
578 case BOOLEAN: return GET_BOOLEAN_VOLATILE;
579 case BYTE: return GET_BYTE_VOLATILE;
580 case SHORT: return GET_SHORT_VOLATILE;
581 case CHAR: return GET_CHAR_VOLATILE;
582 case INT: return GET_INT_VOLATILE;
583 case LONG: return GET_LONG_VOLATILE;
584 case FLOAT: return GET_FLOAT_VOLATILE;
585 case DOUBLE: return GET_DOUBLE_VOLATILE;
586 case OBJECT: return GET_OBJECT_VOLATILE;
587 }
588 } else {
589 switch (wrapper) {
590 case BOOLEAN: return GET_BOOLEAN;
591 case BYTE: return GET_BYTE;
592 case SHORT: return GET_SHORT;
593 case CHAR: return GET_CHAR;
594 case INT: return GET_INT;
595 case LONG: return GET_LONG;
596 case FLOAT: return GET_FLOAT;
597 case DOUBLE: return GET_DOUBLE;
598 case OBJECT: return GET_OBJECT;
599 }
600 }
601 } else {
602 if (isVolatile) {
603 switch (wrapper) {
604 case BOOLEAN: return PUT_BOOLEAN_VOLATILE;
605 case BYTE: return PUT_BYTE_VOLATILE;
606 case SHORT: return PUT_SHORT_VOLATILE;
607 case CHAR: return PUT_CHAR_VOLATILE;
608 case INT: return PUT_INT_VOLATILE;
609 case LONG: return PUT_LONG_VOLATILE;
610 case FLOAT: return PUT_FLOAT_VOLATILE;
611 case DOUBLE: return PUT_DOUBLE_VOLATILE;
612 case OBJECT: return PUT_OBJECT_VOLATILE;
613 }
614 } else {
615 switch (wrapper) {
616 case BOOLEAN: return PUT_BOOLEAN;
617 case BYTE: return PUT_BYTE;
618 case SHORT: return PUT_SHORT;
619 case CHAR: return PUT_CHAR;
620 case INT: return PUT_INT;
621 case LONG: return PUT_LONG;
622 case FLOAT: return PUT_FLOAT;
623 case DOUBLE: return PUT_DOUBLE;
624 case OBJECT: return PUT_OBJECT;
625 }
626 }
627 }
628 throw new AssertionError("Invalid arguments");
629 }
630
631 static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
632 boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1);
633 boolean isStatic = (formOp >= AF_GETSTATIC);
634 boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
635 boolean needsCast = (ftypeKind == FT_CHECKED_REF);
636 Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]);
637 Class<?> ft = fw.primitiveType();
638 assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
639
640 // getObject, putIntVolatile, etc.
641 Kind kind = getFieldKind(isGetter, isVolatile, fw);
642
643 MethodType linkerType;
644 if (isGetter)
645 linkerType = MethodType.methodType(ft, Object.class, long.class);
646 else
647 linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
648 MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual);
649 try {
650 linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
651 } catch (ReflectiveOperationException ex) {
652 throw newInternalError(ex);
653 }
654
655 // What is the external type of the lambda form?
656 MethodType mtype;
657 if (isGetter)
658 mtype = MethodType.methodType(ft);
659 else
660 mtype = MethodType.methodType(void.class, ft);
661 mtype = mtype.basicType(); // erase short to int, etc.
662 if (!isStatic)
663 mtype = mtype.insertParameterTypes(0, Object.class);
664 final int DMH_THIS = 0;
665 final int ARG_BASE = 1;
666 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
667 // if this is for non-static access, the base pointer is stored at this index:
668 final int OBJ_BASE = isStatic ? -1 : ARG_BASE;
669 // if this is for write access, the value to be written is stored at this index:
670 final int SET_VALUE = isGetter ? -1 : ARG_LIMIT - 1;
671 int nameCursor = ARG_LIMIT;
672 final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any
673 final int F_OFFSET = nameCursor++; // Either static offset or field offset.
674 final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
675 final int U_HOLDER = nameCursor++; // UNSAFE holder
676 final int INIT_BAR = (needsInit ? nameCursor++ : -1);
677 final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1);
678 final int LINKER_CALL = nameCursor++;
679 final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
680 final int RESULT = nameCursor-1; // either the call or the cast
681 Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
682 if (needsInit)
683 names[INIT_BAR] = new Name(NF_ensureInitialized, names[DMH_THIS]);
684 if (needsCast && !isGetter)
685 names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
686 Object[] outArgs = new Object[1 + linkerType.parameterCount()];
687 assert(outArgs.length == (isGetter ? 3 : 4));
688 outArgs[0] = names[U_HOLDER] = new Name(NF_unsafe);
689 if (isStatic) {
690 outArgs[1] = names[F_HOLDER] = new Name(NF_staticBase, names[DMH_THIS]);
691 outArgs[2] = names[F_OFFSET] = new Name(NF_staticOffset, names[DMH_THIS]);
692 } else {
693 outArgs[1] = names[OBJ_CHECK] = new Name(NF_checkBase, names[OBJ_BASE]);
694 outArgs[2] = names[F_OFFSET] = new Name(NF_fieldOffset, names[DMH_THIS]);
695 }
696 if (!isGetter) {
697 outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
698 }
699 for (Object a : outArgs) assert(a != null);
700 names[LINKER_CALL] = new Name(linker, outArgs);
701 if (needsCast && isGetter)
702 names[POST_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
703 for (Name n : names) assert(n != null);
704 // add some detail to the lambdaForm debugname,
705 // significant only for debugging
706 StringBuilder nameBuilder = new StringBuilder(kind.methodName);
707 if (isStatic) {
708 nameBuilder.append("Static");
709 } else {
710 nameBuilder.append("Field");
711 }
712 if (needsCast) nameBuilder.append("Cast");
713 if (needsInit) nameBuilder.append("Init");
714 if (needsCast || needsInit) {
715 // can't use the pre-generated form when casting and/or initializing
716 return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
717 } else {
718 return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT, kind);
719 }
720 }
721
722 /**
723 * Pre-initialized NamedFunctions for bootstrapping purposes.
724 * Factored in an inner class to delay initialization until first usage.
725 */
726 static final NamedFunction
727 NF_internalMemberName,
728 NF_internalMemberNameEnsureInit,
729 NF_ensureInitialized,
730 NF_fieldOffset,
731 NF_checkBase,
732 NF_staticBase,
733 NF_staticOffset,
734 NF_checkCast,
735 NF_allocateInstance,
736 NF_constructorMethod,
737 NF_unsafe;
738 static {
739 try {
740 NamedFunction nfs[] = {
741 NF_internalMemberName = new NamedFunction(DirectMethodHandle.class
742 .getDeclaredMethod("internalMemberName", Object.class)),
743 NF_internalMemberNameEnsureInit = new NamedFunction(DirectMethodHandle.class
744 .getDeclaredMethod("internalMemberNameEnsureInit", Object.class)),
745 NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class
746 .getDeclaredMethod("ensureInitialized", Object.class)),
747 NF_fieldOffset = new NamedFunction(DirectMethodHandle.class
748 .getDeclaredMethod("fieldOffset", Object.class)),
749 NF_checkBase = new NamedFunction(DirectMethodHandle.class
750 .getDeclaredMethod("checkBase", Object.class)),
751 NF_staticBase = new NamedFunction(DirectMethodHandle.class
752 .getDeclaredMethod("staticBase", Object.class)),
753 NF_staticOffset = new NamedFunction(DirectMethodHandle.class
754 .getDeclaredMethod("staticOffset", Object.class)),
755 NF_checkCast = new NamedFunction(DirectMethodHandle.class
756 .getDeclaredMethod("checkCast", Object.class, Object.class)),
757 NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
758 .getDeclaredMethod("allocateInstance", Object.class)),
759 NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
760 .getDeclaredMethod("constructorMethod", Object.class)),
761 NF_unsafe = new NamedFunction(DirectMethodHandle.class
762 .getDeclaredMethod("unsafe"))
763 };
764 // Each nf must be statically invocable or we get tied up in our bootstraps.
765 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
766 } catch (ReflectiveOperationException ex) {
767 throw newInternalError(ex);
768 }
769 }
770
771 static {
772 // The Holder class will contain pre-generated DirectMethodHandles resolved
773 // speculatively using MemberName.getFactory().resolveOrNull. However, that
774 // doesn't initialize the class, which subtly breaks inlining etc. By forcing
775 // initialization of the Holder class we avoid these issues.
776 UNSAFE.ensureClassInitialized(Holder.class);
777 }
778
779 /* Placeholder class for DirectMethodHandles generated ahead of time */
780 final class Holder {}
781 }
|