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.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;
 140         ctor = ctor.asConstructor();
 141         assert(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.isStrict()) {
 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     static Object allocateInstance(Object mh) throws InstantiationException {
 508         Constructor dmh = (Constructor)mh;
 509         return UNSAFE.allocateInstance(dmh.instanceClass);
 510     }
 511 
 512     /** This subclass handles non-static field references. */
 513     static final class Accessor extends DirectMethodHandle {
 514         final Class<?> fieldType;
 515         final int      fieldOffset;
 516         final int      layout;
 517         private Accessor(MethodType mtype, LambdaForm form, MemberName member,
 518                          boolean crackable, int fieldOffset) {
 519             super(mtype, form, member, crackable);
 520             this.fieldType   = member.getFieldType();
 521             this.fieldOffset = fieldOffset;
 522             this.layout = member.getLayout();
 523         }
 524 
 525         @Override Object checkCast(Object obj) {
 526             return fieldType.cast(obj);
 527         }
 528         @Override
 529         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 530             return new Accessor(mt, lf, member, crackable, fieldOffset);
 531         }
 532         @Override
 533         MethodHandle viewAsType(MethodType newType, boolean strict) {
 534             assert(viewAsTypeChecks(newType, strict));
 535             return new Accessor(newType, form, member, false, fieldOffset);
 536         }
 537     }
 538 
 539     @ForceInline
 540     /*non-public*/
 541     static long fieldOffset(Object accessorObj) {
 542         // Note: We return a long because that is what Unsafe.getObject likes.
 543         // We store a plain int because it is more compact.
 544         return ((Accessor)accessorObj).fieldOffset;
 545     }
 546 
 547     @ForceInline
 548     /*non-public*/
 549     static Object checkBase(Object obj) {
 550         // Note that the object's class has already been verified,
 551         // since the parameter type of the Accessor method handle
 552         // is either member.getDeclaringClass or a subclass.
 553         // This was verified in DirectMethodHandle.make.
 554         // Therefore, the only remaining check is for null.
 555         // Since this check is *not* guaranteed by Unsafe.getInt
 556         // and its siblings, we need to make an explicit one here.
 557         return Objects.requireNonNull(obj);
 558     }
 559 
 560     /** This subclass handles static field references. */
 561     static final class StaticAccessor extends DirectMethodHandle {
 562         private final Class<?> fieldType;
 563         private final Object   staticBase;
 564         private final long     staticOffset;
 565 
 566         private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member,
 567                                boolean crackable, Object staticBase, long staticOffset) {
 568             super(mtype, form, member, crackable);
 569             this.fieldType    = member.getFieldType();
 570             this.staticBase   = staticBase;
 571             this.staticOffset = staticOffset;
 572         }
 573 
 574         @Override Object checkCast(Object obj) {
 575             return fieldType.cast(obj);
 576         }
 577         @Override
 578         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 579             return new StaticAccessor(mt, lf, member, crackable, staticBase, staticOffset);
 580         }
 581         @Override
 582         MethodHandle viewAsType(MethodType newType, boolean strict) {
 583             assert(viewAsTypeChecks(newType, strict));
 584             return new StaticAccessor(newType, form, member, false, staticBase, staticOffset);
 585         }
 586     }
 587 
 588     @ForceInline
 589     /*non-public*/
 590     static Object nullCheck(Object obj) {
 591         return Objects.requireNonNull(obj);
 592     }
 593 
 594     @ForceInline
 595     /*non-public*/
 596     static Object staticBase(Object accessorObj) {
 597         return ((StaticAccessor)accessorObj).staticBase;
 598     }
 599 
 600     @ForceInline
 601     /*non-public*/
 602     static long staticOffset(Object accessorObj) {
 603         return ((StaticAccessor)accessorObj).staticOffset;
 604     }
 605 
 606     @ForceInline
 607     /*non-public*/
 608     static Object checkCast(Object mh, Object obj) {
 609         return ((DirectMethodHandle) mh).checkCast(obj);
 610     }
 611 
 612     @ForceInline
 613     /*non-public*/ static Class<?> fieldType(Object accessorObj) {
 614         return ((Accessor) accessorObj).fieldType;
 615     }
 616 
 617     @ForceInline
 618     static int fieldLayout(Object accessorObj) {
 619         return ((Accessor) accessorObj).layout;
 620     }
 621 
 622     @ForceInline
 623     /*non-public*/ static Class<?> staticFieldType(Object accessorObj) {
 624         return ((StaticAccessor) accessorObj).fieldType;
 625     }
 626 
 627     Object checkCast(Object obj) {
 628         return member.getMethodType().returnType().cast(obj);
 629     }
 630 
 631     // Caching machinery for field accessors:
 632     static final byte
 633             AF_GETFIELD        = 0,
 634             AF_PUTFIELD        = 1,
 635             AF_GETSTATIC       = 2,
 636             AF_PUTSTATIC       = 3,
 637             AF_GETSTATIC_INIT  = 4,
 638             AF_PUTSTATIC_INIT  = 5,
 639             AF_LIMIT           = 6;
 640     // Enumerate the different field kinds using Wrapper,
 641     // with an extra case added for checked references and value field access
 642     static final int
 643             FT_FIRST_REFERENCE = 8,
 644             // Any oop, same sig (Runnable?)
 645             FT_UNCHECKED_REF    = FT_FIRST_REFERENCE,
 646             // Oop with type checks (Number?)
 647             FT_CHECKED_REF      = FT_FIRST_REFERENCE + 1,
 648             // Oop with null checks, (Runnable!)
 649             FT_UNCHECKED_NR_REF = FT_FIRST_REFERENCE + 2,
 650             // Oop with null and type checks, (Number!)
 651             FT_CHECKED_NR_REF   = FT_FIRST_REFERENCE + 3,
 652             FT_FIRST_FLAT = FT_FIRST_REFERENCE + 4,
 653             // nullable flat (must check type), (Integer?)
 654             FT_NULLABLE_FLAT    = FT_FIRST_FLAT,
 655             // Null restricted flat (must check type), (Integer!)
 656             FT_NR_FLAT          = FT_FIRST_FLAT + 1,
 657             FT_LIMIT            = FT_FIRST_FLAT + 2;
 658 
 659     static {
 660         assert FT_FIRST_REFERENCE == Wrapper.OBJECT.ordinal();
 661     }
 662 
 663     private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
 664         return ((formOp * FT_LIMIT * 2)
 665                 + (isVolatile ? FT_LIMIT : 0)
 666                 + ftypeKind);
 667     }
 668     @Stable
 669     private static final LambdaForm[] ACCESSOR_FORMS
 670             = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
 671     static int ftypeKind(Class<?> ftype, boolean isFlat, boolean isNullRestricted) {
 672         if (ftype.isPrimitive()) {
 673             assert !isFlat && !isNullRestricted : ftype;
 674             return Wrapper.forPrimitiveType(ftype).ordinal();
 675         } else if (ftype.isInterface() || ftype.isAssignableFrom(Object.class)) {
 676             assert !isFlat : ftype;
 677             // retyping can be done without a cast
 678             return isNullRestricted ? FT_UNCHECKED_NR_REF : FT_UNCHECKED_REF;
 679         }
 680         if (isFlat) {
 681             assert ValueClass.isConcreteValueClass(ftype) : ftype;
 682             return isNullRestricted ? FT_NR_FLAT : FT_NULLABLE_FLAT;
 683         }
 684         return isNullRestricted ? FT_CHECKED_NR_REF : FT_CHECKED_REF;
 685     }
 686 
 687     /**
 688      * Create a LF which can access the given field.
 689      * Cache and share this structure among all fields with
 690      * the same basicType and refKind.
 691      */
 692     private static LambdaForm preparedFieldLambdaForm(MemberName m) {
 693         Class<?> ftype = m.getFieldType();
 694         byte formOp = switch (m.getReferenceKind()) {
 695             case REF_getField  -> AF_GETFIELD;
 696             case REF_putField  -> AF_PUTFIELD;
 697             case REF_getStatic -> AF_GETSTATIC;
 698             case REF_putStatic -> AF_PUTSTATIC;
 699             default -> throw new InternalError(m.toString());
 700         };
 701         if (shouldBeInitialized(m)) {
 702             // precompute the barrier-free version:
 703             preparedFieldLambdaForm(formOp, m.isVolatile(), m.isFlat(), m.isNullRestricted(), ftype);
 704             assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
 705                    (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
 706             formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
 707         }
 708         LambdaForm lform = preparedFieldLambdaForm(formOp, m.isVolatile(), m.isFlat(), m.isNullRestricted(), ftype);
 709         assert(lform.methodType().dropParameterTypes(0, 1)
 710                 .equals(m.getInvocationType().basicType()))
 711                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 712         return lform;
 713     }
 714 
 715     private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile,
 716                                                       boolean isFlat, boolean isNullRestricted, Class<?> ftype) {
 717         int ftypeKind = ftypeKind(ftype, isFlat, isNullRestricted);
 718         return preparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
 719     }
 720 
 721     private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
 722         int afIndex = afIndex(formOp, isVolatile, ftypeKind);
 723         LambdaForm lform = ACCESSOR_FORMS[afIndex];
 724         if (lform != null)  return lform;
 725         lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind);
 726         ACCESSOR_FORMS[afIndex] = lform;  // don't bother with a CAS
 727         return lform;
 728     }
 729 
 730     private static final @Stable Wrapper[] ALL_WRAPPERS = Wrapper.values();
 731 
 732     // Names in kind may overload but differ from their basic type
 733     private static Kind getFieldKind(boolean isGetter,
 734                                      boolean isVolatile,
 735                                      boolean needsInit,
 736                                      boolean needsCast,
 737                                      boolean isFlat,
 738                                      boolean isNullRestricted,
 739                                      Wrapper wrapper) {
 740         if (!wrapper.isOther()) {
 741             // primitives
 742             assert !isFlat && !isNullRestricted && !needsCast;
 743             return switch (wrapper) {
 744                 case BYTE -> isVolatile
 745                         ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_B : VOLATILE_FIELD_ACCESS_B)
 746                         : (needsInit ? FIELD_ACCESS_INIT_B : FIELD_ACCESS_B);
 747                 case CHAR -> isVolatile
 748                         ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_C : VOLATILE_FIELD_ACCESS_C)
 749                         : (needsInit ? FIELD_ACCESS_INIT_C : FIELD_ACCESS_C);
 750                 case SHORT -> isVolatile
 751                         ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_S : VOLATILE_FIELD_ACCESS_S)
 752                         : (needsInit ? FIELD_ACCESS_INIT_S : FIELD_ACCESS_S);
 753                 case BOOLEAN -> isVolatile
 754                         ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT_Z : VOLATILE_FIELD_ACCESS_Z)
 755                         : (needsInit ? FIELD_ACCESS_INIT_Z : FIELD_ACCESS_Z);
 756                 // basic types
 757                 default -> isVolatile
 758                         ? (needsInit ? VOLATILE_FIELD_ACCESS_INIT : VOLATILE_FIELD_ACCESS)
 759                         : (needsInit ? FIELD_ACCESS_INIT : FIELD_ACCESS);
 760             };
 761         }
 762 
 763         assert !(isGetter && isNullRestricted);
 764         if (isVolatile) {
 765             if (isFlat) {
 766                 assert !needsInit && needsCast;
 767                 return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_FLAT_VALUE : VOLATILE_FIELD_ACCESS_FLAT;
 768             } else if (needsCast) {
 769                 if (needsInit) {
 770                     return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE_CAST_INIT : VOLATILE_FIELD_ACCESS_INIT_CAST;
 771                 } else {
 772                     return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE_CAST : VOLATILE_FIELD_ACCESS_CAST;
 773                 }
 774             } else {
 775                 if (needsInit) {
 776                     return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE_INIT : VOLATILE_FIELD_ACCESS_INIT;
 777                 } else {
 778                     return isNullRestricted ? VOLATILE_PUT_NULL_RESTRICTED_REFERENCE : VOLATILE_FIELD_ACCESS;
 779                 }
 780             }
 781         } else {
 782             if (isFlat) {
 783                 assert !needsInit && needsCast;
 784                 return isNullRestricted ? PUT_NULL_RESTRICTED_FLAT_VALUE : FIELD_ACCESS_FLAT;
 785             } else if (needsCast) {
 786                 if (needsInit) {
 787                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_CAST_INIT : FIELD_ACCESS_INIT_CAST;
 788                 } else {
 789                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_CAST : FIELD_ACCESS_CAST;
 790                 }
 791             } else {
 792                 if (needsInit) {
 793                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE_INIT : FIELD_ACCESS_INIT;
 794                 } else {
 795                     return isNullRestricted ? PUT_NULL_RESTRICTED_REFERENCE : FIELD_ACCESS;
 796                 }
 797             }
 798         }
 799     }
 800 
 801     private static String unsafeMethodName(boolean isGetter,
 802                                            boolean isVolatile,
 803                                            Wrapper wrapper) {
 804         var name = switch (wrapper) {
 805             case BOOLEAN -> "Boolean";
 806             case BYTE -> "Byte";
 807             case CHAR -> "Char";
 808             case SHORT -> "Short";
 809             case INT -> "Int";
 810             case FLOAT -> "Float";
 811             case LONG -> "Long";
 812             case DOUBLE -> "Double";
 813             case OBJECT -> "Reference";
 814             case VOID -> "FlatValue";
 815         };
 816         var sb = new StringBuilder(3 + name.length() + (isVolatile ? 8 : 0))
 817                 .append(isGetter ? "get" : "put")
 818                 .append(name);
 819         if (isVolatile) {
 820             sb.append("Volatile");
 821         }
 822         return sb.toString();
 823     }
 824 
 825     static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
 826         boolean isGetter  = (formOp & 1) == (AF_GETFIELD & 1);
 827         boolean isStatic  = (formOp >= AF_GETSTATIC);
 828         boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
 829         boolean isFlat = (ftypeKind >= FT_FIRST_FLAT);
 830         boolean isNullRestricted = (ftypeKind == FT_NR_FLAT || ftypeKind == FT_CHECKED_NR_REF || ftypeKind == FT_UNCHECKED_NR_REF);
 831         boolean needsCast = (isFlat || ftypeKind == FT_CHECKED_REF || ftypeKind == FT_CHECKED_NR_REF);
 832 
 833         if (isGetter && isNullRestricted) {
 834             int newKind = switch (ftypeKind) {
 835                 case FT_NR_FLAT -> FT_NULLABLE_FLAT;
 836                 case FT_CHECKED_NR_REF -> FT_CHECKED_REF;
 837                 case FT_UNCHECKED_NR_REF -> FT_UNCHECKED_REF;
 838                 default -> throw new InternalError();
 839             };
 840             return preparedFieldLambdaForm(formOp, isVolatile, newKind);
 841         }
 842 
 843         if (isFlat && isStatic)
 844             throw new InternalError("Static flat not supported yet");
 845 
 846         // primitives, reference, and void for flat
 847         Wrapper fw = ftypeKind < FT_FIRST_REFERENCE ? ALL_WRAPPERS[ftypeKind] :
 848                 isFlat ? Wrapper.VOID : Wrapper.OBJECT;
 849 
 850         // getObject, putIntVolatile, etc.
 851         String unsafeMethodName = unsafeMethodName(isGetter, isVolatile, fw);
 852         // isGetter and isStatic is reflected in field type;
 853         // flat, NR distinguished
 854         // basic type clash for subwords
 855         Kind kind = getFieldKind(isGetter, isVolatile, needsInit, needsCast, isFlat, isNullRestricted, fw);
 856 
 857         Class<?> ft = ftypeKind < FT_FIRST_REFERENCE ? fw.primitiveType() : Object.class;
 858         MethodType linkerType;
 859         if (isGetter) {
 860             linkerType = isFlat
 861                             ? MethodType.methodType(ft, Object.class, long.class, int.class, Class.class)
 862                             : MethodType.methodType(ft, Object.class, long.class);
 863         } else {
 864             linkerType = isFlat
 865                             ? MethodType.methodType(void.class, Object.class, long.class, int.class, Class.class, ft)
 866                             : MethodType.methodType(void.class, Object.class, long.class, ft);
 867         }
 868         MemberName linker = new MemberName(Unsafe.class, unsafeMethodName, linkerType, REF_invokeVirtual);
 869         try {
 870             linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, LM_TRUSTED,
 871                                               NoSuchMethodException.class);
 872         } catch (ReflectiveOperationException ex) {
 873             throw newInternalError(ex);
 874         }
 875 
 876         // What is the external type of the lambda form?
 877         MethodType mtype;
 878         if (isGetter)
 879             mtype = MethodType.methodType(ft);
 880         else
 881             mtype = MethodType.methodType(void.class, ft);
 882         mtype = mtype.basicType();  // erase short to int, etc.
 883         if (!isStatic)
 884             mtype = mtype.insertParameterTypes(0, Object.class);
 885         final int DMH_THIS  = 0;
 886         final int ARG_BASE  = 1;
 887         final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
 888         // if this is for non-static access, the base pointer is stored at this index:
 889         final int OBJ_BASE  = isStatic ? -1 : ARG_BASE;
 890         // if this is for write access, the value to be written is stored at this index:
 891         final int SET_VALUE  = isGetter ? -1 : ARG_LIMIT - 1;
 892         int nameCursor = ARG_LIMIT;
 893         final int F_HOLDER  = (isStatic ? nameCursor++ : -1);  // static base if any
 894         final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
 895         final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
 896         final int U_HOLDER  = nameCursor++;  // UNSAFE holder
 897         final int INIT_BAR  = (needsInit ? nameCursor++ : -1);
 898         final int LAYOUT = (isFlat ? nameCursor++ : -1); // field must be instance
 899         final int VALUE_TYPE = (isFlat ? nameCursor++ : -1);
 900         final int NULL_CHECK  = (isNullRestricted && !isGetter ? nameCursor++ : -1);
 901         final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
 902         final int LINKER_CALL = nameCursor++;
 903         final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
 904         final int RESULT    = nameCursor-1;  // either the call, or the cast
 905         Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
 906         if (needsInit)
 907             names[INIT_BAR] = new Name(getFunction(NF_ensureInitialized), names[DMH_THIS]);
 908         if (!isGetter) {
 909             if (isNullRestricted)
 910                 names[NULL_CHECK] = new Name(getFunction(NF_nullCheck), names[SET_VALUE]);
 911             if (needsCast)
 912                 names[PRE_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[SET_VALUE]);
 913         }
 914         Object[] outArgs = new Object[1 + linkerType.parameterCount()];
 915         assert (outArgs.length == (isGetter ? 3 : 4) + (isFlat ? 2 : 0));
 916         outArgs[0] = names[U_HOLDER] = new Name(getFunction(NF_UNSAFE));
 917         if (isStatic) {
 918             outArgs[1] = names[F_HOLDER]  = new Name(getFunction(NF_staticBase), names[DMH_THIS]);
 919             outArgs[2] = names[F_OFFSET]  = new Name(getFunction(NF_staticOffset), names[DMH_THIS]);
 920         } else {
 921             outArgs[1] = names[OBJ_CHECK] = new Name(getFunction(NF_checkBase), names[OBJ_BASE]);
 922             outArgs[2] = names[F_OFFSET]  = new Name(getFunction(NF_fieldOffset), names[DMH_THIS]);
 923         }
 924         int x = 3;
 925         if (isFlat) {
 926             outArgs[x++] = names[LAYOUT] = new Name(getFunction(NF_fieldLayout), names[DMH_THIS]);
 927             outArgs[x++] = names[VALUE_TYPE] = isStatic ? new Name(getFunction(NF_staticFieldType), names[DMH_THIS])
 928                                                         : new Name(getFunction(NF_fieldType), names[DMH_THIS]);
 929         }
 930         if (!isGetter) {
 931             outArgs[x] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
 932         }
 933         for (Object a : outArgs)  assert(a != null);
 934         names[LINKER_CALL] = new Name(linker, outArgs);
 935         if (needsCast && isGetter)
 936             names[POST_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[LINKER_CALL]);
 937         for (Name n : names)  assert(n != null);
 938 
 939         LambdaForm form = LambdaForm.create(ARG_LIMIT, names, RESULT, kind);
 940 
 941         if (LambdaForm.debugNames()) {
 942             // add some detail to the lambdaForm debugname,
 943             // significant only for debugging
 944             StringBuilder nameBuilder = new StringBuilder(unsafeMethodName);
 945             if (isStatic) {
 946                 nameBuilder.append("Static");
 947             } else {
 948                 nameBuilder.append("Field");
 949             }
 950             if (isNullRestricted) {
 951                 nameBuilder.append("NullRestricted");
 952             }
 953             if (needsCast) {
 954                 nameBuilder.append("Cast");
 955             }
 956             if (needsInit) {
 957                 nameBuilder.append("Init");
 958             }
 959             LambdaForm.associateWithDebugName(form, nameBuilder.toString());
 960         }
 961 
 962         // NF_UNSAFE uses field form, avoid circular dependency in interpreter
 963         form.compileToBytecode();
 964         return form;
 965     }
 966 
 967     /**
 968      * Pre-initialized NamedFunctions for bootstrapping purposes.
 969      */
 970     static final byte NF_internalMemberName = 0,
 971             NF_internalMemberNameEnsureInit = 1,
 972             NF_ensureInitialized = 2,
 973             NF_fieldOffset = 3,
 974             NF_checkBase = 4,
 975             NF_staticBase = 5,
 976             NF_staticOffset = 6,
 977             NF_checkCast = 7,
 978             NF_allocateInstance = 8,
 979             NF_constructorMethod = 9,
 980             NF_UNSAFE = 10,
 981             NF_checkReceiver = 11,
 982             NF_fieldType = 12,
 983             NF_staticFieldType = 13,
 984             NF_fieldLayout = 14,
 985             NF_nullCheck = 15,
 986             NF_LIMIT = 16;
 987 
 988     private static final @Stable NamedFunction[] NFS = new NamedFunction[NF_LIMIT];
 989 
 990     private static NamedFunction getFunction(byte func) {
 991         NamedFunction nf = NFS[func];
 992         if (nf != null) {
 993             return nf;
 994         }
 995         // Each nf must be statically invocable or we get tied up in our bootstraps.
 996         nf = NFS[func] = createFunction(func);
 997         assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf));
 998         return nf;
 999     }
1000 
1001     private static final MethodType CLS_OBJ_TYPE = MethodType.methodType(Class.class, Object.class);
1002     private static final MethodType INT_OBJ_TYPE = MethodType.methodType(int.class, Object.class);
1003 
1004     private static final MethodType OBJ_OBJ_TYPE = MethodType.methodType(Object.class, Object.class);
1005 
1006     private static final MethodType LONG_OBJ_TYPE = MethodType.methodType(long.class, Object.class);
1007 
1008     private static NamedFunction createFunction(byte func) {
1009         try {
1010             switch (func) {
1011                 case NF_internalMemberName:
1012                     return getNamedFunction("internalMemberName", OBJ_OBJ_TYPE);
1013                 case NF_internalMemberNameEnsureInit:
1014                     return getNamedFunction("internalMemberNameEnsureInit", OBJ_OBJ_TYPE);
1015                 case NF_ensureInitialized:
1016                     return getNamedFunction("ensureInitialized", MethodType.methodType(void.class, Object.class));
1017                 case NF_fieldOffset:
1018                     return getNamedFunction("fieldOffset", LONG_OBJ_TYPE);
1019                 case NF_checkBase:
1020                     return getNamedFunction("checkBase", OBJ_OBJ_TYPE);
1021                 case NF_staticBase:
1022                     return getNamedFunction("staticBase", OBJ_OBJ_TYPE);
1023                 case NF_staticOffset:
1024                     return getNamedFunction("staticOffset", LONG_OBJ_TYPE);
1025                 case NF_checkCast:
1026                     return getNamedFunction("checkCast", MethodType.methodType(Object.class, Object.class, Object.class));
1027                 case NF_allocateInstance:
1028                     return getNamedFunction("allocateInstance", OBJ_OBJ_TYPE);
1029                 case NF_constructorMethod:
1030                     return getNamedFunction("constructorMethod", OBJ_OBJ_TYPE);
1031                 case NF_UNSAFE:
1032                     MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getStatic);
1033                     return new NamedFunction(
1034                             MemberName.getFactory().resolveOrFail(REF_getStatic, member,
1035                                                                   DirectMethodHandle.class, LM_TRUSTED,
1036                                                                   NoSuchFieldException.class));
1037                 case NF_checkReceiver:
1038                     member = new MemberName(DirectMethodHandle.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual);
1039                     return new NamedFunction(
1040                             MemberName.getFactory().resolveOrFail(REF_invokeVirtual, member,
1041                                                                   DirectMethodHandle.class, LM_TRUSTED,
1042                                                                   NoSuchMethodException.class));
1043                 case NF_fieldType:
1044                     return getNamedFunction("fieldType", CLS_OBJ_TYPE);
1045                 case NF_staticFieldType:
1046                     return getNamedFunction("staticFieldType", CLS_OBJ_TYPE);
1047                 case NF_nullCheck:
1048                     return getNamedFunction("nullCheck", OBJ_OBJ_TYPE);
1049                 case NF_fieldLayout:
1050                     return getNamedFunction("fieldLayout", INT_OBJ_TYPE);
1051                 default:
1052                     throw newInternalError("Unknown function: " + func);
1053             }
1054         } catch (ReflectiveOperationException ex) {
1055             throw newInternalError(ex);
1056         }
1057     }
1058 
1059     private static NamedFunction getNamedFunction(String name, MethodType type)
1060         throws ReflectiveOperationException
1061     {
1062         MemberName member = new MemberName(DirectMethodHandle.class, name, type, REF_invokeStatic);
1063         return new NamedFunction(
1064                 MemberName.getFactory().resolveOrFail(REF_invokeStatic, member,
1065                                                       DirectMethodHandle.class, LM_TRUSTED,
1066                                                       NoSuchMethodException.class));
1067     }
1068 
1069     static {
1070         // The Holder class will contain pre-generated DirectMethodHandles resolved
1071         // speculatively using MemberName.getFactory().resolveOrNull. However, that
1072         // doesn't initialize the class, which subtly breaks inlining etc. By forcing
1073         // initialization of the Holder class we avoid these issues.
1074         UNSAFE.ensureClassInitialized(Holder.class);
1075     }
1076 
1077     /* Placeholder class for DirectMethodHandles generated ahead of time */
1078     @AOTSafeClassInitializer
1079     final class Holder {}
1080 }