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