rt/emul/compact/src/main/java/java/lang/invoke/DirectMethodHandle.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 09 Aug 2014 11:11:13 +0200
branchjdk8-b132
changeset 1646 c880a8a8803b
child 1653 bd151459ee4f
permissions -rw-r--r--
Batch of classes necessary to implement invoke dynamic interfaces. Taken from JDK8 build 132
jaroslav@1646
     1
/*
jaroslav@1646
     2
 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
jaroslav@1646
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jaroslav@1646
     4
 *
jaroslav@1646
     5
 * This code is free software; you can redistribute it and/or modify it
jaroslav@1646
     6
 * under the terms of the GNU General Public License version 2 only, as
jaroslav@1646
     7
 * published by the Free Software Foundation.  Oracle designates this
jaroslav@1646
     8
 * particular file as subject to the "Classpath" exception as provided
jaroslav@1646
     9
 * by Oracle in the LICENSE file that accompanied this code.
jaroslav@1646
    10
 *
jaroslav@1646
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
jaroslav@1646
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jaroslav@1646
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jaroslav@1646
    14
 * version 2 for more details (a copy is included in the LICENSE file that
jaroslav@1646
    15
 * accompanied this code).
jaroslav@1646
    16
 *
jaroslav@1646
    17
 * You should have received a copy of the GNU General Public License version
jaroslav@1646
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
jaroslav@1646
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jaroslav@1646
    20
 *
jaroslav@1646
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jaroslav@1646
    22
 * or visit www.oracle.com if you need additional information or have any
jaroslav@1646
    23
 * questions.
jaroslav@1646
    24
 */
jaroslav@1646
    25
jaroslav@1646
    26
package java.lang.invoke;
jaroslav@1646
    27
jaroslav@1646
    28
import sun.misc.Unsafe;
jaroslav@1646
    29
import java.lang.reflect.Method;
jaroslav@1646
    30
import java.util.Arrays;
jaroslav@1646
    31
import sun.invoke.util.VerifyAccess;
jaroslav@1646
    32
import static java.lang.invoke.MethodHandleNatives.Constants.*;
jaroslav@1646
    33
import static java.lang.invoke.LambdaForm.*;
jaroslav@1646
    34
import static java.lang.invoke.MethodTypeForm.*;
jaroslav@1646
    35
import static java.lang.invoke.MethodHandleStatics.*;
jaroslav@1646
    36
import java.lang.ref.WeakReference;
jaroslav@1646
    37
import java.lang.reflect.Field;
jaroslav@1646
    38
import sun.invoke.util.ValueConversions;
jaroslav@1646
    39
import sun.invoke.util.VerifyType;
jaroslav@1646
    40
import sun.invoke.util.Wrapper;
jaroslav@1646
    41
jaroslav@1646
    42
/**
jaroslav@1646
    43
 * The flavor of method handle which implements a constant reference
jaroslav@1646
    44
 * to a class member.
jaroslav@1646
    45
 * @author jrose
jaroslav@1646
    46
 */
jaroslav@1646
    47
class DirectMethodHandle extends MethodHandle {
jaroslav@1646
    48
    final MemberName member;
jaroslav@1646
    49
jaroslav@1646
    50
    // Constructors and factory methods in this class *must* be package scoped or private.
jaroslav@1646
    51
    private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
jaroslav@1646
    52
        super(mtype, form);
jaroslav@1646
    53
        if (!member.isResolved())  throw new InternalError();
jaroslav@1646
    54
jaroslav@1646
    55
        if (member.getDeclaringClass().isInterface() &&
jaroslav@1646
    56
                member.isMethod() && !member.isAbstract()) {
jaroslav@1646
    57
            // Check for corner case: invokeinterface of Object method
jaroslav@1646
    58
            MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
jaroslav@1646
    59
            m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
jaroslav@1646
    60
            if (m != null && m.isPublic()) {
jaroslav@1646
    61
                member = m;
jaroslav@1646
    62
            }
jaroslav@1646
    63
        }
jaroslav@1646
    64
jaroslav@1646
    65
        this.member = member;
jaroslav@1646
    66
    }
jaroslav@1646
    67
jaroslav@1646
    68
    // Factory methods:
jaroslav@1646
    69
    static DirectMethodHandle make(byte refKind, Class<?> receiver, MemberName member) {
jaroslav@1646
    70
        MethodType mtype = member.getMethodOrFieldType();
jaroslav@1646
    71
        if (!member.isStatic()) {
jaroslav@1646
    72
            if (!member.getDeclaringClass().isAssignableFrom(receiver) || member.isConstructor())
jaroslav@1646
    73
                throw new InternalError(member.toString());
jaroslav@1646
    74
            mtype = mtype.insertParameterTypes(0, receiver);
jaroslav@1646
    75
        }
jaroslav@1646
    76
        if (!member.isField()) {
jaroslav@1646
    77
            if (refKind == REF_invokeSpecial) {
jaroslav@1646
    78
                member = member.asSpecial();
jaroslav@1646
    79
                LambdaForm lform = preparedLambdaForm(member);
jaroslav@1646
    80
                return new Special(mtype, lform, member);
jaroslav@1646
    81
            } else {
jaroslav@1646
    82
                LambdaForm lform = preparedLambdaForm(member);
jaroslav@1646
    83
                return new DirectMethodHandle(mtype, lform, member);
jaroslav@1646
    84
            }
jaroslav@1646
    85
        } else {
jaroslav@1646
    86
            LambdaForm lform = preparedFieldLambdaForm(member);
jaroslav@1646
    87
            if (member.isStatic()) {
jaroslav@1646
    88
                long offset = MethodHandleNatives.staticFieldOffset(member);
jaroslav@1646
    89
                Object base = MethodHandleNatives.staticFieldBase(member);
jaroslav@1646
    90
                return new StaticAccessor(mtype, lform, member, base, offset);
jaroslav@1646
    91
            } else {
jaroslav@1646
    92
                long offset = MethodHandleNatives.objectFieldOffset(member);
jaroslav@1646
    93
                assert(offset == (int)offset);
jaroslav@1646
    94
                return new Accessor(mtype, lform, member, (int)offset);
jaroslav@1646
    95
            }
jaroslav@1646
    96
        }
jaroslav@1646
    97
    }
jaroslav@1646
    98
    static DirectMethodHandle make(Class<?> receiver, MemberName member) {
jaroslav@1646
    99
        byte refKind = member.getReferenceKind();
jaroslav@1646
   100
        if (refKind == REF_invokeSpecial)
jaroslav@1646
   101
            refKind =  REF_invokeVirtual;
jaroslav@1646
   102
        return make(refKind, receiver, member);
jaroslav@1646
   103
    }
jaroslav@1646
   104
    static DirectMethodHandle make(MemberName member) {
jaroslav@1646
   105
        if (member.isConstructor())
jaroslav@1646
   106
            return makeAllocator(member);
jaroslav@1646
   107
        return make(member.getDeclaringClass(), member);
jaroslav@1646
   108
    }
jaroslav@1646
   109
    static DirectMethodHandle make(Method method) {
jaroslav@1646
   110
        return make(method.getDeclaringClass(), new MemberName(method));
jaroslav@1646
   111
    }
jaroslav@1646
   112
    static DirectMethodHandle make(Field field) {
jaroslav@1646
   113
        return make(field.getDeclaringClass(), new MemberName(field));
jaroslav@1646
   114
    }
jaroslav@1646
   115
    private static DirectMethodHandle makeAllocator(MemberName ctor) {
jaroslav@1646
   116
        assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
jaroslav@1646
   117
        Class<?> instanceClass = ctor.getDeclaringClass();
jaroslav@1646
   118
        ctor = ctor.asConstructor();
jaroslav@1646
   119
        assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
jaroslav@1646
   120
        MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
jaroslav@1646
   121
        LambdaForm lform = preparedLambdaForm(ctor);
jaroslav@1646
   122
        MemberName init = ctor.asSpecial();
jaroslav@1646
   123
        assert(init.getMethodType().returnType() == void.class);
jaroslav@1646
   124
        return new Constructor(mtype, lform, ctor, init, instanceClass);
jaroslav@1646
   125
    }
jaroslav@1646
   126
jaroslav@1646
   127
    @Override
jaroslav@1646
   128
    MethodHandle copyWith(MethodType mt, LambdaForm lf) {
jaroslav@1646
   129
        return new DirectMethodHandle(mt, lf, member);
jaroslav@1646
   130
    }
jaroslav@1646
   131
jaroslav@1646
   132
    @Override
jaroslav@1646
   133
    String internalProperties() {
jaroslav@1646
   134
        return "/DMH="+member.toString();
jaroslav@1646
   135
    }
jaroslav@1646
   136
jaroslav@1646
   137
    //// Implementation methods.
jaroslav@1646
   138
    @Override
jaroslav@1646
   139
    MethodHandle viewAsType(MethodType newType) {
jaroslav@1646
   140
        return new DirectMethodHandle(newType, form, member);
jaroslav@1646
   141
    }
jaroslav@1646
   142
    @Override
jaroslav@1646
   143
    @ForceInline
jaroslav@1646
   144
    MemberName internalMemberName() {
jaroslav@1646
   145
        return member;
jaroslav@1646
   146
    }
jaroslav@1646
   147
jaroslav@1646
   148
    @Override
jaroslav@1646
   149
    MethodHandle bindArgument(int pos, char basicType, Object value) {
jaroslav@1646
   150
        // If the member needs dispatching, do so.
jaroslav@1646
   151
        if (pos == 0 && basicType == 'L') {
jaroslav@1646
   152
            DirectMethodHandle concrete = maybeRebind(value);
jaroslav@1646
   153
            if (concrete != null)
jaroslav@1646
   154
                return concrete.bindReceiver(value);
jaroslav@1646
   155
        }
jaroslav@1646
   156
        return super.bindArgument(pos, basicType, value);
jaroslav@1646
   157
    }
jaroslav@1646
   158
jaroslav@1646
   159
    @Override
jaroslav@1646
   160
    MethodHandle bindReceiver(Object receiver) {
jaroslav@1646
   161
        // If the member needs dispatching, do so.
jaroslav@1646
   162
        DirectMethodHandle concrete = maybeRebind(receiver);
jaroslav@1646
   163
        if (concrete != null)
jaroslav@1646
   164
            return concrete.bindReceiver(receiver);
jaroslav@1646
   165
        return super.bindReceiver(receiver);
jaroslav@1646
   166
    }
jaroslav@1646
   167
jaroslav@1646
   168
    private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
jaroslav@1646
   169
jaroslav@1646
   170
    private DirectMethodHandle maybeRebind(Object receiver) {
jaroslav@1646
   171
        if (receiver != null) {
jaroslav@1646
   172
            switch (member.getReferenceKind()) {
jaroslav@1646
   173
            case REF_invokeInterface:
jaroslav@1646
   174
            case REF_invokeVirtual:
jaroslav@1646
   175
                // Pre-dispatch the member.
jaroslav@1646
   176
                Class<?> concreteClass = receiver.getClass();
jaroslav@1646
   177
                MemberName concrete = new MemberName(concreteClass, member.getName(), member.getMethodType(), REF_invokeSpecial);
jaroslav@1646
   178
                concrete = IMPL_NAMES.resolveOrNull(REF_invokeSpecial, concrete, concreteClass);
jaroslav@1646
   179
                if (concrete != null)
jaroslav@1646
   180
                    return new DirectMethodHandle(type(), preparedLambdaForm(concrete), concrete);
jaroslav@1646
   181
                break;
jaroslav@1646
   182
            }
jaroslav@1646
   183
        }
jaroslav@1646
   184
        return null;
jaroslav@1646
   185
    }
jaroslav@1646
   186
jaroslav@1646
   187
    /**
jaroslav@1646
   188
     * Create a LF which can invoke the given method.
jaroslav@1646
   189
     * Cache and share this structure among all methods with
jaroslav@1646
   190
     * the same basicType and refKind.
jaroslav@1646
   191
     */
jaroslav@1646
   192
    private static LambdaForm preparedLambdaForm(MemberName m) {
jaroslav@1646
   193
        assert(m.isInvocable()) : m;  // call preparedFieldLambdaForm instead
jaroslav@1646
   194
        MethodType mtype = m.getInvocationType().basicType();
jaroslav@1646
   195
        assert(!m.isMethodHandleInvoke() || "invokeBasic".equals(m.getName())) : m;
jaroslav@1646
   196
        int which;
jaroslav@1646
   197
        switch (m.getReferenceKind()) {
jaroslav@1646
   198
        case REF_invokeVirtual:    which = LF_INVVIRTUAL;    break;
jaroslav@1646
   199
        case REF_invokeStatic:     which = LF_INVSTATIC;     break;
jaroslav@1646
   200
        case REF_invokeSpecial:    which = LF_INVSPECIAL;    break;
jaroslav@1646
   201
        case REF_invokeInterface:  which = LF_INVINTERFACE;  break;
jaroslav@1646
   202
        case REF_newInvokeSpecial: which = LF_NEWINVSPECIAL; break;
jaroslav@1646
   203
        default:  throw new InternalError(m.toString());
jaroslav@1646
   204
        }
jaroslav@1646
   205
        if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
jaroslav@1646
   206
            // precompute the barrier-free version:
jaroslav@1646
   207
            preparedLambdaForm(mtype, which);
jaroslav@1646
   208
            which = LF_INVSTATIC_INIT;
jaroslav@1646
   209
        }
jaroslav@1646
   210
        LambdaForm lform = preparedLambdaForm(mtype, which);
jaroslav@1646
   211
        maybeCompile(lform, m);
jaroslav@1646
   212
        assert(lform.methodType().dropParameterTypes(0, 1)
jaroslav@1646
   213
                .equals(m.getInvocationType().basicType()))
jaroslav@1646
   214
                : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
jaroslav@1646
   215
        return lform;
jaroslav@1646
   216
    }
jaroslav@1646
   217
jaroslav@1646
   218
    private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
jaroslav@1646
   219
        LambdaForm lform = mtype.form().cachedLambdaForm(which);
jaroslav@1646
   220
        if (lform != null)  return lform;
jaroslav@1646
   221
        lform = makePreparedLambdaForm(mtype, which);
jaroslav@1646
   222
        return mtype.form().setCachedLambdaForm(which, lform);
jaroslav@1646
   223
    }
jaroslav@1646
   224
jaroslav@1646
   225
    private static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
jaroslav@1646
   226
        boolean needsInit = (which == LF_INVSTATIC_INIT);
jaroslav@1646
   227
        boolean doesAlloc = (which == LF_NEWINVSPECIAL);
jaroslav@1646
   228
        String linkerName, lambdaName;
jaroslav@1646
   229
        switch (which) {
jaroslav@1646
   230
        case LF_INVVIRTUAL:    linkerName = "linkToVirtual";    lambdaName = "DMH.invokeVirtual";    break;
jaroslav@1646
   231
        case LF_INVSTATIC:     linkerName = "linkToStatic";     lambdaName = "DMH.invokeStatic";     break;
jaroslav@1646
   232
        case LF_INVSTATIC_INIT:linkerName = "linkToStatic";     lambdaName = "DMH.invokeStaticInit"; break;
jaroslav@1646
   233
        case LF_INVSPECIAL:    linkerName = "linkToSpecial";    lambdaName = "DMH.invokeSpecial";    break;
jaroslav@1646
   234
        case LF_INVINTERFACE:  linkerName = "linkToInterface";  lambdaName = "DMH.invokeInterface";  break;
jaroslav@1646
   235
        case LF_NEWINVSPECIAL: linkerName = "linkToSpecial";    lambdaName = "DMH.newInvokeSpecial"; break;
jaroslav@1646
   236
        default:  throw new InternalError("which="+which);
jaroslav@1646
   237
        }
jaroslav@1646
   238
        MethodType mtypeWithArg = mtype.appendParameterTypes(MemberName.class);
jaroslav@1646
   239
        if (doesAlloc)
jaroslav@1646
   240
            mtypeWithArg = mtypeWithArg
jaroslav@1646
   241
                    .insertParameterTypes(0, Object.class)  // insert newly allocated obj
jaroslav@1646
   242
                    .changeReturnType(void.class);          // <init> returns void
jaroslav@1646
   243
        MemberName linker = new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
jaroslav@1646
   244
        try {
jaroslav@1646
   245
            linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
jaroslav@1646
   246
        } catch (ReflectiveOperationException ex) {
jaroslav@1646
   247
            throw newInternalError(ex);
jaroslav@1646
   248
        }
jaroslav@1646
   249
        final int DMH_THIS    = 0;
jaroslav@1646
   250
        final int ARG_BASE    = 1;
jaroslav@1646
   251
        final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
jaroslav@1646
   252
        int nameCursor = ARG_LIMIT;
jaroslav@1646
   253
        final int NEW_OBJ     = (doesAlloc ? nameCursor++ : -1);
jaroslav@1646
   254
        final int GET_MEMBER  = nameCursor++;
jaroslav@1646
   255
        final int LINKER_CALL = nameCursor++;
jaroslav@1646
   256
        Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
jaroslav@1646
   257
        assert(names.length == nameCursor);
jaroslav@1646
   258
        if (doesAlloc) {
jaroslav@1646
   259
            // names = { argx,y,z,... new C, init method }
jaroslav@1646
   260
            names[NEW_OBJ] = new Name(Lazy.NF_allocateInstance, names[DMH_THIS]);
jaroslav@1646
   261
            names[GET_MEMBER] = new Name(Lazy.NF_constructorMethod, names[DMH_THIS]);
jaroslav@1646
   262
        } else if (needsInit) {
jaroslav@1646
   263
            names[GET_MEMBER] = new Name(Lazy.NF_internalMemberNameEnsureInit, names[DMH_THIS]);
jaroslav@1646
   264
        } else {
jaroslav@1646
   265
            names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]);
jaroslav@1646
   266
        }
jaroslav@1646
   267
        Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
jaroslav@1646
   268
        assert(outArgs[outArgs.length-1] == names[GET_MEMBER]);  // look, shifted args!
jaroslav@1646
   269
        int result = LambdaForm.LAST_RESULT;
jaroslav@1646
   270
        if (doesAlloc) {
jaroslav@1646
   271
            assert(outArgs[outArgs.length-2] == names[NEW_OBJ]);  // got to move this one
jaroslav@1646
   272
            System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2);
jaroslav@1646
   273
            outArgs[0] = names[NEW_OBJ];
jaroslav@1646
   274
            result = NEW_OBJ;
jaroslav@1646
   275
        }
jaroslav@1646
   276
        names[LINKER_CALL] = new Name(linker, outArgs);
jaroslav@1646
   277
        lambdaName += "_" + LambdaForm.basicTypeSignature(mtype);
jaroslav@1646
   278
        LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result);
jaroslav@1646
   279
        // This is a tricky bit of code.  Don't send it through the LF interpreter.
jaroslav@1646
   280
        lform.compileToBytecode();
jaroslav@1646
   281
        return lform;
jaroslav@1646
   282
    }
jaroslav@1646
   283
jaroslav@1646
   284
    private static void maybeCompile(LambdaForm lform, MemberName m) {
jaroslav@1646
   285
        if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
jaroslav@1646
   286
            // Help along bootstrapping...
jaroslav@1646
   287
            lform.compileToBytecode();
jaroslav@1646
   288
    }
jaroslav@1646
   289
jaroslav@1646
   290
    /** Static wrapper for DirectMethodHandle.internalMemberName. */
jaroslav@1646
   291
    @ForceInline
jaroslav@1646
   292
    /*non-public*/ static Object internalMemberName(Object mh) {
jaroslav@1646
   293
        return ((DirectMethodHandle)mh).member;
jaroslav@1646
   294
    }
jaroslav@1646
   295
jaroslav@1646
   296
    /** Static wrapper for DirectMethodHandle.internalMemberName.
jaroslav@1646
   297
     * This one also forces initialization.
jaroslav@1646
   298
     */
jaroslav@1646
   299
    /*non-public*/ static Object internalMemberNameEnsureInit(Object mh) {
jaroslav@1646
   300
        DirectMethodHandle dmh = (DirectMethodHandle)mh;
jaroslav@1646
   301
        dmh.ensureInitialized();
jaroslav@1646
   302
        return dmh.member;
jaroslav@1646
   303
    }
jaroslav@1646
   304
jaroslav@1646
   305
    /*non-public*/ static
jaroslav@1646
   306
    boolean shouldBeInitialized(MemberName member) {
jaroslav@1646
   307
        switch (member.getReferenceKind()) {
jaroslav@1646
   308
        case REF_invokeStatic:
jaroslav@1646
   309
        case REF_getStatic:
jaroslav@1646
   310
        case REF_putStatic:
jaroslav@1646
   311
        case REF_newInvokeSpecial:
jaroslav@1646
   312
            break;
jaroslav@1646
   313
        default:
jaroslav@1646
   314
            // No need to initialize the class on this kind of member.
jaroslav@1646
   315
            return false;
jaroslav@1646
   316
        }
jaroslav@1646
   317
        Class<?> cls = member.getDeclaringClass();
jaroslav@1646
   318
        if (cls == ValueConversions.class ||
jaroslav@1646
   319
            cls == MethodHandleImpl.class ||
jaroslav@1646
   320
            cls == Invokers.class) {
jaroslav@1646
   321
            // These guys have lots of <clinit> DMH creation but we know
jaroslav@1646
   322
            // the MHs will not be used until the system is booted.
jaroslav@1646
   323
            return false;
jaroslav@1646
   324
        }
jaroslav@1646
   325
        if (VerifyAccess.isSamePackage(MethodHandle.class, cls) ||
jaroslav@1646
   326
            VerifyAccess.isSamePackage(ValueConversions.class, cls)) {
jaroslav@1646
   327
            // It is a system class.  It is probably in the process of
jaroslav@1646
   328
            // being initialized, but we will help it along just to be safe.
jaroslav@1646
   329
            if (UNSAFE.shouldBeInitialized(cls)) {
jaroslav@1646
   330
                UNSAFE.ensureClassInitialized(cls);
jaroslav@1646
   331
            }
jaroslav@1646
   332
            return false;
jaroslav@1646
   333
        }
jaroslav@1646
   334
        return UNSAFE.shouldBeInitialized(cls);
jaroslav@1646
   335
    }
jaroslav@1646
   336
jaroslav@1646
   337
    private static class EnsureInitialized extends ClassValue<WeakReference<Thread>> {
jaroslav@1646
   338
        @Override
jaroslav@1646
   339
        protected WeakReference<Thread> computeValue(Class<?> type) {
jaroslav@1646
   340
            UNSAFE.ensureClassInitialized(type);
jaroslav@1646
   341
            if (UNSAFE.shouldBeInitialized(type))
jaroslav@1646
   342
                // If the previous call didn't block, this can happen.
jaroslav@1646
   343
                // We are executing inside <clinit>.
jaroslav@1646
   344
                return new WeakReference<>(Thread.currentThread());
jaroslav@1646
   345
            return null;
jaroslav@1646
   346
        }
jaroslav@1646
   347
        static final EnsureInitialized INSTANCE = new EnsureInitialized();
jaroslav@1646
   348
    }
jaroslav@1646
   349
jaroslav@1646
   350
    private void ensureInitialized() {
jaroslav@1646
   351
        if (checkInitialized(member)) {
jaroslav@1646
   352
            // The coast is clear.  Delete the <clinit> barrier.
jaroslav@1646
   353
            if (member.isField())
jaroslav@1646
   354
                updateForm(preparedFieldLambdaForm(member));
jaroslav@1646
   355
            else
jaroslav@1646
   356
                updateForm(preparedLambdaForm(member));
jaroslav@1646
   357
        }
jaroslav@1646
   358
    }
jaroslav@1646
   359
    private static boolean checkInitialized(MemberName member) {
jaroslav@1646
   360
        Class<?> defc = member.getDeclaringClass();
jaroslav@1646
   361
        WeakReference<Thread> ref = EnsureInitialized.INSTANCE.get(defc);
jaroslav@1646
   362
        if (ref == null) {
jaroslav@1646
   363
            return true;  // the final state
jaroslav@1646
   364
        }
jaroslav@1646
   365
        Thread clinitThread = ref.get();
jaroslav@1646
   366
        // Somebody may still be running defc.<clinit>.
jaroslav@1646
   367
        if (clinitThread == Thread.currentThread()) {
jaroslav@1646
   368
            // If anybody is running defc.<clinit>, it is this thread.
jaroslav@1646
   369
            if (UNSAFE.shouldBeInitialized(defc))
jaroslav@1646
   370
                // Yes, we are running it; keep the barrier for now.
jaroslav@1646
   371
                return false;
jaroslav@1646
   372
        } else {
jaroslav@1646
   373
            // We are in a random thread.  Block.
jaroslav@1646
   374
            UNSAFE.ensureClassInitialized(defc);
jaroslav@1646
   375
        }
jaroslav@1646
   376
        assert(!UNSAFE.shouldBeInitialized(defc));
jaroslav@1646
   377
        // put it into the final state
jaroslav@1646
   378
        EnsureInitialized.INSTANCE.remove(defc);
jaroslav@1646
   379
        return true;
jaroslav@1646
   380
    }
jaroslav@1646
   381
jaroslav@1646
   382
    /*non-public*/ static void ensureInitialized(Object mh) {
jaroslav@1646
   383
        ((DirectMethodHandle)mh).ensureInitialized();
jaroslav@1646
   384
    }
jaroslav@1646
   385
jaroslav@1646
   386
    /** This subclass represents invokespecial instructions. */
jaroslav@1646
   387
    static class Special extends DirectMethodHandle {
jaroslav@1646
   388
        private Special(MethodType mtype, LambdaForm form, MemberName member) {
jaroslav@1646
   389
            super(mtype, form, member);
jaroslav@1646
   390
        }
jaroslav@1646
   391
        @Override
jaroslav@1646
   392
        boolean isInvokeSpecial() {
jaroslav@1646
   393
            return true;
jaroslav@1646
   394
        }
jaroslav@1646
   395
        @Override
jaroslav@1646
   396
        MethodHandle viewAsType(MethodType newType) {
jaroslav@1646
   397
            return new Special(newType, form, member);
jaroslav@1646
   398
        }
jaroslav@1646
   399
    }
jaroslav@1646
   400
jaroslav@1646
   401
    /** This subclass handles constructor references. */
jaroslav@1646
   402
    static class Constructor extends DirectMethodHandle {
jaroslav@1646
   403
        final MemberName initMethod;
jaroslav@1646
   404
        final Class<?>   instanceClass;
jaroslav@1646
   405
jaroslav@1646
   406
        private Constructor(MethodType mtype, LambdaForm form, MemberName constructor,
jaroslav@1646
   407
                            MemberName initMethod, Class<?> instanceClass) {
jaroslav@1646
   408
            super(mtype, form, constructor);
jaroslav@1646
   409
            this.initMethod = initMethod;
jaroslav@1646
   410
            this.instanceClass = instanceClass;
jaroslav@1646
   411
            assert(initMethod.isResolved());
jaroslav@1646
   412
        }
jaroslav@1646
   413
        @Override
jaroslav@1646
   414
        MethodHandle viewAsType(MethodType newType) {
jaroslav@1646
   415
            return new Constructor(newType, form, member, initMethod, instanceClass);
jaroslav@1646
   416
        }
jaroslav@1646
   417
    }
jaroslav@1646
   418
jaroslav@1646
   419
    /*non-public*/ static Object constructorMethod(Object mh) {
jaroslav@1646
   420
        Constructor dmh = (Constructor)mh;
jaroslav@1646
   421
        return dmh.initMethod;
jaroslav@1646
   422
    }
jaroslav@1646
   423
jaroslav@1646
   424
    /*non-public*/ static Object allocateInstance(Object mh) throws InstantiationException {
jaroslav@1646
   425
        Constructor dmh = (Constructor)mh;
jaroslav@1646
   426
        return UNSAFE.allocateInstance(dmh.instanceClass);
jaroslav@1646
   427
    }
jaroslav@1646
   428
jaroslav@1646
   429
    /** This subclass handles non-static field references. */
jaroslav@1646
   430
    static class Accessor extends DirectMethodHandle {
jaroslav@1646
   431
        final Class<?> fieldType;
jaroslav@1646
   432
        final int      fieldOffset;
jaroslav@1646
   433
        private Accessor(MethodType mtype, LambdaForm form, MemberName member,
jaroslav@1646
   434
                         int fieldOffset) {
jaroslav@1646
   435
            super(mtype, form, member);
jaroslav@1646
   436
            this.fieldType   = member.getFieldType();
jaroslav@1646
   437
            this.fieldOffset = fieldOffset;
jaroslav@1646
   438
        }
jaroslav@1646
   439
jaroslav@1646
   440
        @Override Object checkCast(Object obj) {
jaroslav@1646
   441
            return fieldType.cast(obj);
jaroslav@1646
   442
        }
jaroslav@1646
   443
        @Override
jaroslav@1646
   444
        MethodHandle viewAsType(MethodType newType) {
jaroslav@1646
   445
            return new Accessor(newType, form, member, fieldOffset);
jaroslav@1646
   446
        }
jaroslav@1646
   447
    }
jaroslav@1646
   448
jaroslav@1646
   449
    @ForceInline
jaroslav@1646
   450
    /*non-public*/ static long fieldOffset(Object accessorObj) {
jaroslav@1646
   451
        // Note: We return a long because that is what Unsafe.getObject likes.
jaroslav@1646
   452
        // We store a plain int because it is more compact.
jaroslav@1646
   453
        return ((Accessor)accessorObj).fieldOffset;
jaroslav@1646
   454
    }
jaroslav@1646
   455
jaroslav@1646
   456
    @ForceInline
jaroslav@1646
   457
    /*non-public*/ static Object checkBase(Object obj) {
jaroslav@1646
   458
        // Note that the object's class has already been verified,
jaroslav@1646
   459
        // since the parameter type of the Accessor method handle
jaroslav@1646
   460
        // is either member.getDeclaringClass or a subclass.
jaroslav@1646
   461
        // This was verified in DirectMethodHandle.make.
jaroslav@1646
   462
        // Therefore, the only remaining check is for null.
jaroslav@1646
   463
        // Since this check is *not* guaranteed by Unsafe.getInt
jaroslav@1646
   464
        // and its siblings, we need to make an explicit one here.
jaroslav@1646
   465
        obj.getClass();  // maybe throw NPE
jaroslav@1646
   466
        return obj;
jaroslav@1646
   467
    }
jaroslav@1646
   468
jaroslav@1646
   469
    /** This subclass handles static field references. */
jaroslav@1646
   470
    static class StaticAccessor extends DirectMethodHandle {
jaroslav@1646
   471
        final private Class<?> fieldType;
jaroslav@1646
   472
        final private Object   staticBase;
jaroslav@1646
   473
        final private long     staticOffset;
jaroslav@1646
   474
jaroslav@1646
   475
        private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member,
jaroslav@1646
   476
                               Object staticBase, long staticOffset) {
jaroslav@1646
   477
            super(mtype, form, member);
jaroslav@1646
   478
            this.fieldType    = member.getFieldType();
jaroslav@1646
   479
            this.staticBase   = staticBase;
jaroslav@1646
   480
            this.staticOffset = staticOffset;
jaroslav@1646
   481
        }
jaroslav@1646
   482
jaroslav@1646
   483
        @Override Object checkCast(Object obj) {
jaroslav@1646
   484
            return fieldType.cast(obj);
jaroslav@1646
   485
        }
jaroslav@1646
   486
        @Override
jaroslav@1646
   487
        MethodHandle viewAsType(MethodType newType) {
jaroslav@1646
   488
            return new StaticAccessor(newType, form, member, staticBase, staticOffset);
jaroslav@1646
   489
        }
jaroslav@1646
   490
    }
jaroslav@1646
   491
jaroslav@1646
   492
    @ForceInline
jaroslav@1646
   493
    /*non-public*/ static Object nullCheck(Object obj) {
jaroslav@1646
   494
        obj.getClass();
jaroslav@1646
   495
        return obj;
jaroslav@1646
   496
    }
jaroslav@1646
   497
jaroslav@1646
   498
    @ForceInline
jaroslav@1646
   499
    /*non-public*/ static Object staticBase(Object accessorObj) {
jaroslav@1646
   500
        return ((StaticAccessor)accessorObj).staticBase;
jaroslav@1646
   501
    }
jaroslav@1646
   502
jaroslav@1646
   503
    @ForceInline
jaroslav@1646
   504
    /*non-public*/ static long staticOffset(Object accessorObj) {
jaroslav@1646
   505
        return ((StaticAccessor)accessorObj).staticOffset;
jaroslav@1646
   506
    }
jaroslav@1646
   507
jaroslav@1646
   508
    @ForceInline
jaroslav@1646
   509
    /*non-public*/ static Object checkCast(Object mh, Object obj) {
jaroslav@1646
   510
        return ((DirectMethodHandle) mh).checkCast(obj);
jaroslav@1646
   511
    }
jaroslav@1646
   512
jaroslav@1646
   513
    Object checkCast(Object obj) {
jaroslav@1646
   514
        return member.getReturnType().cast(obj);
jaroslav@1646
   515
    }
jaroslav@1646
   516
jaroslav@1646
   517
    // Caching machinery for field accessors:
jaroslav@1646
   518
    private static byte
jaroslav@1646
   519
            AF_GETFIELD        = 0,
jaroslav@1646
   520
            AF_PUTFIELD        = 1,
jaroslav@1646
   521
            AF_GETSTATIC       = 2,
jaroslav@1646
   522
            AF_PUTSTATIC       = 3,
jaroslav@1646
   523
            AF_GETSTATIC_INIT  = 4,
jaroslav@1646
   524
            AF_PUTSTATIC_INIT  = 5,
jaroslav@1646
   525
            AF_LIMIT           = 6;
jaroslav@1646
   526
    // Enumerate the different field kinds using Wrapper,
jaroslav@1646
   527
    // with an extra case added for checked references.
jaroslav@1646
   528
    private static int
jaroslav@1646
   529
            FT_LAST_WRAPPER    = Wrapper.values().length-1,
jaroslav@1646
   530
            FT_UNCHECKED_REF   = Wrapper.OBJECT.ordinal(),
jaroslav@1646
   531
            FT_CHECKED_REF     = FT_LAST_WRAPPER+1,
jaroslav@1646
   532
            FT_LIMIT           = FT_LAST_WRAPPER+2;
jaroslav@1646
   533
    private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
jaroslav@1646
   534
        return ((formOp * FT_LIMIT * 2)
jaroslav@1646
   535
                + (isVolatile ? FT_LIMIT : 0)
jaroslav@1646
   536
                + ftypeKind);
jaroslav@1646
   537
    }
jaroslav@1646
   538
    private static final LambdaForm[] ACCESSOR_FORMS
jaroslav@1646
   539
            = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
jaroslav@1646
   540
    private static int ftypeKind(Class<?> ftype) {
jaroslav@1646
   541
        if (ftype.isPrimitive())
jaroslav@1646
   542
            return Wrapper.forPrimitiveType(ftype).ordinal();
jaroslav@1646
   543
        else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
jaroslav@1646
   544
            return FT_UNCHECKED_REF;
jaroslav@1646
   545
        else
jaroslav@1646
   546
            return FT_CHECKED_REF;
jaroslav@1646
   547
    }
jaroslav@1646
   548
jaroslav@1646
   549
    /**
jaroslav@1646
   550
     * Create a LF which can access the given field.
jaroslav@1646
   551
     * Cache and share this structure among all fields with
jaroslav@1646
   552
     * the same basicType and refKind.
jaroslav@1646
   553
     */
jaroslav@1646
   554
    private static LambdaForm preparedFieldLambdaForm(MemberName m) {
jaroslav@1646
   555
        Class<?> ftype = m.getFieldType();
jaroslav@1646
   556
        boolean isVolatile = m.isVolatile();
jaroslav@1646
   557
        byte formOp;
jaroslav@1646
   558
        switch (m.getReferenceKind()) {
jaroslav@1646
   559
        case REF_getField:      formOp = AF_GETFIELD;    break;
jaroslav@1646
   560
        case REF_putField:      formOp = AF_PUTFIELD;    break;
jaroslav@1646
   561
        case REF_getStatic:     formOp = AF_GETSTATIC;   break;
jaroslav@1646
   562
        case REF_putStatic:     formOp = AF_PUTSTATIC;   break;
jaroslav@1646
   563
        default:  throw new InternalError(m.toString());
jaroslav@1646
   564
        }
jaroslav@1646
   565
        if (shouldBeInitialized(m)) {
jaroslav@1646
   566
            // precompute the barrier-free version:
jaroslav@1646
   567
            preparedFieldLambdaForm(formOp, isVolatile, ftype);
jaroslav@1646
   568
            assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
jaroslav@1646
   569
                   (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
jaroslav@1646
   570
            formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
jaroslav@1646
   571
        }
jaroslav@1646
   572
        LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
jaroslav@1646
   573
        maybeCompile(lform, m);
jaroslav@1646
   574
        assert(lform.methodType().dropParameterTypes(0, 1)
jaroslav@1646
   575
                .equals(m.getInvocationType().basicType()))
jaroslav@1646
   576
                : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
jaroslav@1646
   577
        return lform;
jaroslav@1646
   578
    }
jaroslav@1646
   579
    private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, Class<?> ftype) {
jaroslav@1646
   580
        int afIndex = afIndex(formOp, isVolatile, ftypeKind(ftype));
jaroslav@1646
   581
        LambdaForm lform = ACCESSOR_FORMS[afIndex];
jaroslav@1646
   582
        if (lform != null)  return lform;
jaroslav@1646
   583
        lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind(ftype));
jaroslav@1646
   584
        ACCESSOR_FORMS[afIndex] = lform;  // don't bother with a CAS
jaroslav@1646
   585
        return lform;
jaroslav@1646
   586
    }
jaroslav@1646
   587
jaroslav@1646
   588
    private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
jaroslav@1646
   589
        boolean isGetter  = (formOp & 1) == (AF_GETFIELD & 1);
jaroslav@1646
   590
        boolean isStatic  = (formOp >= AF_GETSTATIC);
jaroslav@1646
   591
        boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
jaroslav@1646
   592
        boolean needsCast = (ftypeKind == FT_CHECKED_REF);
jaroslav@1646
   593
        Wrapper fw = (needsCast ? Wrapper.OBJECT : Wrapper.values()[ftypeKind]);
jaroslav@1646
   594
        Class<?> ft = fw.primitiveType();
jaroslav@1646
   595
        assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
jaroslav@1646
   596
        String tname  = fw.primitiveSimpleName();
jaroslav@1646
   597
        String ctname = Character.toUpperCase(tname.charAt(0)) + tname.substring(1);
jaroslav@1646
   598
        if (isVolatile)  ctname += "Volatile";
jaroslav@1646
   599
        String getOrPut = (isGetter ? "get" : "put");
jaroslav@1646
   600
        String linkerName = (getOrPut + ctname);  // getObject, putIntVolatile, etc.
jaroslav@1646
   601
        MethodType linkerType;
jaroslav@1646
   602
        if (isGetter)
jaroslav@1646
   603
            linkerType = MethodType.methodType(ft, Object.class, long.class);
jaroslav@1646
   604
        else
jaroslav@1646
   605
            linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
jaroslav@1646
   606
        MemberName linker = new MemberName(Unsafe.class, linkerName, linkerType, REF_invokeVirtual);
jaroslav@1646
   607
        try {
jaroslav@1646
   608
            linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
jaroslav@1646
   609
        } catch (ReflectiveOperationException ex) {
jaroslav@1646
   610
            throw newInternalError(ex);
jaroslav@1646
   611
        }
jaroslav@1646
   612
jaroslav@1646
   613
        // What is the external type of the lambda form?
jaroslav@1646
   614
        MethodType mtype;
jaroslav@1646
   615
        if (isGetter)
jaroslav@1646
   616
            mtype = MethodType.methodType(ft);
jaroslav@1646
   617
        else
jaroslav@1646
   618
            mtype = MethodType.methodType(void.class, ft);
jaroslav@1646
   619
        mtype = mtype.basicType();  // erase short to int, etc.
jaroslav@1646
   620
        if (!isStatic)
jaroslav@1646
   621
            mtype = mtype.insertParameterTypes(0, Object.class);
jaroslav@1646
   622
        final int DMH_THIS  = 0;
jaroslav@1646
   623
        final int ARG_BASE  = 1;
jaroslav@1646
   624
        final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
jaroslav@1646
   625
        // if this is for non-static access, the base pointer is stored at this index:
jaroslav@1646
   626
        final int OBJ_BASE  = isStatic ? -1 : ARG_BASE;
jaroslav@1646
   627
        // if this is for write access, the value to be written is stored at this index:
jaroslav@1646
   628
        final int SET_VALUE  = isGetter ? -1 : ARG_LIMIT - 1;
jaroslav@1646
   629
        int nameCursor = ARG_LIMIT;
jaroslav@1646
   630
        final int F_HOLDER  = (isStatic ? nameCursor++ : -1);  // static base if any
jaroslav@1646
   631
        final int F_OFFSET  = nameCursor++;  // Either static offset or field offset.
jaroslav@1646
   632
        final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
jaroslav@1646
   633
        final int INIT_BAR  = (needsInit ? nameCursor++ : -1);
jaroslav@1646
   634
        final int PRE_CAST  = (needsCast && !isGetter ? nameCursor++ : -1);
jaroslav@1646
   635
        final int LINKER_CALL = nameCursor++;
jaroslav@1646
   636
        final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
jaroslav@1646
   637
        final int RESULT    = nameCursor-1;  // either the call or the cast
jaroslav@1646
   638
        Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
jaroslav@1646
   639
        if (needsInit)
jaroslav@1646
   640
            names[INIT_BAR] = new Name(Lazy.NF_ensureInitialized, names[DMH_THIS]);
jaroslav@1646
   641
        if (needsCast && !isGetter)
jaroslav@1646
   642
            names[PRE_CAST] = new Name(Lazy.NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
jaroslav@1646
   643
        Object[] outArgs = new Object[1 + linkerType.parameterCount()];
jaroslav@1646
   644
        assert(outArgs.length == (isGetter ? 3 : 4));
jaroslav@1646
   645
        outArgs[0] = UNSAFE;
jaroslav@1646
   646
        if (isStatic) {
jaroslav@1646
   647
            outArgs[1] = names[F_HOLDER]  = new Name(Lazy.NF_staticBase, names[DMH_THIS]);
jaroslav@1646
   648
            outArgs[2] = names[F_OFFSET]  = new Name(Lazy.NF_staticOffset, names[DMH_THIS]);
jaroslav@1646
   649
        } else {
jaroslav@1646
   650
            outArgs[1] = names[OBJ_CHECK] = new Name(Lazy.NF_checkBase, names[OBJ_BASE]);
jaroslav@1646
   651
            outArgs[2] = names[F_OFFSET]  = new Name(Lazy.NF_fieldOffset, names[DMH_THIS]);
jaroslav@1646
   652
        }
jaroslav@1646
   653
        if (!isGetter) {
jaroslav@1646
   654
            outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
jaroslav@1646
   655
        }
jaroslav@1646
   656
        for (Object a : outArgs)  assert(a != null);
jaroslav@1646
   657
        names[LINKER_CALL] = new Name(linker, outArgs);
jaroslav@1646
   658
        if (needsCast && isGetter)
jaroslav@1646
   659
            names[POST_CAST] = new Name(Lazy.NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
jaroslav@1646
   660
        for (Name n : names)  assert(n != null);
jaroslav@1646
   661
        String fieldOrStatic = (isStatic ? "Static" : "Field");
jaroslav@1646
   662
        String lambdaName = (linkerName + fieldOrStatic);  // significant only for debugging
jaroslav@1646
   663
        if (needsCast)  lambdaName += "Cast";
jaroslav@1646
   664
        if (needsInit)  lambdaName += "Init";
jaroslav@1646
   665
        return new LambdaForm(lambdaName, ARG_LIMIT, names, RESULT);
jaroslav@1646
   666
    }
jaroslav@1646
   667
jaroslav@1646
   668
    /**
jaroslav@1646
   669
     * Pre-initialized NamedFunctions for bootstrapping purposes.
jaroslav@1646
   670
     * Factored in an inner class to delay initialization until first usage.
jaroslav@1646
   671
     */
jaroslav@1646
   672
    private static class Lazy {
jaroslav@1646
   673
        static final NamedFunction
jaroslav@1646
   674
                NF_internalMemberName,
jaroslav@1646
   675
                NF_internalMemberNameEnsureInit,
jaroslav@1646
   676
                NF_ensureInitialized,
jaroslav@1646
   677
                NF_fieldOffset,
jaroslav@1646
   678
                NF_checkBase,
jaroslav@1646
   679
                NF_staticBase,
jaroslav@1646
   680
                NF_staticOffset,
jaroslav@1646
   681
                NF_checkCast,
jaroslav@1646
   682
                NF_allocateInstance,
jaroslav@1646
   683
                NF_constructorMethod;
jaroslav@1646
   684
        static {
jaroslav@1646
   685
            try {
jaroslav@1646
   686
                NamedFunction nfs[] = {
jaroslav@1646
   687
                        NF_internalMemberName = new NamedFunction(DirectMethodHandle.class
jaroslav@1646
   688
                                .getDeclaredMethod("internalMemberName", Object.class)),
jaroslav@1646
   689
                        NF_internalMemberNameEnsureInit = new NamedFunction(DirectMethodHandle.class
jaroslav@1646
   690
                                .getDeclaredMethod("internalMemberNameEnsureInit", Object.class)),
jaroslav@1646
   691
                        NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class
jaroslav@1646
   692
                                .getDeclaredMethod("ensureInitialized", Object.class)),
jaroslav@1646
   693
                        NF_fieldOffset = new NamedFunction(DirectMethodHandle.class
jaroslav@1646
   694
                                .getDeclaredMethod("fieldOffset", Object.class)),
jaroslav@1646
   695
                        NF_checkBase = new NamedFunction(DirectMethodHandle.class
jaroslav@1646
   696
                                .getDeclaredMethod("checkBase", Object.class)),
jaroslav@1646
   697
                        NF_staticBase = new NamedFunction(DirectMethodHandle.class
jaroslav@1646
   698
                                .getDeclaredMethod("staticBase", Object.class)),
jaroslav@1646
   699
                        NF_staticOffset = new NamedFunction(DirectMethodHandle.class
jaroslav@1646
   700
                                .getDeclaredMethod("staticOffset", Object.class)),
jaroslav@1646
   701
                        NF_checkCast = new NamedFunction(DirectMethodHandle.class
jaroslav@1646
   702
                                .getDeclaredMethod("checkCast", Object.class, Object.class)),
jaroslav@1646
   703
                        NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
jaroslav@1646
   704
                                .getDeclaredMethod("allocateInstance", Object.class)),
jaroslav@1646
   705
                        NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
jaroslav@1646
   706
                                .getDeclaredMethod("constructorMethod", Object.class))
jaroslav@1646
   707
                };
jaroslav@1646
   708
                for (NamedFunction nf : nfs) {
jaroslav@1646
   709
                    // Each nf must be statically invocable or we get tied up in our bootstraps.
jaroslav@1646
   710
                    assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
jaroslav@1646
   711
                    nf.resolve();
jaroslav@1646
   712
                }
jaroslav@1646
   713
            } catch (ReflectiveOperationException ex) {
jaroslav@1646
   714
                throw newInternalError(ex);
jaroslav@1646
   715
            }
jaroslav@1646
   716
        }
jaroslav@1646
   717
    }
jaroslav@1646
   718
}