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
  51  * to a class member.
  52  * @author jrose
  53  */
  54 @AOTSafeClassInitializer
  55 sealed class DirectMethodHandle extends MethodHandle {
  56     final MemberName member;
  57     final boolean crackable;
  58 
  59     // Constructors and factory methods in this class *must* be package scoped or private.
  60     private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member, boolean crackable) {
  61         super(mtype, form);
  62         if (!member.isResolved())  throw new InternalError();
  63 
  64         if (member.getDeclaringClass().isInterface() &&
  65             member.getReferenceKind() == REF_invokeInterface &&
  66             member.isMethod() && !member.isAbstract()) {
  67             // Check for corner case: invokeinterface of Object method
  68             MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
  69             m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null, LM_TRUSTED);
  70             if (m != null && m.isPublic()) {
  71                 assert(member.getReferenceKind() == m.getReferenceKind());  // else this.form is wrong
  72                 member = m;
  73             }
  74         }
  75 
  76         this.member = member;
  77         this.crackable = crackable;
  78     }
  79 
  80     // Factory methods:
  81     static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) {
  82         MethodType mtype = member.getMethodOrFieldType();
  83         if (!member.isStatic()) {
  84             if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
  85                 throw new InternalError(member.toString());
  86             mtype = mtype.insertParameterTypes(0, refc);
  87         }
  88         if (!member.isField()) {
  89             // refKind reflects the original type of lookup via findSpecial or
  90             // findVirtual etc.
  91             return switch (refKind) {
  92                 case REF_invokeSpecial -> {
  93                     member = member.asSpecial();
  94                     // if caller is an interface we need to adapt to get the
  95                     // receiver check inserted
  96                     if (callerClass == null) {
  97                         throw new InternalError("callerClass must not be null for REF_invokeSpecial");
  98                     }
  99                     LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
 100                     yield new Special(mtype, lform, member, true, callerClass);
 101                 }
 102                 case REF_invokeInterface -> {
 103                     // for interfaces we always need the receiver typecheck,
 104                     // so we always pass 'true' to ensure we adapt if needed
 105                     // to include the REF_invokeSpecial case
 106                     LambdaForm lform = preparedLambdaForm(member, true);
 107                     yield new Interface(mtype, lform, member, true, refc);
 108                 }
 109                 default -> {
 110                     LambdaForm lform = preparedLambdaForm(member);
 111                     yield new DirectMethodHandle(mtype, lform, member, true);
 112                 }
 113             };
 114         } else {
 115             LambdaForm lform = preparedFieldLambdaForm(member);
 116             if (member.isStatic()) {
 117                 long offset = MethodHandleNatives.staticFieldOffset(member);
 118                 Object base = MethodHandleNatives.staticFieldBase(member);
 119                 return new StaticAccessor(mtype, lform, member, true, base, offset);
 120             } else {
 121                 long offset = MethodHandleNatives.objectFieldOffset(member);
 122                 assert(offset == (int)offset);
 123                 return new Accessor(mtype, lform, member, true, (int)offset);
 124             }
 125         }
 126     }
 127     static DirectMethodHandle make(Class<?> refc, MemberName member) {
 128         byte refKind = member.getReferenceKind();
 129         if (refKind == REF_invokeSpecial)
 130             refKind =  REF_invokeVirtual;
 131         return make(refKind, refc, member, null /* no callerClass context */);
 132     }
 133     static DirectMethodHandle make(MemberName member) {
 134         if (member.isConstructor())
 135             return makeAllocator(member.getDeclaringClass(), member);
 136         return make(member.getDeclaringClass(), member);
 137     }
 138     static DirectMethodHandle makeAllocator(Class<?> instanceClass, MemberName ctor) {
 139         assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
 140         ctor = ctor.asConstructor();
 141         assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
 142         MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
 143         LambdaForm lform = preparedLambdaForm(ctor);
 144         MemberName init = ctor.asSpecial();
 145         assert(init.getMethodType().returnType() == void.class);
 146         return new Constructor(mtype, lform, ctor, true, init, instanceClass);
 147     }
 148 
 149     @Override
 150     BoundMethodHandle rebind() {
 151         return BoundMethodHandle.makeReinvoker(this);
 152     }
 153 
 154     @Override
 155     MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 156         assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
 157         return new DirectMethodHandle(mt, lf, member, crackable);
 158     }
 159 
 160     @Override
 161     MethodHandle viewAsType(MethodType newType, boolean strict) {
 162         // No actual conversions, just a new view of the same method.
 163         // However, we must not expose a DMH that is crackable into a
 164         // MethodHandleInfo, so we return a cloned, uncrackable DMH
 165         assert(viewAsTypeChecks(newType, strict));
 166         assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
 167         return new DirectMethodHandle(newType, form, member, false);
 168     }
 169 
 170     @Override
 171     boolean isCrackable() {
 172         return crackable;
 173     }
 174 
 175     @Override
 176     String internalProperties(int indentLevel) {
 177         return "\n" + debugPrefix(indentLevel) + "& DMH.MN=" + internalMemberName();
 178     }
 179 
 180     //// Implementation methods.
 181     @Override
 182     @ForceInline
 183     MemberName internalMemberName() {
 184         return member;
 185     }
 186 
 187     private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
 188 
 189     /**
 190      * Create a LF which can invoke the given method.
 191      * Cache and share this structure among all methods with
 192      * the same basicType and refKind.
 193      */
 194     private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) {
 195         assert(m.isInvocable()) : m;  // call preparedFieldLambdaForm instead
 196         MethodType mtype = m.getInvocationType().basicType();
 197         assert(!m.isMethodHandleInvoke()) : m;
 198         // MemberName.getReferenceKind represents the JVM optimized form of the call
 199         // as distinct from the "kind" passed to DMH.make which represents the original
 200         // bytecode-equivalent request. Specifically private/final methods that use a direct
 201         // call have getReferenceKind adapted to REF_invokeSpecial, even though the actual
 202         // invocation mode may be invokevirtual or invokeinterface.
 203         int which = switch (m.getReferenceKind()) {
 204             case REF_invokeVirtual    -> LF_INVVIRTUAL;
 205             case REF_invokeStatic     -> LF_INVSTATIC;
 206             case REF_invokeSpecial    -> LF_INVSPECIAL;
 207             case REF_invokeInterface  -> LF_INVINTERFACE;
 208             case REF_newInvokeSpecial -> LF_NEWINVSPECIAL;
 209             default -> throw new InternalError(m.toString());
 210         };
 211         if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
 212             // precompute the barrier-free version:
 213             preparedLambdaForm(mtype, which);
 214             which = LF_INVSTATIC_INIT;
 215         }
 216         if (which == LF_INVSPECIAL && adaptToSpecialIfc) {
 217             which = LF_INVSPECIAL_IFC;
 218         }
 219         LambdaForm lform = preparedLambdaForm(mtype, which);
 220         assert(lform.methodType().dropParameterTypes(0, 1)
 221                 .equals(m.getInvocationType().basicType()))
 222                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 223         return lform;
 224     }
 225 
 226     private static LambdaForm preparedLambdaForm(MemberName m) {
 227         return preparedLambdaForm(m, false);
 228     }
 229 
 230     private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
 231         LambdaForm lform = mtype.form().cachedLambdaForm(which);
 232         if (lform != null)  return lform;
 233         lform = makePreparedLambdaForm(mtype, which);
 234         return mtype.form().setCachedLambdaForm(which, lform);
 235     }
 236 
 237     static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
 238         boolean needsInit = (which == LF_INVSTATIC_INIT);
 239         boolean doesAlloc = (which == LF_NEWINVSPECIAL);
 240         boolean needsReceiverCheck = (which == LF_INVINTERFACE ||
 241                                       which == LF_INVSPECIAL_IFC);
 242 
 243         String linkerName;
 244         LambdaForm.Kind kind;
 245         switch (which) {
 246         case LF_INVVIRTUAL:    linkerName = "linkToVirtual";   kind = DIRECT_INVOKE_VIRTUAL;     break;
 247         case LF_INVSTATIC:     linkerName = "linkToStatic";    kind = DIRECT_INVOKE_STATIC;      break;
 248         case LF_INVSTATIC_INIT:linkerName = "linkToStatic";    kind = DIRECT_INVOKE_STATIC_INIT; break;
 249         case LF_INVSPECIAL_IFC:linkerName = "linkToSpecial";   kind = DIRECT_INVOKE_SPECIAL_IFC; break;
 250         case LF_INVSPECIAL:    linkerName = "linkToSpecial";   kind = DIRECT_INVOKE_SPECIAL;     break;
 251         case LF_INVINTERFACE:  linkerName = "linkToInterface"; kind = DIRECT_INVOKE_INTERFACE;   break;
 252         case LF_NEWINVSPECIAL: linkerName = "linkToSpecial";   kind = DIRECT_NEW_INVOKE_SPECIAL; break;
 253         default:  throw new InternalError("which="+which);
 254         }
 255 
 256         MethodType mtypeWithArg;
 257         if (doesAlloc) {
 258             var ptypes = mtype.ptypes();
 259             var newPtypes = new Class<?>[ptypes.length + 2];
 260             newPtypes[0] = Object.class; // insert newly allocated obj
 261             System.arraycopy(ptypes, 0, newPtypes, 1, ptypes.length);
 262             newPtypes[newPtypes.length - 1] = MemberName.class;
 263             mtypeWithArg = MethodType.methodType(void.class, newPtypes, true);
 264         } else {
 265             mtypeWithArg = mtype.appendParameterTypes(MemberName.class);
 266         }
 267         MemberName linker = new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
 268         try {
 269             linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, LM_TRUSTED,
 270                                               NoSuchMethodException.class);
 271         } catch (ReflectiveOperationException ex) {
 272             throw newInternalError(ex);
 273         }
 274         final int DMH_THIS    = 0;
 275         final int ARG_BASE    = 1;
 276         final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
 277         int nameCursor = ARG_LIMIT;
 278         final int NEW_OBJ     = (doesAlloc ? nameCursor++ : -1);
 279         final int GET_MEMBER  = nameCursor++;
 280         final int CHECK_RECEIVER = (needsReceiverCheck ? nameCursor++ : -1);
 281         final int LINKER_CALL = nameCursor++;
 282         Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
 283         assert(names.length == nameCursor);
 284         if (doesAlloc) {
 285             // names = { argx,y,z,... new C, init method }
 286             names[NEW_OBJ] = new Name(getFunction(NF_allocateInstance), names[DMH_THIS]);
 287             names[GET_MEMBER] = new Name(getFunction(NF_constructorMethod), names[DMH_THIS]);
 288         } else if (needsInit) {
 289             names[GET_MEMBER] = new Name(getFunction(NF_internalMemberNameEnsureInit), names[DMH_THIS]);
 290         } else {
 291             names[GET_MEMBER] = new Name(getFunction(NF_internalMemberName), names[DMH_THIS]);
 292         }
 293         assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]);
 294         Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
 295         if (needsReceiverCheck) {
 296             names[CHECK_RECEIVER] = new Name(getFunction(NF_checkReceiver), names[DMH_THIS], names[ARG_BASE]);
 297             outArgs[0] = names[CHECK_RECEIVER];
 298         }
 299         assert(outArgs[outArgs.length-1] == names[GET_MEMBER]);  // look, shifted args!
 300         int result = LAST_RESULT;
 301         if (doesAlloc) {
 302             assert(outArgs[outArgs.length-2] == names[NEW_OBJ]);  // got to move this one
 303             System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2);
 304             outArgs[0] = names[NEW_OBJ];
 305             result = NEW_OBJ;
 306         }
 307         names[LINKER_CALL] = new Name(linker, outArgs);
 308         LambdaForm lform = LambdaForm.create(ARG_LIMIT, names, result, kind);
 309 
 310         // This is a tricky bit of code.  Don't send it through the LF interpreter.
 311         lform.compileToBytecode();
 312         return lform;
 313     }
 314 
 315     /* assert */ static Object findDirectMethodHandle(Name name) {
 316         if (name.function.equals(getFunction(NF_internalMemberName)) ||
 317             name.function.equals(getFunction(NF_internalMemberNameEnsureInit)) ||
 318             name.function.equals(getFunction(NF_constructorMethod))) {
 319             assert(name.arguments.length == 1);
 320             return name.arguments[0];
 321         }
 322         return null;
 323     }
 324 
 325     /** Static wrapper for DirectMethodHandle.internalMemberName. */
 326     @ForceInline
 327     /*non-public*/
 328     static Object internalMemberName(Object mh) {
 329         return ((DirectMethodHandle)mh).member;
 330     }
 331 
 332     /** Static wrapper for DirectMethodHandle.internalMemberName.
 333      * This one also forces initialization.
 334      */
 335     /*non-public*/
 336     static Object internalMemberNameEnsureInit(Object mh) {
 337         DirectMethodHandle dmh = (DirectMethodHandle)mh;
 338         dmh.ensureInitialized();
 339         return dmh.member;
 340     }
 341 
 342     /*non-public*/
 343     static boolean shouldBeInitialized(MemberName member) {
 344         switch (member.getReferenceKind()) {
 345         case REF_invokeStatic:
 346         case REF_getStatic:
 347         case REF_putStatic:
 348         case REF_newInvokeSpecial:
 349             break;
 350         default:
 351             // No need to initialize the class on this kind of member.
 352             return false;
 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) {
 416             return new Special(mt, lf, member, crackable, caller);
 417         }
 418         @Override
 419         MethodHandle viewAsType(MethodType newType, boolean strict) {
 420             assert(viewAsTypeChecks(newType, strict));
 421             return new Special(newType, form, member, false, caller);
 422         }
 423         Object checkReceiver(Object recv) {
 424             if (!caller.isInstance(recv)) {
 425                 if (recv != null) {
 426                     String msg = String.format("Receiver class %s is not a subclass of caller class %s",
 427                                                recv.getClass().getName(), caller.getName());
 428                     throw new IncompatibleClassChangeError(msg);
 429                 } else {
 430                     String msg = String.format("Cannot invoke %s with null receiver", member);
 431                     throw new NullPointerException(msg);
 432                 }
 433             }
 434             return recv;
 435         }
 436     }
 437 
 438     /** This subclass represents invokeinterface instructions. */
 439     static final class Interface extends DirectMethodHandle {
 440         private final Class<?> refc;
 441         private Interface(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> refc) {
 442             super(mtype, form, member, crackable);
 443             assert(refc.isInterface()) : refc;
 444             this.refc = refc;
 445         }
 446         @Override
 447         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 448             return new Interface(mt, lf, member, crackable, refc);
 449         }
 450         @Override
 451         MethodHandle viewAsType(MethodType newType, boolean strict) {
 452             assert(viewAsTypeChecks(newType, strict));
 453             return new Interface(newType, form, member, false, refc);
 454         }
 455         @Override
 456         Object checkReceiver(Object recv) {
 457             if (!refc.isInstance(recv)) {
 458                 if (recv != null) {
 459                     String msg = String.format("Receiver class %s does not implement the requested interface %s",
 460                                                recv.getClass().getName(), refc.getName());
 461                     throw new IncompatibleClassChangeError(msg);
 462                 } else {
 463                     String msg = String.format("Cannot invoke %s with null receiver", member);
 464                     throw new NullPointerException(msg);
 465                 }
 466             }
 467             return recv;
 468         }
 469     }
 470 
 471     /** Used for interface receiver type checks, by Interface and Special modes. */
 472     Object checkReceiver(Object recv) {
 473         throw new InternalError("Should only be invoked on a subclass");
 474     }
 475 
 476     /** This subclass handles constructor references. */
 477     @AOTSafeClassInitializer
 478     static final class Constructor extends DirectMethodHandle {
 479         final MemberName initMethod;
 480         final Class<?>   instanceClass;
 481 
 482         private Constructor(MethodType mtype, LambdaForm form, MemberName constructor,
 483                             boolean crackable, MemberName initMethod, Class<?> instanceClass) {
 484             super(mtype, form, constructor, crackable);
 485             this.initMethod = initMethod;
 486             this.instanceClass = instanceClass;
 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.
 552         // We store a plain int because it is more compact.
 553         return ((Accessor)accessorObj).fieldOffset;
 554     }
 555 
 556     @ForceInline
 557     /*non-public*/
 558     static Object checkBase(Object obj) {
 559         // Note that the object's class has already been verified,
 560         // since the parameter type of the Accessor method handle
 561         // is either member.getDeclaringClass or a subclass.
 562         // This was verified in DirectMethodHandle.make.
 563         // Therefore, the only remaining check is for null.
 564         // Since this check is *not* guaranteed by Unsafe.getInt
 565         // and its siblings, we need to make an explicit one here.
 566         return Objects.requireNonNull(obj);
 567     }
 568 
 569     /** This subclass handles static field references. */
 570     static final class StaticAccessor extends DirectMethodHandle {
 571         private final Class<?> fieldType;
 572         private final Object   staticBase;
 573         private final long     staticOffset;
 574 
 575         private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member,
 576                                boolean crackable, Object staticBase, long staticOffset) {
 577             super(mtype, form, member, crackable);
 578             this.fieldType    = member.getFieldType();
 579             this.staticBase   = staticBase;
 580             this.staticOffset = staticOffset;
 581         }
 582 
 583         @Override Object checkCast(Object obj) {
 584             return fieldType.cast(obj);
 585         }
 586         @Override
 587         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 588             return new StaticAccessor(mt, lf, member, crackable, staticBase, staticOffset);
 589         }
 590         @Override
 591         MethodHandle viewAsType(MethodType newType, boolean strict) {
 592             assert(viewAsTypeChecks(newType, strict));
 593             return new StaticAccessor(newType, form, member, false, staticBase, staticOffset);
 594         }
 595     }
 596 
 597     @ForceInline
 598     /*non-public*/
 599     static Object nullCheck(Object obj) {
 600         return Objects.requireNonNull(obj);
 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
1080         // speculatively using MemberName.getFactory().resolveOrNull. However, that
1081         // doesn't initialize the class, which subtly breaks inlining etc. By forcing
1082         // initialization of the Holder class we avoid these issues.
1083         UNSAFE.ensureClassInitialized(Holder.class);
1084     }
1085 
1086     /// Holds pre-generated bytecode for lambda forms used by DirectMethodHandle.
1087     ///
1088     /// This class may be substituted in the JDK's modules image, or in an AOT
1089     /// cache, by a version generated by [GenerateJLIClassesHelper].
1090     ///
1091     /// The method names of this class are internal tokens recognized by
1092     /// [InvokerBytecodeGenerator#lookupPregenerated] and are subject to change.
1093     @AOTSafeClassInitializer
1094     final class Holder {}
1095 }