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