src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java
author redestad
Wed, 14 Feb 2018 15:27:29 +0100
changeset 48895 7a1916641c0c
parent 48826 c4d9d1b08e2e
child 48921 576e024f10b6
permissions -rw-r--r--
8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker Reviewed-by: psandoz, jrose
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
     1
/*
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
     2
 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
     4
 *
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    10
 *
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    15
 * accompanied this code).
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    16
 *
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    20
 *
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    23
 * questions.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    24
 */
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    25
package java.lang.invoke;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    26
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    27
import sun.invoke.util.Wrapper;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    28
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    29
import java.lang.invoke.AbstractConstantGroup.BSCIWithCache;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    30
import java.util.Arrays;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    31
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    32
import static java.lang.invoke.BootstrapCallInfo.makeBootstrapCallInfo;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    33
import static java.lang.invoke.ConstantGroup.makeConstantGroup;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    34
import static java.lang.invoke.MethodHandleNatives.*;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    35
import static java.lang.invoke.MethodHandleStatics.TRACE_METHOD_LINKAGE;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    36
import static java.lang.invoke.MethodHandles.Lookup;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    37
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    38
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    39
final class BootstrapMethodInvoker {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    40
    /**
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    41
     * Factored code for invoking a bootstrap method for invokedynamic
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    42
     * or a dynamic constant.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    43
     * @param resultType the expected return type (either CallSite or a constant type)
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    44
     * @param bootstrapMethod the BSM to call
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    45
     * @param name the method name or constant name
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    46
     * @param type the method type or constant type
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    47
     * @param info information passed up from the JVM, to derive static arguments
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    48
     * @param callerClass the class containing the resolved method call or constant load
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    49
     * @param <T> the expected return type
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    50
     * @return the expected value, either a CallSite or a constant value
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    51
     */
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    52
    static <T> T invoke(Class<T> resultType,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    53
                        MethodHandle bootstrapMethod,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    54
                        // Callee information:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    55
                        String name, Object type,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    56
                        // Extra arguments for BSM, if any:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    57
                        Object info,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    58
                        // Caller information:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    59
                        Class<?> callerClass) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    60
        MethodHandles.Lookup caller = IMPL_LOOKUP.in(callerClass);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    61
        Object result;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    62
        boolean pullMode = isPullModeBSM(bootstrapMethod);  // default value is false
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    63
        boolean vmIsPushing = !staticArgumentsPulled(info); // default value is true
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    64
        MethodHandle pullModeBSM;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    65
        // match the VM with the BSM
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    66
        if (vmIsPushing) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    67
            // VM is pushing arguments at us
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    68
            pullModeBSM = null;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    69
            if (pullMode) {
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
    70
                bootstrapMethod = pushMePullYou(bootstrapMethod, true);
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    71
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    72
        } else {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    73
            // VM wants us to pull args from it
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    74
            pullModeBSM = pullMode ? bootstrapMethod :
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
    75
                    pushMePullYou(bootstrapMethod, false);
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    76
            bootstrapMethod = null;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    77
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    78
        try {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    79
            info = maybeReBox(info);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    80
            if (info == null) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    81
                // VM is allowed to pass up a null meaning no BSM args
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    82
                result = bootstrapMethod.invoke(caller, name, type);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    83
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    84
            else if (!info.getClass().isArray()) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    85
                // VM is allowed to pass up a single BSM arg directly
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    86
                result = bootstrapMethod.invoke(caller, name, type, info);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    87
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    88
            else if (info.getClass() == int[].class) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    89
                // VM is allowed to pass up a pair {argc, index}
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    90
                // referring to 'argc' BSM args at some place 'index'
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    91
                // in the guts of the VM (associated with callerClass).
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    92
                // The format of this index pair is private to the
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    93
                // handshake between the VM and this class only.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    94
                // This supports "pulling" of arguments.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    95
                // The VM is allowed to do this for any reason.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    96
                // The code in this method makes up for any mismatches.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    97
                BootstrapCallInfo<Object> bsci
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    98
                    = new VM_BSCI<>(bootstrapMethod, name, type, caller, (int[])info);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
    99
                // Pull-mode API is (Lookup, BootstrapCallInfo) -> Object
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   100
                result = pullModeBSM.invoke(caller, bsci);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   101
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   102
            else {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   103
                // VM is allowed to pass up a full array of resolved BSM args
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   104
                Object[] argv = (Object[]) info;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   105
                maybeReBoxElements(argv);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   106
                switch (argv.length) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   107
                    case 0:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   108
                        result = bootstrapMethod.invoke(caller, name, type);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   109
                        break;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   110
                    case 1:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   111
                        result = bootstrapMethod.invoke(caller, name, type,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   112
                                                        argv[0]);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   113
                        break;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   114
                    case 2:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   115
                        result = bootstrapMethod.invoke(caller, name, type,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   116
                                                        argv[0], argv[1]);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   117
                        break;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   118
                    case 3:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   119
                        result = bootstrapMethod.invoke(caller, name, type,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   120
                                                        argv[0], argv[1], argv[2]);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   121
                        break;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   122
                    case 4:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   123
                        result = bootstrapMethod.invoke(caller, name, type,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   124
                                                        argv[0], argv[1], argv[2], argv[3]);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   125
                        break;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   126
                    case 5:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   127
                        result = bootstrapMethod.invoke(caller, name, type,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   128
                                                        argv[0], argv[1], argv[2], argv[3], argv[4]);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   129
                        break;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   130
                    case 6:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   131
                        result = bootstrapMethod.invoke(caller, name, type,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   132
                                                        argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   133
                        break;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   134
                    default:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   135
                        final int NON_SPREAD_ARG_COUNT = 3;  // (caller, name, type)
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   136
                        final int MAX_SAFE_SIZE = MethodType.MAX_MH_ARITY / 2 - NON_SPREAD_ARG_COUNT;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   137
                        if (argv.length >= MAX_SAFE_SIZE) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   138
                            // to be on the safe side, use invokeWithArguments which handles jumbo lists
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   139
                            Object[] newargv = new Object[NON_SPREAD_ARG_COUNT + argv.length];
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   140
                            newargv[0] = caller;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   141
                            newargv[1] = name;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   142
                            newargv[2] = type;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   143
                            System.arraycopy(argv, 0, newargv, NON_SPREAD_ARG_COUNT, argv.length);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   144
                            result = bootstrapMethod.invokeWithArguments(newargv);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   145
                            break;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   146
                        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   147
                        MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argv.length);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   148
                        MethodHandle typedBSM = bootstrapMethod.asType(invocationType);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   149
                        MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   150
                        result = spreader.invokeExact(typedBSM, (Object) caller, (Object) name, type, argv);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   151
                }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   152
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   153
            if (resultType.isPrimitive()) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   154
                // Non-reference conversions are more than just plain casts.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   155
                // By pushing the value through a funnel of the form (T x)->x,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   156
                // the boxed result can be widened as needed.  See MH::asType.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   157
                MethodHandle funnel = MethodHandles.identity(resultType);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   158
                result = funnel.invoke(result);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   159
                // Now it is the wrapper type for resultType.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   160
                resultType = Wrapper.asWrapperType(resultType);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   161
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   162
            return resultType.cast(result);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   163
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   164
        catch (Error e) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   165
            // Pass through an Error, including BootstrapMethodError, any other
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   166
            // form of linkage error, such as IllegalAccessError if the bootstrap
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   167
            // method is inaccessible, or say ThreadDeath/OutOfMemoryError
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   168
            // See the "Linking Exceptions" section for the invokedynamic
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   169
            // instruction in JVMS 6.5.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   170
            throw e;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   171
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   172
        catch (Throwable ex) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   173
            // Wrap anything else in BootstrapMethodError
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   174
            throw new BootstrapMethodError("bootstrap method initialization exception", ex);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   175
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   176
    }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   177
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   178
    /** The JVM produces java.lang.Integer values to box
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   179
     *  CONSTANT_Integer boxes but does not intern them.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   180
     *  Let's intern them.  This is slightly wrong for
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   181
     *  a {@code CONSTANT_Dynamic} which produces an
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   182
     *  un-interned integer (e.g., {@code new Integer(0)}).
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   183
     */
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   184
    private static Object maybeReBox(Object x) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   185
        if (x instanceof Integer) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   186
            int xi = (int) x;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   187
            if (xi == (byte) xi)
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   188
                x = xi;  // must rebox; see JLS 5.1.7
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   189
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   190
        return x;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   191
    }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   192
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   193
    private static void maybeReBoxElements(Object[] xa) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   194
        for (int i = 0; i < xa.length; i++) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   195
            xa[i] = maybeReBox(xa[i]);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   196
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   197
    }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   198
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   199
    /** Canonical VM-aware implementation of BootstrapCallInfo.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   200
     * Knows how to dig into the JVM for lazily resolved (pull-mode) constants.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   201
     */
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   202
    private static final class VM_BSCI<T> extends BSCIWithCache<T> {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   203
        private final int[] indexInfo;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   204
        private final Class<?> caller;  // for index resolution only
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   205
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   206
        VM_BSCI(MethodHandle bsm, String name, T type,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   207
                Lookup lookup, int[] indexInfo) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   208
            super(bsm, name, type, indexInfo[0]);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   209
            if (!lookup.hasPrivateAccess())  //D.I.D.
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   210
                throw new AssertionError("bad Lookup object");
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   211
            this.caller = lookup.lookupClass();
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   212
            this.indexInfo = indexInfo;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   213
            // scoop up all the easy stuff right away:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   214
            prefetchIntoCache(0, size());
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   215
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   216
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   217
        @Override Object fillCache(int i) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   218
            Object[] buf = { null };
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   219
            copyConstants(i, i+1, buf, 0);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   220
            Object res = wrapNull(buf[0]);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   221
            cache[i] = res;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   222
            int next = i + 1;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   223
            if (next < cache.length && cache[next] == null)
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   224
                maybePrefetchIntoCache(next, false);  // try to prefetch
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   225
            return res;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   226
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   227
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   228
        @Override public int copyConstants(int start, int end,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   229
                                           Object[] buf, int pos) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   230
            int i = start, bufi = pos;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   231
            while (i < end) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   232
                Object x = cache[i];
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   233
                if (x == null)  break;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   234
                buf[bufi++] = unwrapNull(x);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   235
                i++;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   236
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   237
            // give up at first null and grab the rest in one big block
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   238
            if (i >= end)  return i;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   239
            Object[] temp = new Object[end - i];
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   240
            if (TRACE_METHOD_LINKAGE) {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   241
                System.out.println("resolving more BSM arguments: " +
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   242
                        Arrays.asList(caller.getSimpleName(), Arrays.toString(indexInfo), i, end));
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   243
            }
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   244
            copyOutBootstrapArguments(caller, indexInfo,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   245
                                      i, end, temp, 0,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   246
                                      true, null);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   247
            for (Object x : temp) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   248
                x = maybeReBox(x);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   249
                buf[bufi++] = x;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   250
                cache[i++] = wrapNull(x);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   251
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   252
            if (end < cache.length && cache[end] == null)
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   253
                maybePrefetchIntoCache(end, true);  // try to prefetch
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   254
            return i;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   255
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   256
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   257
        private static final int MIN_PF = 4;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   258
        private void maybePrefetchIntoCache(int i, boolean bulk) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   259
            int len = cache.length;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   260
            assert(0 <= i && i <= len);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   261
            int pfLimit = i;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   262
            if (bulk)  pfLimit += i;  // exponential prefetch expansion
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   263
            // try to prefetch at least MIN_PF elements
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   264
            if (pfLimit < i + MIN_PF)  pfLimit = i + MIN_PF;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   265
            if (pfLimit > len || pfLimit < 0)  pfLimit = len;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   266
            // stop prefetching where cache is more full than empty
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   267
            int empty = 0, nonEmpty = 0, lastEmpty = i;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   268
            for (int j = i; j < pfLimit; j++) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   269
                if (cache[j] == null) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   270
                    empty++;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   271
                    lastEmpty = j;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   272
                } else {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   273
                    nonEmpty++;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   274
                    if (nonEmpty > empty) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   275
                        pfLimit = lastEmpty + 1;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   276
                        break;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   277
                    }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   278
                    if (pfLimit < len)  pfLimit++;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   279
                }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   280
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   281
            if (bulk && empty < MIN_PF && pfLimit < len)
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   282
                return;  // not worth the effort
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   283
            prefetchIntoCache(i, pfLimit);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   284
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   285
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   286
        private void prefetchIntoCache(int i, int pfLimit) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   287
            if (pfLimit <= i)  return;  // corner case
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   288
            Object[] temp = new Object[pfLimit - i];
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   289
            if (TRACE_METHOD_LINKAGE) {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   290
                System.out.println("prefetching BSM arguments: " +
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   291
                        Arrays.asList(caller.getSimpleName(), Arrays.toString(indexInfo), i, pfLimit));
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   292
            }
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   293
            copyOutBootstrapArguments(caller, indexInfo,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   294
                                      i, pfLimit, temp, 0,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   295
                                      false, NOT_PRESENT);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   296
            for (Object x : temp) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   297
                if (x != NOT_PRESENT && cache[i] == null) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   298
                    cache[i] = wrapNull(maybeReBox(x));
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   299
                }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   300
                i++;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   301
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   302
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   303
    }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   304
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   305
    /*non-public*/ static final
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   306
    class PushAdapter {
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   307
        // skeleton for push-mode BSM which wraps a pull-mode BSM:
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   308
        static Object pushToBootstrapMethod(MethodHandle pullModeBSM,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   309
                                            MethodHandles.Lookup lookup, String name, Object type,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   310
                                            Object... arguments) throws Throwable {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   311
            ConstantGroup cons = makeConstantGroup(Arrays.asList(arguments));
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   312
            BootstrapCallInfo<?> bsci = makeBootstrapCallInfo(pullModeBSM, name, type, cons);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   313
            if (TRACE_METHOD_LINKAGE)
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   314
                System.out.println("pull-mode BSM gets pushed arguments from fake BSCI");
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   315
            return pullModeBSM.invoke(lookup, bsci);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   316
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   317
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   318
        static final MethodHandle MH_pushToBootstrapMethod;
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   319
        static {
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   320
            final Class<?> THIS_CLASS = PushAdapter.class;
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   321
            try {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   322
                MH_pushToBootstrapMethod = IMPL_LOOKUP
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   323
                    .findStatic(THIS_CLASS, "pushToBootstrapMethod",
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   324
                                MethodType.methodType(Object.class, MethodHandle.class,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   325
                                        Lookup.class, String.class, Object.class, Object[].class));
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   326
            } catch (Throwable ex) {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   327
                throw new InternalError(ex);
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   328
            }
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   329
        }
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   330
    }
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   331
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   332
    /*non-public*/ static final
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   333
    class PullAdapter {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   334
        // skeleton for pull-mode BSM which wraps a push-mode BSM:
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   335
        static Object pullFromBootstrapMethod(MethodHandle pushModeBSM,
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   336
                                              MethodHandles.Lookup lookup,
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   337
                                              BootstrapCallInfo<?> bsci)
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   338
                throws Throwable {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   339
            int argc = bsci.size();
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   340
            switch (argc) {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   341
                case 0:
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   342
                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType());
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   343
                case 1:
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   344
                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   345
                            bsci.get(0));
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   346
                case 2:
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   347
                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   348
                            bsci.get(0), bsci.get(1));
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   349
                case 3:
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   350
                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   351
                            bsci.get(0), bsci.get(1), bsci.get(2));
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   352
                case 4:
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   353
                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   354
                            bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3));
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   355
                case 5:
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   356
                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   357
                            bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3), bsci.get(4));
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   358
                case 6:
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   359
                    return pushModeBSM.invoke(lookup, bsci.invocationName(), bsci.invocationType(),
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   360
                            bsci.get(0), bsci.get(1), bsci.get(2), bsci.get(3), bsci.get(4), bsci.get(5));
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   361
                default:
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   362
                    final int NON_SPREAD_ARG_COUNT = 3;  // (lookup, name, type)
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   363
                    final int MAX_SAFE_SIZE = MethodType.MAX_MH_ARITY / 2 - NON_SPREAD_ARG_COUNT;
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   364
                    if (argc >= MAX_SAFE_SIZE) {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   365
                        // to be on the safe side, use invokeWithArguments which handles jumbo lists
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   366
                        Object[] newargv = new Object[NON_SPREAD_ARG_COUNT + argc];
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   367
                        newargv[0] = lookup;
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   368
                        newargv[1] = bsci.invocationName();
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   369
                        newargv[2] = bsci.invocationType();
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   370
                        bsci.copyConstants(0, argc, newargv, NON_SPREAD_ARG_COUNT);
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   371
                        return pushModeBSM.invokeWithArguments(newargv);
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   372
                    }
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   373
                    MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argc);
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   374
                    MethodHandle typedBSM = pushModeBSM.asType(invocationType);
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   375
                    MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   376
                    Object[] argv = new Object[argc];
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   377
                    bsci.copyConstants(0, argc, argv, 0);
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   378
                    return spreader.invokeExact(typedBSM, (Object) lookup, (Object) bsci.invocationName(), bsci.invocationType(), argv);
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   379
                }
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   380
        }
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   381
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   382
        static final MethodHandle MH_pullFromBootstrapMethod;
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   383
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   384
        static {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   385
            final Class<?> THIS_CLASS = PullAdapter.class;
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   386
            try {
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   387
                MH_pullFromBootstrapMethod = IMPL_LOOKUP
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   388
                    .findStatic(THIS_CLASS, "pullFromBootstrapMethod",
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   389
                                MethodType.methodType(Object.class, MethodHandle.class,
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   390
                                        Lookup.class, BootstrapCallInfo.class));
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   391
            } catch (Throwable ex) {
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   392
                throw new InternalError(ex);
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   393
            }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   394
        }
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   395
    }
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   396
48895
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   397
    /** Given a push-mode BSM (taking one argument) convert it to a
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   398
     *  pull-mode BSM (taking N pre-resolved arguments).
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   399
     *  This method is used when, in fact, the JVM is passing up
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   400
     *  pre-resolved arguments, but the BSM is expecting lazy stuff.
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   401
     *  Or, when goToPushMode is true, do the reverse transform.
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   402
     *  (The two transforms are exactly inverse.)
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   403
     */
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   404
    static MethodHandle pushMePullYou(MethodHandle bsm, boolean goToPushMode) {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   405
        if (TRACE_METHOD_LINKAGE) {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   406
            System.out.println("converting BSM of type " + bsm.type() + " to "
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   407
                    + (goToPushMode ? "push mode" : "pull mode"));
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   408
        }
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   409
        assert(isPullModeBSM(bsm) == goToPushMode); // there must be a change
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   410
        if (goToPushMode) {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   411
            return PushAdapter.MH_pushToBootstrapMethod.bindTo(bsm).withVarargs(true);
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   412
        } else {
7a1916641c0c 8195850: Improve startup of code to pull arguments from BootstrapMethodInvoker
redestad
parents: 48826
diff changeset
   413
            return PullAdapter.MH_pullFromBootstrapMethod.bindTo(bsm).withVarargs(false);
48826
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   414
        }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   415
    }
c4d9d1b08e2e 8186209: Tool support for ConstantDynamic
psandoz
parents:
diff changeset
   416
}