1 /*
   2  * Copyright (c) 2008, 2022, 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.Unsafe;
  29 import jdk.internal.vm.annotation.ForceInline;
  30 import jdk.internal.vm.annotation.Stable;
  31 import sun.invoke.util.ValueConversions;
  32 import sun.invoke.util.VerifyAccess;
  33 import sun.invoke.util.Wrapper;
  34 
  35 import java.util.Arrays;
  36 import java.util.Objects;
  37 import java.util.function.Function;
  38 
  39 import static java.lang.invoke.LambdaForm.*;
  40 import static java.lang.invoke.LambdaForm.Kind.*;
  41 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  42 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  43 import static java.lang.invoke.MethodHandleStatics.newInternalError;
  44 import static java.lang.invoke.MethodTypeForm.*;
  45 
  46 /**
  47  * The flavor of method handle which implements a constant reference
  48  * to a class member.
  49  * @author jrose
  50  */
  51 sealed class DirectMethodHandle extends MethodHandle {
  52     final MemberName member;
  53     final boolean crackable;
  54 
  55     // Constructors and factory methods in this class *must* be package scoped or private.
  56     private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member, boolean crackable) {
  57         super(mtype, form);
  58         if (!member.isResolved())  throw new InternalError();
  59 
  60         if (member.getDeclaringClass().isInterface() &&
  61             member.getReferenceKind() == REF_invokeInterface &&
  62             member.isMethod() && !member.isAbstract()) {
  63             // Check for corner case: invokeinterface of Object method
  64             MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
  65             m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null, LM_TRUSTED);
  66             if (m != null && m.isPublic()) {
  67                 assert(member.getReferenceKind() == m.getReferenceKind());  // else this.form is wrong
  68                 member = m;
  69             }
  70         }
  71 
  72         this.member = member;
  73         this.crackable = crackable;
  74     }
  75 
  76     // Factory methods:
  77     static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) {
  78         MethodType mtype = member.getMethodOrFieldType();
  79         if (!member.isStatic()) {
  80             if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
  81                 throw new InternalError(member.toString());
  82             mtype = mtype.insertParameterTypes(0, refc);
  83         }
  84         if (!member.isField()) {
  85             // refKind reflects the original type of lookup via findSpecial or
  86             // findVirtual etc.
  87             return switch (refKind) {
  88                 case REF_invokeSpecial -> {
  89                     member = member.asSpecial();
  90                     // if caller is an interface we need to adapt to get the
  91                     // receiver check inserted
  92                     if (callerClass == null) {
  93                         throw new InternalError("callerClass must not be null for REF_invokeSpecial");
  94                     }
  95                     LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
  96                     yield new Special(mtype, lform, member, true, callerClass);
  97                 }
  98                 case REF_invokeInterface -> {
  99                     // for interfaces we always need the receiver typecheck,
 100                     // so we always pass 'true' to ensure we adapt if needed
 101                     // to include the REF_invokeSpecial case
 102                     LambdaForm lform = preparedLambdaForm(member, true);
 103                     yield new Interface(mtype, lform, member, true, refc);
 104                 }
 105                 default -> {
 106                     LambdaForm lform = preparedLambdaForm(member);
 107                     yield new DirectMethodHandle(mtype, lform, member, true);
 108                 }
 109             };
 110         } else {
 111             LambdaForm lform = preparedFieldLambdaForm(member);
 112             if (member.isStatic()) {
 113                 long offset = MethodHandleNatives.staticFieldOffset(member);
 114                 Object base = MethodHandleNatives.staticFieldBase(member);
 115                 return new StaticAccessor(mtype, lform, member, true, base, offset);
 116             } else {
 117                 long offset = MethodHandleNatives.objectFieldOffset(member);
 118                 assert(offset == (int)offset);
 119                 return new Accessor(mtype, lform, member, true, (int)offset);
 120             }
 121         }
 122     }
 123     static DirectMethodHandle make(Class<?> refc, MemberName member) {
 124         byte refKind = member.getReferenceKind();
 125         if (refKind == REF_invokeSpecial)
 126             refKind =  REF_invokeVirtual;
 127         return make(refKind, refc, member, null /* no callerClass context */);
 128     }
 129     static DirectMethodHandle make(MemberName member) {
 130         if (member.isConstructor())
 131             return makeAllocator(member.getDeclaringClass(), member);
 132         return make(member.getDeclaringClass(), member);
 133     }
 134     static DirectMethodHandle makeAllocator(Class<?> instanceClass, MemberName ctor) {
 135         assert(ctor.isConstructor()) : ctor;
 136         ctor = ctor.asConstructor();
 137         assert(ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
 138         MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
 139         LambdaForm lform = preparedLambdaForm(ctor);
 140         MemberName init = ctor.asSpecial();
 141         assert(init.getMethodType().returnType() == void.class);
 142         return new Constructor(mtype, lform, ctor, true, init, instanceClass);
 143     }
 144 
 145     @Override
 146     BoundMethodHandle rebind() {
 147         return BoundMethodHandle.makeReinvoker(this);
 148     }
 149 
 150     @Override
 151     MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 152         assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
 153         return new DirectMethodHandle(mt, lf, member, crackable);
 154     }
 155 
 156     @Override
 157     MethodHandle viewAsType(MethodType newType, boolean strict) {
 158         // No actual conversions, just a new view of the same method.
 159         // However, we must not expose a DMH that is crackable into a
 160         // MethodHandleInfo, so we return a cloned, uncrackable DMH
 161         assert(viewAsTypeChecks(newType, strict));
 162         assert(this.getClass() == DirectMethodHandle.class);  // must override in subclasses
 163         return new DirectMethodHandle(newType, form, member, false);
 164     }
 165 
 166     @Override
 167     boolean isCrackable() {
 168         return crackable;
 169     }
 170 
 171     @Override
 172     String internalProperties(int indentLevel) {
 173         return "\n" + debugPrefix(indentLevel) + "& DMH.MN=" + internalMemberName();
 174     }
 175 
 176     //// Implementation methods.
 177     @Override
 178     @ForceInline
 179     MemberName internalMemberName() {
 180         return member;
 181     }
 182 
 183     private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
 184 
 185     /**
 186      * Create a LF which can invoke the given method.
 187      * Cache and share this structure among all methods with
 188      * the same basicType and refKind.
 189      */
 190     private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) {
 191         assert(m.isInvocable()) : m;  // call preparedFieldLambdaForm instead
 192         MethodType mtype = m.getInvocationType().basicType();
 193         assert(!m.isMethodHandleInvoke()) : m;
 194         // MemberName.getReferenceKind represents the JVM optimized form of the call
 195         // as distinct from the "kind" passed to DMH.make which represents the original
 196         // bytecode-equivalent request. Specifically private/final methods that use a direct
 197         // call have getReferenceKind adapted to REF_invokeSpecial, even though the actual
 198         // invocation mode may be invokevirtual or invokeinterface.
 199         int which = switch (m.getReferenceKind()) {
 200             case REF_invokeVirtual    -> LF_INVVIRTUAL;
 201             case REF_invokeStatic     -> LF_INVSTATIC;
 202             case REF_invokeSpecial    -> LF_INVSPECIAL;
 203             case REF_invokeInterface  -> LF_INVINTERFACE;
 204             case REF_newInvokeSpecial -> LF_NEWINVSPECIAL;
 205             default -> throw new InternalError(m.toString());
 206         };
 207         if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
 208             // precompute the barrier-free version:
 209             preparedLambdaForm(mtype, which);
 210             which = LF_INVSTATIC_INIT;
 211         }
 212         if (which == LF_INVSPECIAL && adaptToSpecialIfc) {
 213             which = LF_INVSPECIAL_IFC;
 214         }
 215         LambdaForm lform = preparedLambdaForm(mtype, which);
 216         maybeCompile(lform, m);
 217         assert(lform.methodType().dropParameterTypes(0, 1)
 218                 .equals(m.getInvocationType().basicType()))
 219                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 220         return lform;
 221     }
 222 
 223     private static LambdaForm preparedLambdaForm(MemberName m) {
 224         return preparedLambdaForm(m, false);
 225     }
 226 
 227     private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
 228         LambdaForm lform = mtype.form().cachedLambdaForm(which);
 229         if (lform != null)  return lform;
 230         lform = makePreparedLambdaForm(mtype, which);
 231         return mtype.form().setCachedLambdaForm(which, lform);
 232     }
 233 
 234     static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
 235         boolean needsInit = (which == LF_INVSTATIC_INIT);
 236         boolean doesAlloc = (which == LF_NEWINVSPECIAL);
 237         boolean needsReceiverCheck = (which == LF_INVINTERFACE ||
 238                                       which == LF_INVSPECIAL_IFC);
 239 
 240         String linkerName;
 241         LambdaForm.Kind kind;
 242         switch (which) {
 243         case LF_INVVIRTUAL:    linkerName = "linkToVirtual";   kind = DIRECT_INVOKE_VIRTUAL;     break;
 244         case LF_INVSTATIC:     linkerName = "linkToStatic";    kind = DIRECT_INVOKE_STATIC;      break;
 245         case LF_INVSTATIC_INIT:linkerName = "linkToStatic";    kind = DIRECT_INVOKE_STATIC_INIT; break;
 246         case LF_INVSPECIAL_IFC:linkerName = "linkToSpecial";   kind = DIRECT_INVOKE_SPECIAL_IFC; break;
 247         case LF_INVSPECIAL:    linkerName = "linkToSpecial";   kind = DIRECT_INVOKE_SPECIAL;     break;
 248         case LF_INVINTERFACE:  linkerName = "linkToInterface"; kind = DIRECT_INVOKE_INTERFACE;   break;
 249         case LF_NEWINVSPECIAL: linkerName = "linkToSpecial";   kind = DIRECT_NEW_INVOKE_SPECIAL; break;
 250         default:  throw new InternalError("which="+which);
 251         }
 252 
 253         MethodType mtypeWithArg;
 254         if (doesAlloc) {
 255             var ptypes = mtype.ptypes();
 256             var newPtypes = new Class<?>[ptypes.length + 2];
 257             newPtypes[0] = Object.class; // insert newly allocated obj
 258             System.arraycopy(ptypes, 0, newPtypes, 1, ptypes.length);
 259             newPtypes[newPtypes.length - 1] = MemberName.class;
 260             mtypeWithArg = MethodType.methodType(void.class, newPtypes, true);
 261         } else {
 262             mtypeWithArg = mtype.appendParameterTypes(MemberName.class);
 263         }
 264         MemberName linker = new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
 265         try {
 266             linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, LM_TRUSTED,
 267                                               NoSuchMethodException.class);
 268         } catch (ReflectiveOperationException ex) {
 269             throw newInternalError(ex);
 270         }
 271         final int DMH_THIS    = 0;
 272         final int ARG_BASE    = 1;
 273         final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
 274         int nameCursor = ARG_LIMIT;
 275         final int NEW_OBJ     = (doesAlloc ? nameCursor++ : -1);
 276         final int GET_MEMBER  = nameCursor++;
 277         final int CHECK_RECEIVER = (needsReceiverCheck ? nameCursor++ : -1);
 278         final int LINKER_CALL = nameCursor++;
 279         Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
 280         assert(names.length == nameCursor);
 281         if (doesAlloc) {
 282             // names = { argx,y,z,... new C, init method }
 283             names[NEW_OBJ] = new Name(getFunction(NF_allocateInstance), names[DMH_THIS]);
 284             names[GET_MEMBER] = new Name(getFunction(NF_constructorMethod), names[DMH_THIS]);
 285         } else if (needsInit) {
 286             names[GET_MEMBER] = new Name(getFunction(NF_internalMemberNameEnsureInit), names[DMH_THIS]);
 287         } else {
 288             names[GET_MEMBER] = new Name(getFunction(NF_internalMemberName), names[DMH_THIS]);
 289         }
 290         assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]);
 291         Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
 292         if (needsReceiverCheck) {
 293             names[CHECK_RECEIVER] = new Name(getFunction(NF_checkReceiver), names[DMH_THIS], names[ARG_BASE]);
 294             outArgs[0] = names[CHECK_RECEIVER];
 295         }
 296         assert(outArgs[outArgs.length-1] == names[GET_MEMBER]);  // look, shifted args!
 297         int result = LAST_RESULT;
 298         if (doesAlloc) {
 299             assert(outArgs[outArgs.length-2] == names[NEW_OBJ]);  // got to move this one
 300             System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2);
 301             outArgs[0] = names[NEW_OBJ];
 302             result = NEW_OBJ;
 303         }
 304         names[LINKER_CALL] = new Name(linker, outArgs);
 305         LambdaForm lform = LambdaForm.create(ARG_LIMIT, names, result, kind);
 306 
 307         // This is a tricky bit of code.  Don't send it through the LF interpreter.
 308         lform.compileToBytecode();
 309         return lform;
 310     }
 311 
 312     /* assert */ static Object findDirectMethodHandle(Name name) {
 313         if (name.function.equals(getFunction(NF_internalMemberName)) ||
 314             name.function.equals(getFunction(NF_internalMemberNameEnsureInit)) ||
 315             name.function.equals(getFunction(NF_constructorMethod))) {
 316             assert(name.arguments.length == 1);
 317             return name.arguments[0];
 318         }
 319         return null;
 320     }
 321 
 322     private static void maybeCompile(LambdaForm lform, MemberName m) {
 323         if (lform.vmentry == null && VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
 324             // Help along bootstrapping...
 325             lform.compileToBytecode();
 326     }
 327 
 328     /** Static wrapper for DirectMethodHandle.internalMemberName. */
 329     @ForceInline
 330     /*non-public*/
 331     static Object internalMemberName(Object mh) {
 332         return ((DirectMethodHandle)mh).member;
 333     }
 334 
 335     /** Static wrapper for DirectMethodHandle.internalMemberName.
 336      * This one also forces initialization.
 337      */
 338     /*non-public*/
 339     static Object internalMemberNameEnsureInit(Object mh) {
 340         DirectMethodHandle dmh = (DirectMethodHandle)mh;
 341         dmh.ensureInitialized();
 342         return dmh.member;
 343     }
 344 
 345     /*non-public*/
 346     static boolean shouldBeInitialized(MemberName member) {
 347         switch (member.getReferenceKind()) {
 348         case REF_invokeStatic:
 349         case REF_getStatic:
 350         case REF_putStatic:
 351         case REF_newInvokeSpecial:
 352             break;
 353         default:
 354             // No need to initialize the class on this kind of member.
 355             return false;
 356         }
 357         Class<?> cls = member.getDeclaringClass();
 358         if (cls == ValueConversions.class ||
 359             cls == MethodHandleImpl.class ||
 360             cls == Invokers.class) {
 361             // These guys have lots of <clinit> DMH creation but we know
 362             // the MHs will not be used until the system is booted.
 363             return false;
 364         }
 365         if (VerifyAccess.isSamePackage(MethodHandle.class, cls) ||
 366             VerifyAccess.isSamePackage(ValueConversions.class, cls)) {
 367             // It is a system class.  It is probably in the process of
 368             // being initialized, but we will help it along just to be safe.
 369             UNSAFE.ensureClassInitialized(cls);
 370             return false;
 371         }
 372         return UNSAFE.shouldBeInitialized(cls);
 373     }
 374 
 375     private void ensureInitialized() {
 376         if (checkInitialized(member)) {
 377             // The coast is clear.  Delete the <clinit> barrier.
 378             updateForm(new Function<>() {
 379                 public LambdaForm apply(LambdaForm oldForm) {
 380                     return (member.isField() ? preparedFieldLambdaForm(member)
 381                                              : preparedLambdaForm(member));
 382                 }
 383             });
 384         }
 385     }
 386     private static boolean checkInitialized(MemberName member) {
 387         Class<?> defc = member.getDeclaringClass();
 388         UNSAFE.ensureClassInitialized(defc);
 389         // Once we get here either defc was fully initialized by another thread, or
 390         // defc was already being initialized by the current thread. In the latter case
 391         // the barrier must remain. We can detect this simply by checking if initialization
 392         // is still needed.
 393         return !UNSAFE.shouldBeInitialized(defc);
 394     }
 395 
 396     /*non-public*/
 397     static void ensureInitialized(Object mh) {
 398         ((DirectMethodHandle)mh).ensureInitialized();
 399     }
 400 
 401     /** This subclass represents invokespecial instructions. */
 402     static final class Special extends DirectMethodHandle {
 403         private final Class<?> caller;
 404         private Special(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> caller) {
 405             super(mtype, form, member, crackable);
 406             this.caller = caller;
 407         }
 408         @Override
 409         boolean isInvokeSpecial() {
 410             return true;
 411         }
 412         @Override
 413         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 414             return new Special(mt, lf, member, crackable, caller);
 415         }
 416         @Override
 417         MethodHandle viewAsType(MethodType newType, boolean strict) {
 418             assert(viewAsTypeChecks(newType, strict));
 419             return new Special(newType, form, member, false, caller);
 420         }
 421         Object checkReceiver(Object recv) {
 422             if (!caller.isInstance(recv)) {
 423                 if (recv != null) {
 424                     String msg = String.format("Receiver class %s is not a subclass of caller class %s",
 425                                                recv.getClass().getName(), caller.getName());
 426                     throw new IncompatibleClassChangeError(msg);
 427                 } else {
 428                     String msg = String.format("Cannot invoke %s with null receiver", member);
 429                     throw new NullPointerException(msg);
 430                 }
 431             }
 432             return recv;
 433         }
 434     }
 435 
 436     /** This subclass represents invokeinterface instructions. */
 437     static final class Interface extends DirectMethodHandle {
 438         private final Class<?> refc;
 439         private Interface(MethodType mtype, LambdaForm form, MemberName member, boolean crackable, Class<?> refc) {
 440             super(mtype, form, member, crackable);
 441             assert(refc.isInterface()) : refc;
 442             this.refc = refc;
 443         }
 444         @Override
 445         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 446             return new Interface(mt, lf, member, crackable, refc);
 447         }
 448         @Override
 449         MethodHandle viewAsType(MethodType newType, boolean strict) {
 450             assert(viewAsTypeChecks(newType, strict));
 451             return new Interface(newType, form, member, false, refc);
 452         }
 453         @Override
 454         Object checkReceiver(Object recv) {
 455             if (!refc.isInstance(recv)) {
 456                 if (recv != null) {
 457                     String msg = String.format("Receiver class %s does not implement the requested interface %s",
 458                                                recv.getClass().getName(), refc.getName());
 459                     throw new IncompatibleClassChangeError(msg);
 460                 } else {
 461                     String msg = String.format("Cannot invoke %s with null receiver", member);
 462                     throw new NullPointerException(msg);
 463                 }
 464             }
 465             return recv;
 466         }
 467     }
 468 
 469     /** Used for interface receiver type checks, by Interface and Special modes. */
 470     Object checkReceiver(Object recv) {
 471         throw new InternalError("Should only be invoked on a subclass");
 472     }
 473 
 474     /** This subclass handles constructor references. */
 475     static final class Constructor extends DirectMethodHandle {
 476         final MemberName initMethod;
 477         final Class<?>   instanceClass;
 478 
 479         private Constructor(MethodType mtype, LambdaForm form, MemberName constructor,
 480                             boolean crackable, MemberName initMethod, Class<?> instanceClass) {
 481             super(mtype, form, constructor, crackable);
 482             this.initMethod = initMethod;
 483             this.instanceClass = instanceClass;
 484             assert(initMethod.isResolved());
 485         }
 486         @Override
 487         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 488             return new Constructor(mt, lf, member, crackable, initMethod, instanceClass);
 489         }
 490         @Override
 491         MethodHandle viewAsType(MethodType newType, boolean strict) {
 492             assert(viewAsTypeChecks(newType, strict));
 493             return new Constructor(newType, form, member, false, initMethod, instanceClass);
 494         }
 495     }
 496 
 497     /*non-public*/
 498     static Object constructorMethod(Object mh) {
 499         Constructor dmh = (Constructor)mh;
 500         return dmh.initMethod;
 501     }
 502 
 503     /*non-public*/
 504     static Object allocateInstance(Object mh) throws InstantiationException {
 505         Constructor dmh = (Constructor)mh;
 506         return UNSAFE.allocateInstance(dmh.instanceClass);
 507     }
 508 
 509     /** This subclass handles non-static field references. */
 510     static final class Accessor extends DirectMethodHandle {
 511         final Class<?> fieldType;
 512         final int      fieldOffset;
 513         private Accessor(MethodType mtype, LambdaForm form, MemberName member,
 514                          boolean crackable, int fieldOffset) {
 515             super(mtype, form, member, crackable);
 516             this.fieldType   = member.getFieldType();
 517             this.fieldOffset = fieldOffset;
 518         }
 519 
 520         @Override Object checkCast(Object obj) {
 521             return fieldType.cast(obj);
 522         }
 523         @Override
 524         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 525             return new Accessor(mt, lf, member, crackable, fieldOffset);
 526         }
 527         @Override
 528         MethodHandle viewAsType(MethodType newType, boolean strict) {
 529             assert(viewAsTypeChecks(newType, strict));
 530             return new Accessor(newType, form, member, false, fieldOffset);
 531         }
 532     }
 533 
 534     @ForceInline
 535     /*non-public*/
 536     static long fieldOffset(Object accessorObj) {
 537         // Note: We return a long because that is what Unsafe.getObject likes.
 538         // We store a plain int because it is more compact.
 539         return ((Accessor)accessorObj).fieldOffset;
 540     }
 541 
 542     @ForceInline
 543     /*non-public*/
 544     static Object checkBase(Object obj) {
 545         // Note that the object's class has already been verified,
 546         // since the parameter type of the Accessor method handle
 547         // is either member.getDeclaringClass or a subclass.
 548         // This was verified in DirectMethodHandle.make.
 549         // Therefore, the only remaining check is for null.
 550         // Since this check is *not* guaranteed by Unsafe.getInt
 551         // and its siblings, we need to make an explicit one here.
 552         return Objects.requireNonNull(obj);
 553     }
 554 
 555     /** This subclass handles static field references. */
 556     static final class StaticAccessor extends DirectMethodHandle {
 557         private final Class<?> fieldType;
 558         private final Object   staticBase;
 559         private final long     staticOffset;
 560 
 561         private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member,
 562                                boolean crackable, Object staticBase, long staticOffset) {
 563             super(mtype, form, member, crackable);
 564             this.fieldType    = member.getFieldType();
 565             this.staticBase   = staticBase;
 566             this.staticOffset = staticOffset;
 567         }
 568 
 569         @Override Object checkCast(Object obj) {
 570             return fieldType.cast(obj);
 571         }
 572         @Override
 573         MethodHandle copyWith(MethodType mt, LambdaForm lf) {
 574             return new StaticAccessor(mt, lf, member, crackable, staticBase, staticOffset);
 575         }
 576         @Override
 577         MethodHandle viewAsType(MethodType newType, boolean strict) {
 578             assert(viewAsTypeChecks(newType, strict));
 579             return new StaticAccessor(newType, form, member, false, staticBase, staticOffset);
 580         }
 581     }
 582 
 583     @ForceInline
 584     /*non-public*/
 585     static Object nullCheck(Object obj) {
 586         return Objects.requireNonNull(obj);
 587     }
 588 
 589     @ForceInline
 590     /*non-public*/
 591     static Object staticBase(Object accessorObj) {
 592         return ((StaticAccessor)accessorObj).staticBase;
 593     }
 594 
 595     @ForceInline
 596     /*non-public*/
 597     static long staticOffset(Object accessorObj) {
 598         return ((StaticAccessor)accessorObj).staticOffset;
 599     }
 600 
 601     @ForceInline
 602     /*non-public*/
 603     static Object checkCast(Object mh, Object obj) {
 604         return ((DirectMethodHandle) mh).checkCast(obj);
 605     }
 606 
 607     @ForceInline
 608     /*non-public*/ static Class<?> fieldType(Object accessorObj) {
 609         return ((Accessor) accessorObj).fieldType;
 610     }
 611 
 612     @ForceInline
 613     /*non-public*/ static Class<?> staticFieldType(Object accessorObj) {
 614         return ((StaticAccessor) accessorObj).fieldType;
 615     }
 616 
 617     @ForceInline
 618     /*non-public*/ static Object zeroInstanceIfNull(Class<?> fieldType, Object obj) {
 619         return obj != null ? obj : UNSAFE.uninitializedDefaultValue(fieldType);
 620     }
 621 
 622     Object checkCast(Object obj) {
 623         return member.getMethodType().returnType().cast(obj);
 624     }
 625 
 626     // Caching machinery for field accessors:
 627     static final byte
 628             AF_GETFIELD        = 0,
 629             AF_PUTFIELD        = 1,
 630             AF_GETSTATIC       = 2,
 631             AF_PUTSTATIC       = 3,
 632             AF_GETSTATIC_INIT  = 4,
 633             AF_PUTSTATIC_INIT  = 5,
 634             AF_LIMIT           = 6;
 635     // Enumerate the different field kinds using Wrapper,
 636     // with an extra case added for checked references and value field access
 637     static final int
 638             FT_LAST_WRAPPER     = Wrapper.COUNT-1,
 639             FT_UNCHECKED_REF    = Wrapper.OBJECT.ordinal(),
 640             FT_CHECKED_REF      = FT_LAST_WRAPPER+1,
 641             FT_CHECKED_VALUE    = FT_LAST_WRAPPER+2,  // flat vs non-flat x null value vs null-restricted value
 642             FT_LIMIT            = FT_LAST_WRAPPER+6;
 643     private static int afIndex(byte formOp, boolean isVolatile, boolean isFlat, boolean isNullRestricted, int ftypeKind) {
 644         return ((formOp * FT_LIMIT * 2)
 645                 + (isVolatile ? FT_LIMIT : 0)
 646                 + (isFlat ? 1 : 0)
 647                 + (isNullRestricted ? 1 : 0)
 648                 + ftypeKind);
 649     }
 650     @Stable
 651     private static final LambdaForm[] ACCESSOR_FORMS
 652             = new LambdaForm[afIndex(AF_LIMIT, false, false, false, 0)];
 653     static int ftypeKind(Class<?> ftype) {
 654         if (ftype.isPrimitive()) {
 655             return Wrapper.forPrimitiveType(ftype).ordinal();
 656         } else if (ftype.isInterface() || ftype.isAssignableFrom(Object.class)) {
 657             // retyping can be done without a cast
 658             return FT_UNCHECKED_REF;
 659         } else {
 660             return ftype.isValue() ? FT_CHECKED_VALUE : FT_CHECKED_REF;
 661         }
 662     }
 663 
 664     /**
 665      * Create a LF which can access the given field.
 666      * Cache and share this structure among all fields with
 667      * the same basicType and refKind.
 668      */
 669     private static LambdaForm preparedFieldLambdaForm(MemberName m) {
 670         Class<?> ftype = m.getFieldType();
 671         byte formOp = switch (m.getReferenceKind()) {
 672             case REF_getField  -> AF_GETFIELD;
 673             case REF_putField  -> AF_PUTFIELD;
 674             case REF_getStatic -> AF_GETSTATIC;
 675             case REF_putStatic -> AF_PUTSTATIC;
 676             default -> throw new InternalError(m.toString());
 677         };
 678         if (shouldBeInitialized(m)) {
 679             // precompute the barrier-free version:
 680             preparedFieldLambdaForm(formOp, m.isVolatile(), m.isFlat(), m.isNullRestricted(), ftype);
 681             assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
 682                    (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
 683             formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
 684         }
 685         LambdaForm lform = preparedFieldLambdaForm(formOp, m.isVolatile(), m.isFlat(), m.isNullRestricted(), ftype);
 686         maybeCompile(lform, m);
 687         assert(lform.methodType().dropParameterTypes(0, 1)
 688                 .equals(m.getInvocationType().basicType()))
 689                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 690         return lform;
 691     }
 692 
 693     private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile,
 694                                                       boolean isFlat, boolean isNullRestricted, Class<?> ftype) {
 695         int ftypeKind = ftypeKind(ftype);
 696         int afIndex = afIndex(formOp, isVolatile, isFlat, isNullRestricted, ftypeKind);
 697         LambdaForm lform = ACCESSOR_FORMS[afIndex];
 698         if (lform != null)  return lform;
 699         lform = makePreparedFieldLambdaForm(formOp, isVolatile,isFlat, isNullRestricted, ftypeKind);
 700         ACCESSOR_FORMS[afIndex] = lform;  // don't bother with a CAS
 701         return lform;
 702     }
 703 
 704     private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
 705 
 706     private static Kind getFieldKind(boolean isGetter, boolean isVolatile, boolean isFlat, Wrapper wrapper) {
 707         if (isGetter) {
 708             if (isVolatile) {
 709                 switch (wrapper) {
 710                     case BOOLEAN: return GET_BOOLEAN_VOLATILE;
 711                     case BYTE:    return GET_BYTE_VOLATILE;
 712                     case SHORT:   return GET_SHORT_VOLATILE;
 713                     case CHAR:    return GET_CHAR_VOLATILE;
 714                     case INT:     return GET_INT_VOLATILE;
 715                     case LONG:    return GET_LONG_VOLATILE;
 716                     case FLOAT:   return GET_FLOAT_VOLATILE;
 717                     case DOUBLE:  return GET_DOUBLE_VOLATILE;
 718                     case OBJECT:  return isFlat ? GET_VALUE_VOLATILE : GET_REFERENCE_VOLATILE;
 719                 }
 720             } else {
 721                 switch (wrapper) {
 722                     case BOOLEAN: return GET_BOOLEAN;
 723                     case BYTE:    return GET_BYTE;
 724                     case SHORT:   return GET_SHORT;
 725                     case CHAR:    return GET_CHAR;
 726                     case INT:     return GET_INT;
 727                     case LONG:    return GET_LONG;
 728                     case FLOAT:   return GET_FLOAT;
 729                     case DOUBLE:  return GET_DOUBLE;
 730                     case OBJECT:  return isFlat ? GET_VALUE : GET_REFERENCE;
 731                 }
 732             }
 733         } else {
 734             if (isVolatile) {
 735                 switch (wrapper) {
 736                     case BOOLEAN: return PUT_BOOLEAN_VOLATILE;
 737                     case BYTE:    return PUT_BYTE_VOLATILE;
 738                     case SHORT:   return PUT_SHORT_VOLATILE;
 739                     case CHAR:    return PUT_CHAR_VOLATILE;
 740                     case INT:     return PUT_INT_VOLATILE;
 741                     case LONG:    return PUT_LONG_VOLATILE;
 742                     case FLOAT:   return PUT_FLOAT_VOLATILE;
 743                     case DOUBLE:  return PUT_DOUBLE_VOLATILE;
 744                     case OBJECT:  return isFlat ? PUT_VALUE_VOLATILE : PUT_REFERENCE_VOLATILE;
 745                 }
 746             } else {
 747                 switch (wrapper) {
 748                     case BOOLEAN: return PUT_BOOLEAN;
 749                     case BYTE:    return PUT_BYTE;
 750                     case SHORT:   return PUT_SHORT;
 751                     case CHAR:    return PUT_CHAR;
 752                     case INT:     return PUT_INT;
 753                     case LONG:    return PUT_LONG;
 754                     case FLOAT:   return PUT_FLOAT;
 755                     case DOUBLE:  return PUT_DOUBLE;
 756                     case OBJECT:  return isFlat ? PUT_VALUE : PUT_REFERENCE;
 757                 }
 758             }
 759         }
 760         throw new AssertionError("Invalid arguments");
 761     }
 762 
 763     /** invoked by GenerateJLIClassesHelper */
 764     static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftype) {
 765         return makePreparedFieldLambdaForm(formOp, isVolatile, false, false, ftype);
 766     }
 767 
 768     private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile,
 769                                                           boolean isFlat, boolean isNullRestricted, int ftypeKind) {
 770         boolean isGetter  = (formOp & 1) == (AF_GETFIELD & 1);
 771         boolean isStatic  = (formOp >= AF_GETSTATIC);
 772         boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
 773         boolean needsCast = (ftypeKind == FT_CHECKED_REF || ftypeKind == FT_CHECKED_VALUE);
 774         Wrapper fw = (needsCast ? Wrapper.OBJECT : ALL_WRAPPERS[ftypeKind]);
 775         Class<?> ft = fw.primitiveType();
 776         assert(needsCast ? true : ftypeKind(ft) == ftypeKind);
 777 
 778         // getObject, putIntVolatile, etc.
 779         Kind kind = getFieldKind(isGetter, isVolatile, isFlat, fw);
 780 
 781         MethodType linkerType;
 782         if (isGetter) {
 783             linkerType = isFlat
 784                             ? MethodType.methodType(ft, Object.class, long.class, Class.class)
 785                             : MethodType.methodType(ft, Object.class, long.class);
 786         } else {
 787             linkerType = isFlat
 788                             ? MethodType.methodType(void.class, Object.class, long.class, Class.class, ft)
 789                             : MethodType.methodType(void.class, Object.class, long.class, ft);
 790         }
 791         MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual);
 792         try {
 793             linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, LM_TRUSTED,
 794                                               NoSuchMethodException.class);
 795         } catch (ReflectiveOperationException ex) {
 796             throw newInternalError(ex);
 797         }
 798 
 799         // What is the external type of the lambda form?
 800         MethodType mtype;
 801         if (isGetter)
 802             mtype = MethodType.methodType(ft);
 803         else
 804             mtype = MethodType.methodType(void.class, ft);
 805         mtype = mtype.basicType();  // erase short to int, etc.
 806         if (!isStatic)
 807             mtype = mtype.insertParameterTypes(0, Object.class);
 808         final int DMH_THIS  = 0;
 809         final int ARG_BASE  = 1;
 810         final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
 811         // if this is for non-static access, the base pointer is stored at this index:
 812         final int OBJ_BASE  = isStatic ? -1 : ARG_BASE;
 813         // if this is for write access, the value to be written is stored at this index:
 814         final int SET_VALUE  = isGetter ? -1 : ARG_LIMIT - 1;
 815         int nameCursor = ARG_LIMIT;
 816         final int F_HOLDER  = (isStatic ? nameCursor++ : -1);  // static base if any
 817         final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
 818         final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
 819         final int U_HOLDER  = nameCursor++;  // UNSAFE holder
 820         final int INIT_BAR  = (needsInit ? nameCursor++ : -1);
 821         final int VALUE_TYPE = (isFlat ? nameCursor++ : -1);
 822         final int NULL_CHECK  = (isNullRestricted && !isGetter ? nameCursor++ : -1);
 823         final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
 824         final int LINKER_CALL = nameCursor++;
 825         final int FIELD_TYPE = (isNullRestricted && isGetter ? nameCursor++ : -1);
 826         final int ZERO_INSTANCE = (isNullRestricted && isGetter ? nameCursor++ : -1);
 827         final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
 828         final int RESULT    = nameCursor-1;  // either the call, zero instance, or the cast
 829         Name[] names = invokeArguments(nameCursor - ARG_LIMIT, mtype);
 830         if (needsInit)
 831             names[INIT_BAR] = new Name(getFunction(NF_ensureInitialized), names[DMH_THIS]);
 832         if (!isGetter) {
 833             if (isNullRestricted)
 834                 names[NULL_CHECK] = new Name(getFunction(NF_nullCheck), names[SET_VALUE]);
 835             if (needsCast)
 836                 names[PRE_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[SET_VALUE]);
 837         }
 838         Object[] outArgs = new Object[1 + linkerType.parameterCount()];
 839         assert (outArgs.length == (isGetter ? 3 : 4) + (isFlat ? 1 : 0));
 840         outArgs[0] = names[U_HOLDER] = new Name(getFunction(NF_UNSAFE));
 841         if (isStatic) {
 842             outArgs[1] = names[F_HOLDER]  = new Name(getFunction(NF_staticBase), names[DMH_THIS]);
 843             outArgs[2] = names[F_OFFSET]  = new Name(getFunction(NF_staticOffset), names[DMH_THIS]);
 844         } else {
 845             outArgs[1] = names[OBJ_CHECK] = new Name(getFunction(NF_checkBase), names[OBJ_BASE]);
 846             outArgs[2] = names[F_OFFSET]  = new Name(getFunction(NF_fieldOffset), names[DMH_THIS]);
 847         }
 848         int x = 3;
 849         if (isFlat) {
 850             outArgs[x++] = names[VALUE_TYPE] = isStatic ? new Name(getFunction(NF_staticFieldType), names[DMH_THIS])
 851                                                         : new Name(getFunction(NF_fieldType), names[DMH_THIS]);
 852         }
 853         if (!isGetter) {
 854             outArgs[x] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
 855         }
 856         for (Object a : outArgs)  assert(a != null);
 857         names[LINKER_CALL] = new Name(linker, outArgs);
 858         if (isGetter) {
 859             int argIndex = LINKER_CALL;
 860             if (isNullRestricted) {
 861                 names[FIELD_TYPE] = isStatic ? new Name(getFunction(NF_staticFieldType), names[DMH_THIS])
 862                                              : new Name(getFunction(NF_fieldType), names[DMH_THIS]);
 863                 names[ZERO_INSTANCE] = new Name(getFunction(NF_zeroInstance), names[FIELD_TYPE], names[LINKER_CALL]);
 864                 argIndex = ZERO_INSTANCE;
 865             }
 866             if (needsCast)
 867                 names[POST_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[argIndex]);
 868         }
 869         for (Name n : names)  assert(n != null);
 870 
 871         LambdaForm form;
 872         if (needsCast || needsInit) {
 873             // can't use the pre-generated form when casting and/or initializing
 874             form = LambdaForm.create(ARG_LIMIT, names, RESULT);
 875         } else {
 876             form = LambdaForm.create(ARG_LIMIT, names, RESULT, kind);
 877         }
 878 
 879         if (LambdaForm.debugNames()) {
 880             // add some detail to the lambdaForm debugname,
 881             // significant only for debugging
 882             StringBuilder nameBuilder = new StringBuilder(kind.methodName);
 883             if (isStatic) {
 884                 nameBuilder.append("Static");
 885             } else {
 886                 nameBuilder.append("Field");
 887             }
 888             if (needsCast) {
 889                 nameBuilder.append("Cast");
 890             }
 891             if (needsInit) {
 892                 nameBuilder.append("Init");
 893             }
 894             LambdaForm.associateWithDebugName(form, nameBuilder.toString());
 895         }
 896         return form;
 897     }
 898 
 899     /**
 900      * Pre-initialized NamedFunctions for bootstrapping purposes.
 901      */
 902     static final byte NF_internalMemberName = 0,
 903             NF_internalMemberNameEnsureInit = 1,
 904             NF_ensureInitialized = 2,
 905             NF_fieldOffset = 3,
 906             NF_checkBase = 4,
 907             NF_staticBase = 5,
 908             NF_staticOffset = 6,
 909             NF_checkCast = 7,
 910             NF_allocateInstance = 8,
 911             NF_constructorMethod = 9,
 912             NF_UNSAFE = 10,
 913             NF_checkReceiver = 11,
 914             NF_fieldType = 12,
 915             NF_staticFieldType = 13,
 916             NF_zeroInstance = 14,
 917             NF_nullCheck = 15,
 918             NF_LIMIT = 16;
 919 
 920     private static final @Stable NamedFunction[] NFS = new NamedFunction[NF_LIMIT];
 921 
 922     private static NamedFunction getFunction(byte func) {
 923         NamedFunction nf = NFS[func];
 924         if (nf != null) {
 925             return nf;
 926         }
 927         // Each nf must be statically invocable or we get tied up in our bootstraps.
 928         nf = NFS[func] = createFunction(func);
 929         assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf));
 930         return nf;
 931     }
 932 
 933     private static final MethodType CLS_OBJ_TYPE = MethodType.methodType(Class.class, Object.class);
 934 
 935     private static final MethodType OBJ_OBJ_TYPE = MethodType.methodType(Object.class, Object.class);
 936 
 937     private static final MethodType LONG_OBJ_TYPE = MethodType.methodType(long.class, Object.class);
 938 
 939     private static NamedFunction createFunction(byte func) {
 940         try {
 941             switch (func) {
 942                 case NF_internalMemberName:
 943                     return getNamedFunction("internalMemberName", OBJ_OBJ_TYPE);
 944                 case NF_internalMemberNameEnsureInit:
 945                     return getNamedFunction("internalMemberNameEnsureInit", OBJ_OBJ_TYPE);
 946                 case NF_ensureInitialized:
 947                     return getNamedFunction("ensureInitialized", MethodType.methodType(void.class, Object.class));
 948                 case NF_fieldOffset:
 949                     return getNamedFunction("fieldOffset", LONG_OBJ_TYPE);
 950                 case NF_checkBase:
 951                     return getNamedFunction("checkBase", OBJ_OBJ_TYPE);
 952                 case NF_staticBase:
 953                     return getNamedFunction("staticBase", OBJ_OBJ_TYPE);
 954                 case NF_staticOffset:
 955                     return getNamedFunction("staticOffset", LONG_OBJ_TYPE);
 956                 case NF_checkCast:
 957                     return getNamedFunction("checkCast", MethodType.methodType(Object.class, Object.class, Object.class));
 958                 case NF_allocateInstance:
 959                     return getNamedFunction("allocateInstance", OBJ_OBJ_TYPE);
 960                 case NF_constructorMethod:
 961                     return getNamedFunction("constructorMethod", OBJ_OBJ_TYPE);
 962                 case NF_UNSAFE:
 963                     MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getStatic);
 964                     return new NamedFunction(
 965                             MemberName.getFactory().resolveOrFail(REF_getStatic, member,
 966                                                                   DirectMethodHandle.class, LM_TRUSTED,
 967                                                                   NoSuchFieldException.class));
 968                 case NF_checkReceiver:
 969                     member = new MemberName(DirectMethodHandle.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual);
 970                     return new NamedFunction(
 971                             MemberName.getFactory().resolveOrFail(REF_invokeVirtual, member,
 972                                                                   DirectMethodHandle.class, LM_TRUSTED,
 973                                                                   NoSuchMethodException.class));
 974                 case NF_fieldType:
 975                     return getNamedFunction("fieldType", CLS_OBJ_TYPE);
 976                 case NF_staticFieldType:
 977                     return getNamedFunction("staticFieldType", CLS_OBJ_TYPE);
 978                 case NF_zeroInstance:
 979                     return getNamedFunction("zeroInstanceIfNull", MethodType.methodType(Object.class, Class.class, Object.class));
 980                 case NF_nullCheck:
 981                     return getNamedFunction("nullCheck", OBJ_OBJ_TYPE);
 982                 default:
 983                     throw newInternalError("Unknown function: " + func);
 984             }
 985         } catch (ReflectiveOperationException ex) {
 986             throw newInternalError(ex);
 987         }
 988     }
 989 
 990     private static NamedFunction getNamedFunction(String name, MethodType type)
 991         throws ReflectiveOperationException
 992     {
 993         MemberName member = new MemberName(DirectMethodHandle.class, name, type, REF_invokeStatic);
 994         return new NamedFunction(
 995                 MemberName.getFactory().resolveOrFail(REF_invokeStatic, member,
 996                                                       DirectMethodHandle.class, LM_TRUSTED,
 997                                                       NoSuchMethodException.class));
 998     }
 999 
1000     static {
1001         // The Holder class will contain pre-generated DirectMethodHandles resolved
1002         // speculatively using MemberName.getFactory().resolveOrNull. However, that
1003         // doesn't initialize the class, which subtly breaks inlining etc. By forcing
1004         // initialization of the Holder class we avoid these issues.
1005         UNSAFE.ensureClassInitialized(Holder.class);
1006     }
1007 
1008     /* Placeholder class for DirectMethodHandles generated ahead of time */
1009     final class Holder {}
1010 }