< prev index next >

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

Print this page

   1 /*
   2  * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import jdk.internal.misc.CDS;
  29 import jdk.internal.misc.Unsafe;

  30 import jdk.internal.vm.annotation.AOTSafeClassInitializer;
  31 import jdk.internal.vm.annotation.ForceInline;
  32 import jdk.internal.vm.annotation.Stable;
  33 import sun.invoke.util.ValueConversions;
  34 import sun.invoke.util.VerifyAccess;
  35 import sun.invoke.util.Wrapper;
  36 
  37 import java.util.Arrays;
  38 import java.util.Objects;
  39 import java.util.function.Function;
  40 
  41 import static java.lang.invoke.LambdaForm.*;
  42 import static java.lang.invoke.LambdaForm.Kind.*;
  43 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  44 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  45 import static java.lang.invoke.MethodHandleStatics.newInternalError;
  46 import static java.lang.invoke.MethodTypeForm.*;
  47 
  48 /**
  49  * The flavor of method handle which implements a constant reference

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





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

 481             assert(initMethod.isResolved());
 482         }
 483         @Override
 484         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 485             return new Constructor(mt, lf, member, crackable, initMethod, instanceClass);
 486         }
 487         @Override
 488         MethodHandle viewAsType(MethodType newType, boolean strict) {
 489             assert(viewAsTypeChecks(newType, strict));
 490             return new Constructor(newType, form, member, false, initMethod, instanceClass);
 491         }
 492     }
 493 
 494     /*non-public*/
 495     static Object constructorMethod(Object mh) {
 496         Constructor dmh = (Constructor)mh;
 497         return dmh.initMethod;
 498     }
 499 
 500     /*non-public*/









 501     static Object allocateInstance(Object mh) throws InstantiationException {
 502         Constructor dmh = (Constructor)mh;
 503         return UNSAFE.allocateInstance(dmh.instanceClass);
 504     }
 505 
 506     /** This subclass handles non-static field references. */
 507     static final class Accessor extends DirectMethodHandle {
 508         final Class<?> fieldType;
 509         final int      fieldOffset;

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

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

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















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

















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

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

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


 639         }

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






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






























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

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

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


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
















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


 758 

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





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



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




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






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



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




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



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








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

   1 /*
   2  * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import jdk.internal.misc.CDS;
  29 import jdk.internal.misc.Unsafe;
  30 import jdk.internal.value.ValueClass;
  31 import jdk.internal.vm.annotation.AOTSafeClassInitializer;
  32 import jdk.internal.vm.annotation.ForceInline;
  33 import jdk.internal.vm.annotation.Stable;
  34 import sun.invoke.util.ValueConversions;
  35 import sun.invoke.util.VerifyAccess;
  36 import sun.invoke.util.Wrapper;
  37 
  38 import java.util.Arrays;
  39 import java.util.Objects;
  40 import java.util.function.Function;
  41 
  42 import static java.lang.invoke.LambdaForm.*;
  43 import static java.lang.invoke.LambdaForm.Kind.*;
  44 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  45 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  46 import static java.lang.invoke.MethodHandleStatics.newInternalError;
  47 import static java.lang.invoke.MethodTypeForm.*;
  48 
  49 /**
  50  * The flavor of method handle which implements a constant reference

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

 487             assert(initMethod.isResolved());
 488         }
 489         @Override
 490         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 491             return new Constructor(mt, lf, member, crackable, initMethod, instanceClass);
 492         }
 493         @Override
 494         MethodHandle viewAsType(MethodType newType, boolean strict) {
 495             assert(viewAsTypeChecks(newType, strict));
 496             return new Constructor(newType, form, member, false, initMethod, instanceClass);
 497         }
 498     }
 499 
 500     /*non-public*/
 501     static Object constructorMethod(Object mh) {
 502         Constructor dmh = (Constructor)mh;
 503         return dmh.initMethod;
 504     }
 505 
 506     /*non-public*/
 507 
 508     /**
 509      * This method returns an uninitialized instance. In general, this is undefined behavior, this
 510      * method is treated specially by the JVM to allow this behavior. The returned value must be
 511      * passed into a constructor using {@link MethodHandle#linkToSpecial} before any other
 512      * operation can be performed on it. Otherwise, the program is ill-formed.
 513      *
 514      * @see Unsafe
 515      */
 516     static Object allocateInstance(Object mh) throws InstantiationException {
 517         Constructor dmh = (Constructor)mh;
 518         return UNSAFE.allocateInstance(dmh.instanceClass);
 519     }
 520 
 521     /** This subclass handles non-static field references. */
 522     static final class Accessor extends DirectMethodHandle {
 523         final Class<?> fieldType;
 524         final int      fieldOffset;
 525         final int      layout;
 526         private Accessor(MethodType mtype, LambdaForm form, MemberName member,
 527                          boolean crackable, int fieldOffset) {
 528             super(mtype, form, member, crackable);
 529             this.fieldType   = member.getFieldType();
 530             this.fieldOffset = fieldOffset;
 531             this.layout = member.getLayout();
 532         }
 533 
 534         @Override Object checkCast(Object obj) {
 535             return fieldType.cast(obj);
 536         }
 537         @Override
 538         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 539             return new Accessor(mt, lf, member, crackable, fieldOffset);
 540         }
 541         @Override
 542         MethodHandle viewAsType(MethodType newType, boolean strict) {
 543             assert(viewAsTypeChecks(newType, strict));
 544             return new Accessor(newType, form, member, false, fieldOffset);
 545         }
 546     }
 547 
 548     @ForceInline
 549     /*non-public*/
 550     static long fieldOffset(Object accessorObj) {
 551         // Note: We return a long because that is what Unsafe.getObject likes.

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

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


 789             }
 790         } else {
 791             if (isFlat) {
 792                 assert !needsInit && needsCast;
 793                 return isNullRestricted ? PUT_NULL_RESTRICTED_FLAT_VALUE : FIELD_ACCESS_FLAT;
 794             } else if (needsCast) {
 795                 if (needsInit) {
 796                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_CAST_INIT : FIELD_ACCESS_INIT_CAST;
 797                 } else {
 798                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_CAST : FIELD_ACCESS_CAST;
 799                 }
 800             } else {
 801                 if (needsInit) {
 802                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_INIT : FIELD_ACCESS_INIT;
 803                 } else {
 804                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE : FIELD_ACCESS;
 805                 }


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