1.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/LambdaForm.java Sun Aug 17 20:09:05 2014 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1650 +0,0 @@
1.4 -/*
1.5 - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 - *
1.8 - * This code is free software; you can redistribute it and/or modify it
1.9 - * under the terms of the GNU General Public License version 2 only, as
1.10 - * published by the Free Software Foundation. Oracle designates this
1.11 - * particular file as subject to the "Classpath" exception as provided
1.12 - * by Oracle in the LICENSE file that accompanied this code.
1.13 - *
1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 - * version 2 for more details (a copy is included in the LICENSE file that
1.18 - * accompanied this code).
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License version
1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 - *
1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 - * or visit www.oracle.com if you need additional information or have any
1.26 - * questions.
1.27 - */
1.28 -
1.29 -package java.lang.invoke;
1.30 -
1.31 -import java.lang.annotation.*;
1.32 -import java.lang.reflect.Method;
1.33 -import java.util.Map;
1.34 -import java.util.List;
1.35 -import java.util.Arrays;
1.36 -import java.util.ArrayList;
1.37 -import java.util.HashMap;
1.38 -import java.util.concurrent.ConcurrentHashMap;
1.39 -import sun.invoke.util.Wrapper;
1.40 -import static java.lang.invoke.MethodHandleStatics.*;
1.41 -import static java.lang.invoke.MethodHandleNatives.Constants.*;
1.42 -import java.lang.reflect.Field;
1.43 -import java.util.Objects;
1.44 -
1.45 -/**
1.46 - * The symbolic, non-executable form of a method handle's invocation semantics.
1.47 - * It consists of a series of names.
1.48 - * The first N (N=arity) names are parameters,
1.49 - * while any remaining names are temporary values.
1.50 - * Each temporary specifies the application of a function to some arguments.
1.51 - * The functions are method handles, while the arguments are mixes of
1.52 - * constant values and local names.
1.53 - * The result of the lambda is defined as one of the names, often the last one.
1.54 - * <p>
1.55 - * Here is an approximate grammar:
1.56 - * <blockquote><pre>{@code
1.57 - * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
1.58 - * ArgName = "a" N ":" T
1.59 - * TempName = "t" N ":" T "=" Function "(" Argument* ");"
1.60 - * Function = ConstantValue
1.61 - * Argument = NameRef | ConstantValue
1.62 - * Result = NameRef | "void"
1.63 - * NameRef = "a" N | "t" N
1.64 - * N = (any whole number)
1.65 - * T = "L" | "I" | "J" | "F" | "D" | "V"
1.66 - * }</pre></blockquote>
1.67 - * Names are numbered consecutively from left to right starting at zero.
1.68 - * (The letters are merely a taste of syntax sugar.)
1.69 - * Thus, the first temporary (if any) is always numbered N (where N=arity).
1.70 - * Every occurrence of a name reference in an argument list must refer to
1.71 - * a name previously defined within the same lambda.
1.72 - * A lambda has a void result if and only if its result index is -1.
1.73 - * If a temporary has the type "V", it cannot be the subject of a NameRef,
1.74 - * even though possesses a number.
1.75 - * Note that all reference types are erased to "L", which stands for {@code Object}.
1.76 - * All subword types (boolean, byte, short, char) are erased to "I" which is {@code int}.
1.77 - * The other types stand for the usual primitive types.
1.78 - * <p>
1.79 - * Function invocation closely follows the static rules of the Java verifier.
1.80 - * Arguments and return values must exactly match when their "Name" types are
1.81 - * considered.
1.82 - * Conversions are allowed only if they do not change the erased type.
1.83 - * <ul>
1.84 - * <li>L = Object: casts are used freely to convert into and out of reference types
1.85 - * <li>I = int: subword types are forcibly narrowed when passed as arguments (see {@code explicitCastArguments})
1.86 - * <li>J = long: no implicit conversions
1.87 - * <li>F = float: no implicit conversions
1.88 - * <li>D = double: no implicit conversions
1.89 - * <li>V = void: a function result may be void if and only if its Name is of type "V"
1.90 - * </ul>
1.91 - * Although implicit conversions are not allowed, explicit ones can easily be
1.92 - * encoded by using temporary expressions which call type-transformed identity functions.
1.93 - * <p>
1.94 - * Examples:
1.95 - * <blockquote><pre>{@code
1.96 - * (a0:J)=>{ a0 }
1.97 - * == identity(long)
1.98 - * (a0:I)=>{ t1:V = System.out#println(a0); void }
1.99 - * == System.out#println(int)
1.100 - * (a0:L)=>{ t1:V = System.out#println(a0); a0 }
1.101 - * == identity, with printing side-effect
1.102 - * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
1.103 - * t3:L = BoundMethodHandle#target(a0);
1.104 - * t4:L = MethodHandle#invoke(t3, t2, a1); t4 }
1.105 - * == general invoker for unary insertArgument combination
1.106 - * (a0:L, a1:L)=>{ t2:L = FilterMethodHandle#filter(a0);
1.107 - * t3:L = MethodHandle#invoke(t2, a1);
1.108 - * t4:L = FilterMethodHandle#target(a0);
1.109 - * t5:L = MethodHandle#invoke(t4, t3); t5 }
1.110 - * == general invoker for unary filterArgument combination
1.111 - * (a0:L, a1:L)=>{ ...(same as previous example)...
1.112 - * t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
1.113 - * == general invoker for unary/unary foldArgument combination
1.114 - * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
1.115 - * == invoker for identity method handle which performs i2l
1.116 - * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
1.117 - * t3:L = Class#cast(t2,a1); t3 }
1.118 - * == invoker for identity method handle which performs cast
1.119 - * }</pre></blockquote>
1.120 - * <p>
1.121 - * @author John Rose, JSR 292 EG
1.122 - */
1.123 -class LambdaForm {
1.124 - final int arity;
1.125 - final int result;
1.126 - @Stable final Name[] names;
1.127 - final String debugName;
1.128 - MemberName vmentry; // low-level behavior, or null if not yet prepared
1.129 - private boolean isCompiled;
1.130 -
1.131 - // Caches for common structural transforms:
1.132 - LambdaForm[] bindCache;
1.133 -
1.134 - public static final int VOID_RESULT = -1, LAST_RESULT = -2;
1.135 -
1.136 - LambdaForm(String debugName,
1.137 - int arity, Name[] names, int result) {
1.138 - assert(namesOK(arity, names));
1.139 - this.arity = arity;
1.140 - this.result = fixResult(result, names);
1.141 - this.names = names.clone();
1.142 - this.debugName = debugName;
1.143 - normalize();
1.144 - }
1.145 -
1.146 - LambdaForm(String debugName,
1.147 - int arity, Name[] names) {
1.148 - this(debugName,
1.149 - arity, names, LAST_RESULT);
1.150 - }
1.151 -
1.152 - LambdaForm(String debugName,
1.153 - Name[] formals, Name[] temps, Name result) {
1.154 - this(debugName,
1.155 - formals.length, buildNames(formals, temps, result), LAST_RESULT);
1.156 - }
1.157 -
1.158 - private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
1.159 - int arity = formals.length;
1.160 - int length = arity + temps.length + (result == null ? 0 : 1);
1.161 - Name[] names = Arrays.copyOf(formals, length);
1.162 - System.arraycopy(temps, 0, names, arity, temps.length);
1.163 - if (result != null)
1.164 - names[length - 1] = result;
1.165 - return names;
1.166 - }
1.167 -
1.168 - private LambdaForm(String sig) {
1.169 - // Make a blank lambda form, which returns a constant zero or null.
1.170 - // It is used as a template for managing the invocation of similar forms that are non-empty.
1.171 - // Called only from getPreparedForm.
1.172 - assert(isValidSignature(sig));
1.173 - this.arity = signatureArity(sig);
1.174 - this.result = (signatureReturn(sig) == 'V' ? -1 : arity);
1.175 - this.names = buildEmptyNames(arity, sig);
1.176 - this.debugName = "LF.zero";
1.177 - assert(nameRefsAreLegal());
1.178 - assert(isEmpty());
1.179 - assert(sig.equals(basicTypeSignature()));
1.180 - }
1.181 -
1.182 - private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
1.183 - assert(isValidSignature(basicTypeSignature));
1.184 - int resultPos = arity + 1; // skip '_'
1.185 - if (arity < 0 || basicTypeSignature.length() != resultPos+1)
1.186 - throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
1.187 - int numRes = (basicTypeSignature.charAt(resultPos) == 'V' ? 0 : 1);
1.188 - Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
1.189 - for (int i = 0; i < numRes; i++) {
1.190 - names[arity + i] = constantZero(arity + i, basicTypeSignature.charAt(resultPos + i));
1.191 - }
1.192 - return names;
1.193 - }
1.194 -
1.195 - private static int fixResult(int result, Name[] names) {
1.196 - if (result >= 0) {
1.197 - if (names[result].type == 'V')
1.198 - return -1;
1.199 - } else if (result == LAST_RESULT) {
1.200 - return names.length - 1;
1.201 - }
1.202 - return result;
1.203 - }
1.204 -
1.205 - private static boolean namesOK(int arity, Name[] names) {
1.206 - for (int i = 0; i < names.length; i++) {
1.207 - Name n = names[i];
1.208 - assert(n != null) : "n is null";
1.209 - if (i < arity)
1.210 - assert( n.isParam()) : n + " is not param at " + i;
1.211 - else
1.212 - assert(!n.isParam()) : n + " is param at " + i;
1.213 - }
1.214 - return true;
1.215 - }
1.216 -
1.217 - /** Renumber and/or replace params so that they are interned and canonically numbered. */
1.218 - private void normalize() {
1.219 - Name[] oldNames = null;
1.220 - int changesStart = 0;
1.221 - for (int i = 0; i < names.length; i++) {
1.222 - Name n = names[i];
1.223 - if (!n.initIndex(i)) {
1.224 - if (oldNames == null) {
1.225 - oldNames = names.clone();
1.226 - changesStart = i;
1.227 - }
1.228 - names[i] = n.cloneWithIndex(i);
1.229 - }
1.230 - }
1.231 - if (oldNames != null) {
1.232 - int startFixing = arity;
1.233 - if (startFixing <= changesStart)
1.234 - startFixing = changesStart+1;
1.235 - for (int i = startFixing; i < names.length; i++) {
1.236 - Name fixed = names[i].replaceNames(oldNames, names, changesStart, i);
1.237 - names[i] = fixed.newIndex(i);
1.238 - }
1.239 - }
1.240 - assert(nameRefsAreLegal());
1.241 - int maxInterned = Math.min(arity, INTERNED_ARGUMENT_LIMIT);
1.242 - boolean needIntern = false;
1.243 - for (int i = 0; i < maxInterned; i++) {
1.244 - Name n = names[i], n2 = internArgument(n);
1.245 - if (n != n2) {
1.246 - names[i] = n2;
1.247 - needIntern = true;
1.248 - }
1.249 - }
1.250 - if (needIntern) {
1.251 - for (int i = arity; i < names.length; i++) {
1.252 - names[i].internArguments();
1.253 - }
1.254 - assert(nameRefsAreLegal());
1.255 - }
1.256 - }
1.257 -
1.258 - /**
1.259 - * Check that all embedded Name references are localizable to this lambda,
1.260 - * and are properly ordered after their corresponding definitions.
1.261 - * <p>
1.262 - * Note that a Name can be local to multiple lambdas, as long as
1.263 - * it possesses the same index in each use site.
1.264 - * This allows Name references to be freely reused to construct
1.265 - * fresh lambdas, without confusion.
1.266 - */
1.267 - private boolean nameRefsAreLegal() {
1.268 - assert(arity >= 0 && arity <= names.length);
1.269 - assert(result >= -1 && result < names.length);
1.270 - // Do all names possess an index consistent with their local definition order?
1.271 - for (int i = 0; i < arity; i++) {
1.272 - Name n = names[i];
1.273 - assert(n.index() == i) : Arrays.asList(n.index(), i);
1.274 - assert(n.isParam());
1.275 - }
1.276 - // Also, do all local name references
1.277 - for (int i = arity; i < names.length; i++) {
1.278 - Name n = names[i];
1.279 - assert(n.index() == i);
1.280 - for (Object arg : n.arguments) {
1.281 - if (arg instanceof Name) {
1.282 - Name n2 = (Name) arg;
1.283 - int i2 = n2.index;
1.284 - assert(0 <= i2 && i2 < names.length) : n.debugString() + ": 0 <= i2 && i2 < names.length: 0 <= " + i2 + " < " + names.length;
1.285 - assert(names[i2] == n2) : Arrays.asList("-1-", i, "-2-", n.debugString(), "-3-", i2, "-4-", n2.debugString(), "-5-", names[i2].debugString(), "-6-", this);
1.286 - assert(i2 < i); // ref must come after def!
1.287 - }
1.288 - }
1.289 - }
1.290 - return true;
1.291 - }
1.292 -
1.293 - /** Invoke this form on the given arguments. */
1.294 - // final Object invoke(Object... args) throws Throwable {
1.295 - // // NYI: fit this into the fast path?
1.296 - // return interpretWithArguments(args);
1.297 - // }
1.298 -
1.299 - /** Report the return type. */
1.300 - char returnType() {
1.301 - if (result < 0) return 'V';
1.302 - Name n = names[result];
1.303 - return n.type;
1.304 - }
1.305 -
1.306 - /** Report the N-th argument type. */
1.307 - char parameterType(int n) {
1.308 - assert(n < arity);
1.309 - return names[n].type;
1.310 - }
1.311 -
1.312 - /** Report the arity. */
1.313 - int arity() {
1.314 - return arity;
1.315 - }
1.316 -
1.317 - /** Return the method type corresponding to my basic type signature. */
1.318 - MethodType methodType() {
1.319 - return signatureType(basicTypeSignature());
1.320 - }
1.321 - /** Return ABC_Z, where the ABC are parameter type characters, and Z is the return type character. */
1.322 - final String basicTypeSignature() {
1.323 - StringBuilder buf = new StringBuilder(arity() + 3);
1.324 - for (int i = 0, a = arity(); i < a; i++)
1.325 - buf.append(parameterType(i));
1.326 - return buf.append('_').append(returnType()).toString();
1.327 - }
1.328 - static int signatureArity(String sig) {
1.329 - assert(isValidSignature(sig));
1.330 - return sig.indexOf('_');
1.331 - }
1.332 - static char signatureReturn(String sig) {
1.333 - return sig.charAt(signatureArity(sig)+1);
1.334 - }
1.335 - static boolean isValidSignature(String sig) {
1.336 - int arity = sig.indexOf('_');
1.337 - if (arity < 0) return false; // must be of the form *_*
1.338 - int siglen = sig.length();
1.339 - if (siglen != arity + 2) return false; // *_X
1.340 - for (int i = 0; i < siglen; i++) {
1.341 - if (i == arity) continue; // skip '_'
1.342 - char c = sig.charAt(i);
1.343 - if (c == 'V')
1.344 - return (i == siglen - 1 && arity == siglen - 2);
1.345 - if (ALL_TYPES.indexOf(c) < 0) return false; // must be [LIJFD]
1.346 - }
1.347 - return true; // [LIJFD]*_[LIJFDV]
1.348 - }
1.349 - static Class<?> typeClass(char t) {
1.350 - switch (t) {
1.351 - case 'I': return int.class;
1.352 - case 'J': return long.class;
1.353 - case 'F': return float.class;
1.354 - case 'D': return double.class;
1.355 - case 'L': return Object.class;
1.356 - case 'V': return void.class;
1.357 - default: assert false;
1.358 - }
1.359 - return null;
1.360 - }
1.361 - static MethodType signatureType(String sig) {
1.362 - Class<?>[] ptypes = new Class<?>[signatureArity(sig)];
1.363 - for (int i = 0; i < ptypes.length; i++)
1.364 - ptypes[i] = typeClass(sig.charAt(i));
1.365 - Class<?> rtype = typeClass(signatureReturn(sig));
1.366 - return MethodType.methodType(rtype, ptypes);
1.367 - }
1.368 -
1.369 - /*
1.370 - * Code generation issues:
1.371 - *
1.372 - * Compiled LFs should be reusable in general.
1.373 - * The biggest issue is how to decide when to pull a name into
1.374 - * the bytecode, versus loading a reified form from the MH data.
1.375 - *
1.376 - * For example, an asType wrapper may require execution of a cast
1.377 - * after a call to a MH. The target type of the cast can be placed
1.378 - * as a constant in the LF itself. This will force the cast type
1.379 - * to be compiled into the bytecodes and native code for the MH.
1.380 - * Or, the target type of the cast can be erased in the LF, and
1.381 - * loaded from the MH data. (Later on, if the MH as a whole is
1.382 - * inlined, the data will flow into the inlined instance of the LF,
1.383 - * as a constant, and the end result will be an optimal cast.)
1.384 - *
1.385 - * This erasure of cast types can be done with any use of
1.386 - * reference types. It can also be done with whole method
1.387 - * handles. Erasing a method handle might leave behind
1.388 - * LF code that executes correctly for any MH of a given
1.389 - * type, and load the required MH from the enclosing MH's data.
1.390 - * Or, the erasure might even erase the expected MT.
1.391 - *
1.392 - * Also, for direct MHs, the MemberName of the target
1.393 - * could be erased, and loaded from the containing direct MH.
1.394 - * As a simple case, a LF for all int-valued non-static
1.395 - * field getters would perform a cast on its input argument
1.396 - * (to non-constant base type derived from the MemberName)
1.397 - * and load an integer value from the input object
1.398 - * (at a non-constant offset also derived from the MemberName).
1.399 - * Such MN-erased LFs would be inlinable back to optimized
1.400 - * code, whenever a constant enclosing DMH is available
1.401 - * to supply a constant MN from its data.
1.402 - *
1.403 - * The main problem here is to keep LFs reasonably generic,
1.404 - * while ensuring that hot spots will inline good instances.
1.405 - * "Reasonably generic" means that we don't end up with
1.406 - * repeated versions of bytecode or machine code that do
1.407 - * not differ in their optimized form. Repeated versions
1.408 - * of machine would have the undesirable overheads of
1.409 - * (a) redundant compilation work and (b) extra I$ pressure.
1.410 - * To control repeated versions, we need to be ready to
1.411 - * erase details from LFs and move them into MH data,
1.412 - * whevener those details are not relevant to significant
1.413 - * optimization. "Significant" means optimization of
1.414 - * code that is actually hot.
1.415 - *
1.416 - * Achieving this may require dynamic splitting of MHs, by replacing
1.417 - * a generic LF with a more specialized one, on the same MH,
1.418 - * if (a) the MH is frequently executed and (b) the MH cannot
1.419 - * be inlined into a containing caller, such as an invokedynamic.
1.420 - *
1.421 - * Compiled LFs that are no longer used should be GC-able.
1.422 - * If they contain non-BCP references, they should be properly
1.423 - * interlinked with the class loader(s) that their embedded types
1.424 - * depend on. This probably means that reusable compiled LFs
1.425 - * will be tabulated (indexed) on relevant class loaders,
1.426 - * or else that the tables that cache them will have weak links.
1.427 - */
1.428 -
1.429 - /**
1.430 - * Make this LF directly executable, as part of a MethodHandle.
1.431 - * Invariant: Every MH which is invoked must prepare its LF
1.432 - * before invocation.
1.433 - * (In principle, the JVM could do this very lazily,
1.434 - * as a sort of pre-invocation linkage step.)
1.435 - */
1.436 - public void prepare() {
1.437 - if (COMPILE_THRESHOLD == 0) {
1.438 - compileToBytecode();
1.439 - }
1.440 - if (this.vmentry != null) {
1.441 - // already prepared (e.g., a primitive DMH invoker form)
1.442 - return;
1.443 - }
1.444 - LambdaForm prep = getPreparedForm(basicTypeSignature());
1.445 - this.vmentry = prep.vmentry;
1.446 - // TO DO: Maybe add invokeGeneric, invokeWithArguments
1.447 - }
1.448 -
1.449 - /** Generate optimizable bytecode for this form. */
1.450 - MemberName compileToBytecode() {
1.451 - MethodType invokerType = methodType();
1.452 - assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
1.453 - if (vmentry != null && isCompiled) {
1.454 - return vmentry; // already compiled somehow
1.455 - }
1.456 - throw newInternalError("compileToBytecode", new Exception());
1.457 -// try {
1.458 -// vmentry = InvokerBytecodeGenerator.generateCustomizedCode(this, invokerType);
1.459 -// if (TRACE_INTERPRETER)
1.460 -// traceInterpreter("compileToBytecode", this);
1.461 -// isCompiled = true;
1.462 -// return vmentry;
1.463 -// } catch (Error | Exception ex) {
1.464 -// throw newInternalError("compileToBytecode", ex);
1.465 -// }
1.466 - }
1.467 -
1.468 - private static final ConcurrentHashMap<String,LambdaForm> PREPARED_FORMS;
1.469 - static {
1.470 - int capacity = 512; // expect many distinct signatures over time
1.471 - float loadFactor = 0.75f; // normal default
1.472 - int writers = 1;
1.473 - PREPARED_FORMS = new ConcurrentHashMap<>(capacity, loadFactor, writers);
1.474 - }
1.475 -
1.476 - private static Map<String,LambdaForm> computeInitialPreparedForms() {
1.477 - // Find all predefined invokers and associate them with canonical empty lambda forms.
1.478 - HashMap<String,LambdaForm> forms = new HashMap<>();
1.479 - for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
1.480 - if (!m.isStatic() || !m.isPackage()) continue;
1.481 - MethodType mt = m.getMethodType();
1.482 - if (mt.parameterCount() > 0 &&
1.483 - mt.parameterType(0) == MethodHandle.class &&
1.484 - m.getName().startsWith("interpret_")) {
1.485 - String sig = basicTypeSignature(mt);
1.486 - assert(m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
1.487 - LambdaForm form = new LambdaForm(sig);
1.488 - form.vmentry = m;
1.489 - mt.form().setCachedLambdaForm(MethodTypeForm.LF_COUNTER, form);
1.490 - // FIXME: get rid of PREPARED_FORMS; use MethodTypeForm cache only
1.491 - forms.put(sig, form);
1.492 - }
1.493 - }
1.494 - //System.out.println("computeInitialPreparedForms => "+forms);
1.495 - return forms;
1.496 - }
1.497 -
1.498 - // Set this false to disable use of the interpret_L methods defined in this file.
1.499 - private static final boolean USE_PREDEFINED_INTERPRET_METHODS = true;
1.500 -
1.501 - // The following are predefined exact invokers. The system must build
1.502 - // a separate invoker for each distinct signature.
1.503 - static Object interpret_L(MethodHandle mh) throws Throwable {
1.504 - Object[] av = {mh};
1.505 - String sig = null;
1.506 - assert(argumentTypesMatch(sig = "L_L", av));
1.507 - Object res = mh.form.interpretWithArguments(av);
1.508 - assert(returnTypesMatch(sig, av, res));
1.509 - return res;
1.510 - }
1.511 - static Object interpret_L(MethodHandle mh, Object x1) throws Throwable {
1.512 - Object[] av = {mh, x1};
1.513 - String sig = null;
1.514 - assert(argumentTypesMatch(sig = "LL_L", av));
1.515 - Object res = mh.form.interpretWithArguments(av);
1.516 - assert(returnTypesMatch(sig, av, res));
1.517 - return res;
1.518 - }
1.519 - static Object interpret_L(MethodHandle mh, Object x1, Object x2) throws Throwable {
1.520 - Object[] av = {mh, x1, x2};
1.521 - String sig = null;
1.522 - assert(argumentTypesMatch(sig = "LLL_L", av));
1.523 - Object res = mh.form.interpretWithArguments(av);
1.524 - assert(returnTypesMatch(sig, av, res));
1.525 - return res;
1.526 - }
1.527 - private static LambdaForm getPreparedForm(String sig) {
1.528 - MethodType mtype = signatureType(sig);
1.529 - //LambdaForm prep = PREPARED_FORMS.get(sig);
1.530 - LambdaForm prep = mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET);
1.531 - if (prep != null) return prep;
1.532 - assert(isValidSignature(sig));
1.533 - prep = new LambdaForm(sig);
1.534 -// prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(sig);
1.535 - if (true) throw new IllegalStateException();
1.536 -
1.537 - //LambdaForm prep2 = PREPARED_FORMS.putIfAbsent(sig.intern(), prep);
1.538 - return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep);
1.539 - }
1.540 -
1.541 - // The next few routines are called only from assert expressions
1.542 - // They verify that the built-in invokers process the correct raw data types.
1.543 - private static boolean argumentTypesMatch(String sig, Object[] av) {
1.544 - int arity = signatureArity(sig);
1.545 - assert(av.length == arity) : "av.length == arity: av.length=" + av.length + ", arity=" + arity;
1.546 - assert(av[0] instanceof MethodHandle) : "av[0] not instace of MethodHandle: " + av[0];
1.547 - MethodHandle mh = (MethodHandle) av[0];
1.548 - MethodType mt = mh.type();
1.549 - assert(mt.parameterCount() == arity-1);
1.550 - for (int i = 0; i < av.length; i++) {
1.551 - Class<?> pt = (i == 0 ? MethodHandle.class : mt.parameterType(i-1));
1.552 - assert(valueMatches(sig.charAt(i), pt, av[i]));
1.553 - }
1.554 - return true;
1.555 - }
1.556 - private static boolean valueMatches(char tc, Class<?> type, Object x) {
1.557 - // The following line is needed because (...)void method handles can use non-void invokers
1.558 - if (type == void.class) tc = 'V'; // can drop any kind of value
1.559 - assert tc == basicType(type) : tc + " == basicType(" + type + ")=" + basicType(type);
1.560 - switch (tc) {
1.561 - case 'I': assert checkInt(type, x) : "checkInt(" + type + "," + x +")"; break;
1.562 - case 'J': assert x instanceof Long : "instanceof Long: " + x; break;
1.563 - case 'F': assert x instanceof Float : "instanceof Float: " + x; break;
1.564 - case 'D': assert x instanceof Double : "instanceof Double: " + x; break;
1.565 - case 'L': assert checkRef(type, x) : "checkRef(" + type + "," + x + ")"; break;
1.566 - case 'V': break; // allow anything here; will be dropped
1.567 - default: assert(false);
1.568 - }
1.569 - return true;
1.570 - }
1.571 - private static boolean returnTypesMatch(String sig, Object[] av, Object res) {
1.572 - MethodHandle mh = (MethodHandle) av[0];
1.573 - return valueMatches(signatureReturn(sig), mh.type().returnType(), res);
1.574 - }
1.575 - private static boolean checkInt(Class<?> type, Object x) {
1.576 - assert(x instanceof Integer);
1.577 - if (type == int.class) return true;
1.578 - Wrapper w = Wrapper.forBasicType(type);
1.579 - assert(w.isSubwordOrInt());
1.580 - Object x1 = Wrapper.INT.wrap(w.wrap(x));
1.581 - return x.equals(x1);
1.582 - }
1.583 - private static boolean checkRef(Class<?> type, Object x) {
1.584 - assert(!type.isPrimitive());
1.585 - if (x == null) return true;
1.586 - if (type.isInterface()) return true;
1.587 - return type.isInstance(x);
1.588 - }
1.589 -
1.590 - /** If the invocation count hits the threshold we spin bytecodes and call that subsequently. */
1.591 - private static final int COMPILE_THRESHOLD;
1.592 - static {
1.593 - if (MethodHandleStatics.COMPILE_THRESHOLD != null)
1.594 - COMPILE_THRESHOLD = MethodHandleStatics.COMPILE_THRESHOLD;
1.595 - else
1.596 - COMPILE_THRESHOLD = 30; // default value
1.597 - }
1.598 - private int invocationCounter = 0;
1.599 -
1.600 - @Hidden
1.601 - @DontInline
1.602 - /** Interpretively invoke this form on the given arguments. */
1.603 - Object interpretWithArguments(Object... argumentValues) throws Throwable {
1.604 - if (TRACE_INTERPRETER)
1.605 - return interpretWithArgumentsTracing(argumentValues);
1.606 - checkInvocationCounter();
1.607 - assert(arityCheck(argumentValues));
1.608 - Object[] values = Arrays.copyOf(argumentValues, names.length);
1.609 - for (int i = argumentValues.length; i < values.length; i++) {
1.610 - values[i] = interpretName(names[i], values);
1.611 - }
1.612 - return (result < 0) ? null : values[result];
1.613 - }
1.614 -
1.615 - @Hidden
1.616 - @DontInline
1.617 - /** Evaluate a single Name within this form, applying its function to its arguments. */
1.618 - Object interpretName(Name name, Object[] values) throws Throwable {
1.619 - if (TRACE_INTERPRETER)
1.620 - traceInterpreter("| interpretName", name.debugString(), (Object[]) null);
1.621 - Object[] arguments = Arrays.copyOf(name.arguments, name.arguments.length, Object[].class);
1.622 - for (int i = 0; i < arguments.length; i++) {
1.623 - Object a = arguments[i];
1.624 - if (a instanceof Name) {
1.625 - int i2 = ((Name)a).index();
1.626 - assert(names[i2] == a);
1.627 - a = values[i2];
1.628 - arguments[i] = a;
1.629 - }
1.630 - }
1.631 - return name.function.invokeWithArguments(arguments);
1.632 - }
1.633 -
1.634 - private void checkInvocationCounter() {
1.635 - if (COMPILE_THRESHOLD != 0 &&
1.636 - invocationCounter < COMPILE_THRESHOLD) {
1.637 - invocationCounter++; // benign race
1.638 - if (invocationCounter >= COMPILE_THRESHOLD) {
1.639 - // Replace vmentry with a bytecode version of this LF.
1.640 - compileToBytecode();
1.641 - }
1.642 - }
1.643 - }
1.644 - Object interpretWithArgumentsTracing(Object... argumentValues) throws Throwable {
1.645 - traceInterpreter("[ interpretWithArguments", this, argumentValues);
1.646 - if (invocationCounter < COMPILE_THRESHOLD) {
1.647 - int ctr = invocationCounter++; // benign race
1.648 - traceInterpreter("| invocationCounter", ctr);
1.649 - if (invocationCounter >= COMPILE_THRESHOLD) {
1.650 - compileToBytecode();
1.651 - }
1.652 - }
1.653 - Object rval;
1.654 - try {
1.655 - assert(arityCheck(argumentValues));
1.656 - Object[] values = Arrays.copyOf(argumentValues, names.length);
1.657 - for (int i = argumentValues.length; i < values.length; i++) {
1.658 - values[i] = interpretName(names[i], values);
1.659 - }
1.660 - rval = (result < 0) ? null : values[result];
1.661 - } catch (Throwable ex) {
1.662 - traceInterpreter("] throw =>", ex);
1.663 - throw ex;
1.664 - }
1.665 - traceInterpreter("] return =>", rval);
1.666 - return rval;
1.667 - }
1.668 -
1.669 - //** This transform is applied (statically) to every name.function. */
1.670 - /*
1.671 - private static MethodHandle eraseSubwordTypes(MethodHandle mh) {
1.672 - MethodType mt = mh.type();
1.673 - if (mt.hasPrimitives()) {
1.674 - mt = mt.changeReturnType(eraseSubwordType(mt.returnType()));
1.675 - for (int i = 0; i < mt.parameterCount(); i++) {
1.676 - mt = mt.changeParameterType(i, eraseSubwordType(mt.parameterType(i)));
1.677 - }
1.678 - mh = MethodHandles.explicitCastArguments(mh, mt);
1.679 - }
1.680 - return mh;
1.681 - }
1.682 - private static Class<?> eraseSubwordType(Class<?> type) {
1.683 - if (!type.isPrimitive()) return type;
1.684 - if (type == int.class) return type;
1.685 - Wrapper w = Wrapper.forPrimitiveType(type);
1.686 - if (w.isSubwordOrInt()) return int.class;
1.687 - return type;
1.688 - }
1.689 - */
1.690 -
1.691 - static void traceInterpreter(String event, Object obj, Object... args) {
1.692 - if (TRACE_INTERPRETER) {
1.693 - System.out.println("LFI: "+event+" "+(obj != null ? obj : "")+(args != null && args.length != 0 ? Arrays.asList(args) : ""));
1.694 - }
1.695 - }
1.696 - static void traceInterpreter(String event, Object obj) {
1.697 - traceInterpreter(event, obj, (Object[])null);
1.698 - }
1.699 - private boolean arityCheck(Object[] argumentValues) {
1.700 - assert(argumentValues.length == arity) : arity+"!="+Arrays.asList(argumentValues)+".length";
1.701 - // also check that the leading (receiver) argument is somehow bound to this LF:
1.702 - assert(argumentValues[0] instanceof MethodHandle) : "not MH: " + argumentValues[0];
1.703 - assert(((MethodHandle)argumentValues[0]).internalForm() == this);
1.704 - // note: argument #0 could also be an interface wrapper, in the future
1.705 - return true;
1.706 - }
1.707 -
1.708 - private boolean isEmpty() {
1.709 - if (result < 0)
1.710 - return (names.length == arity);
1.711 - else if (result == arity && names.length == arity + 1)
1.712 - return names[arity].isConstantZero();
1.713 - else
1.714 - return false;
1.715 - }
1.716 -
1.717 - public String toString() {
1.718 - StringBuilder buf = new StringBuilder(debugName+"=Lambda(");
1.719 - for (int i = 0; i < names.length; i++) {
1.720 - if (i == arity) buf.append(")=>{");
1.721 - Name n = names[i];
1.722 - if (i >= arity) buf.append("\n ");
1.723 - buf.append(n);
1.724 - if (i < arity) {
1.725 - if (i+1 < arity) buf.append(",");
1.726 - continue;
1.727 - }
1.728 - buf.append("=").append(n.exprString());
1.729 - buf.append(";");
1.730 - }
1.731 - buf.append(result < 0 ? "void" : names[result]).append("}");
1.732 - if (TRACE_INTERPRETER) {
1.733 - // Extra verbosity:
1.734 - buf.append(":").append(basicTypeSignature());
1.735 - buf.append("/").append(vmentry);
1.736 - }
1.737 - return buf.toString();
1.738 - }
1.739 -
1.740 - /**
1.741 - * Apply immediate binding for a Name in this form indicated by its position relative to the form.
1.742 - * The first parameter to a LambdaForm, a0:L, always represents the form's method handle, so 0 is not
1.743 - * accepted as valid.
1.744 - */
1.745 - LambdaForm bindImmediate(int pos, char basicType, Object value) {
1.746 - // must be an argument, and the types must match
1.747 - assert pos > 0 && pos < arity && names[pos].type == basicType && Name.typesMatch(basicType, value);
1.748 -
1.749 - int arity2 = arity - 1;
1.750 - Name[] names2 = new Name[names.length - 1];
1.751 - for (int r = 0, w = 0; r < names.length; ++r, ++w) { // (r)ead from names, (w)rite to names2
1.752 - Name n = names[r];
1.753 - if (n.isParam()) {
1.754 - if (n.index == pos) {
1.755 - // do not copy over the argument that is to be replaced with a literal,
1.756 - // but adjust the write index
1.757 - --w;
1.758 - } else {
1.759 - names2[w] = new Name(w, n.type);
1.760 - }
1.761 - } else {
1.762 - Object[] arguments2 = new Object[n.arguments.length];
1.763 - for (int i = 0; i < n.arguments.length; ++i) {
1.764 - Object arg = n.arguments[i];
1.765 - if (arg instanceof Name) {
1.766 - int ni = ((Name) arg).index;
1.767 - if (ni == pos) {
1.768 - arguments2[i] = value;
1.769 - } else if (ni < pos) {
1.770 - // replacement position not yet passed
1.771 - arguments2[i] = names2[ni];
1.772 - } else {
1.773 - // replacement position passed
1.774 - arguments2[i] = names2[ni - 1];
1.775 - }
1.776 - } else {
1.777 - arguments2[i] = arg;
1.778 - }
1.779 - }
1.780 - names2[w] = new Name(n.function, arguments2);
1.781 - names2[w].initIndex(w);
1.782 - }
1.783 - }
1.784 -
1.785 - int result2 = result == -1 ? -1 : result - 1;
1.786 - return new LambdaForm(debugName, arity2, names2, result2);
1.787 - }
1.788 -
1.789 - LambdaForm bind(int namePos, BoundMethodHandle.SpeciesData oldData) {
1.790 - Name name = names[namePos];
1.791 - BoundMethodHandle.SpeciesData newData = oldData.extendWithType(name.type);
1.792 - return bind(name, newData.getterName(names[0], oldData.fieldCount()), oldData, newData);
1.793 - }
1.794 - LambdaForm bind(Name name, Name binding,
1.795 - BoundMethodHandle.SpeciesData oldData,
1.796 - BoundMethodHandle.SpeciesData newData) {
1.797 - int pos = name.index;
1.798 - assert(name.isParam());
1.799 - assert(!binding.isParam());
1.800 - assert(name.type == binding.type);
1.801 - assert(0 <= pos && pos < arity && names[pos] == name);
1.802 - assert(binding.function.memberDeclaringClassOrNull() == newData.clazz);
1.803 - assert(oldData.getters.length == newData.getters.length-1);
1.804 - if (bindCache != null) {
1.805 - LambdaForm form = bindCache[pos];
1.806 - if (form != null) {
1.807 - assert(form.contains(binding)) : "form << " + form + " >> does not contain binding << " + binding + " >>";
1.808 - return form;
1.809 - }
1.810 - } else {
1.811 - bindCache = new LambdaForm[arity];
1.812 - }
1.813 - assert(nameRefsAreLegal());
1.814 - int arity2 = arity-1;
1.815 - Name[] names2 = names.clone();
1.816 - names2[pos] = binding; // we might move this in a moment
1.817 -
1.818 - // The newly created LF will run with a different BMH.
1.819 - // Switch over any pre-existing BMH field references to the new BMH class.
1.820 - int firstOldRef = -1;
1.821 - for (int i = 0; i < names2.length; i++) {
1.822 - Name n = names[i];
1.823 - if (n.function != null &&
1.824 - n.function.memberDeclaringClassOrNull() == oldData.clazz) {
1.825 - MethodHandle oldGetter = n.function.resolvedHandle;
1.826 - MethodHandle newGetter = null;
1.827 - for (int j = 0; j < oldData.getters.length; j++) {
1.828 - if (oldGetter == oldData.getters[j])
1.829 - newGetter = newData.getters[j];
1.830 - }
1.831 - if (newGetter != null) {
1.832 - if (firstOldRef < 0) firstOldRef = i;
1.833 - Name n2 = new Name(newGetter, n.arguments);
1.834 - names2[i] = n2;
1.835 - }
1.836 - }
1.837 - }
1.838 -
1.839 - // Walk over the new list of names once, in forward order.
1.840 - // Replace references to 'name' with 'binding'.
1.841 - // Replace data structure references to the old BMH species with the new.
1.842 - // This might cause a ripple effect, but it will settle in one pass.
1.843 - assert(firstOldRef < 0 || firstOldRef > pos);
1.844 - for (int i = pos+1; i < names2.length; i++) {
1.845 - if (i <= arity2) continue;
1.846 - names2[i] = names2[i].replaceNames(names, names2, pos, i);
1.847 - }
1.848 -
1.849 - // (a0, a1, name=a2, a3, a4) => (a0, a1, a3, a4, binding)
1.850 - int insPos = pos;
1.851 - for (; insPos+1 < names2.length; insPos++) {
1.852 - Name n = names2[insPos+1];
1.853 - if (n.isSiblingBindingBefore(binding)) {
1.854 - names2[insPos] = n;
1.855 - } else {
1.856 - break;
1.857 - }
1.858 - }
1.859 - names2[insPos] = binding;
1.860 -
1.861 - // Since we moved some stuff, maybe update the result reference:
1.862 - int result2 = result;
1.863 - if (result2 == pos)
1.864 - result2 = insPos;
1.865 - else if (result2 > pos && result2 <= insPos)
1.866 - result2 -= 1;
1.867 -
1.868 - return bindCache[pos] = new LambdaForm(debugName, arity2, names2, result2);
1.869 - }
1.870 -
1.871 - boolean contains(Name name) {
1.872 - int pos = name.index();
1.873 - if (pos >= 0) {
1.874 - return pos < names.length && name.equals(names[pos]);
1.875 - }
1.876 - for (int i = arity; i < names.length; i++) {
1.877 - if (name.equals(names[i]))
1.878 - return true;
1.879 - }
1.880 - return false;
1.881 - }
1.882 -
1.883 - LambdaForm addArguments(int pos, char... types) {
1.884 - assert(pos <= arity);
1.885 - int length = names.length;
1.886 - int inTypes = types.length;
1.887 - Name[] names2 = Arrays.copyOf(names, length + inTypes);
1.888 - int arity2 = arity + inTypes;
1.889 - int result2 = result;
1.890 - if (result2 >= arity)
1.891 - result2 += inTypes;
1.892 - // names array has MH in slot 0; skip it.
1.893 - int argpos = pos + 1;
1.894 - // Note: The LF constructor will rename names2[argpos...].
1.895 - // Make space for new arguments (shift temporaries).
1.896 - System.arraycopy(names, argpos, names2, argpos + inTypes, length - argpos);
1.897 - for (int i = 0; i < inTypes; i++) {
1.898 - names2[argpos + i] = new Name(types[i]);
1.899 - }
1.900 - return new LambdaForm(debugName, arity2, names2, result2);
1.901 - }
1.902 -
1.903 - LambdaForm addArguments(int pos, List<Class<?>> types) {
1.904 - char[] basicTypes = new char[types.size()];
1.905 - for (int i = 0; i < basicTypes.length; i++)
1.906 - basicTypes[i] = basicType(types.get(i));
1.907 - return addArguments(pos, basicTypes);
1.908 - }
1.909 -
1.910 - LambdaForm permuteArguments(int skip, int[] reorder, char[] types) {
1.911 - // Note: When inArg = reorder[outArg], outArg is fed by a copy of inArg.
1.912 - // The types are the types of the new (incoming) arguments.
1.913 - int length = names.length;
1.914 - int inTypes = types.length;
1.915 - int outArgs = reorder.length;
1.916 - assert(skip+outArgs == arity);
1.917 - assert(permutedTypesMatch(reorder, types, names, skip));
1.918 - int pos = 0;
1.919 - // skip trivial first part of reordering:
1.920 - while (pos < outArgs && reorder[pos] == pos) pos += 1;
1.921 - Name[] names2 = new Name[length - outArgs + inTypes];
1.922 - System.arraycopy(names, 0, names2, 0, skip+pos);
1.923 - // copy the body:
1.924 - int bodyLength = length - arity;
1.925 - System.arraycopy(names, skip+outArgs, names2, skip+inTypes, bodyLength);
1.926 - int arity2 = names2.length - bodyLength;
1.927 - int result2 = result;
1.928 - if (result2 >= 0) {
1.929 - if (result2 < skip+outArgs) {
1.930 - // return the corresponding inArg
1.931 - result2 = reorder[result2-skip];
1.932 - } else {
1.933 - result2 = result2 - outArgs + inTypes;
1.934 - }
1.935 - }
1.936 - // rework names in the body:
1.937 - for (int j = pos; j < outArgs; j++) {
1.938 - Name n = names[skip+j];
1.939 - int i = reorder[j];
1.940 - // replace names[skip+j] by names2[skip+i]
1.941 - Name n2 = names2[skip+i];
1.942 - if (n2 == null)
1.943 - names2[skip+i] = n2 = new Name(types[i]);
1.944 - else
1.945 - assert(n2.type == types[i]);
1.946 - for (int k = arity2; k < names2.length; k++) {
1.947 - names2[k] = names2[k].replaceName(n, n2);
1.948 - }
1.949 - }
1.950 - // some names are unused, but must be filled in
1.951 - for (int i = skip+pos; i < arity2; i++) {
1.952 - if (names2[i] == null)
1.953 - names2[i] = argument(i, types[i - skip]);
1.954 - }
1.955 - for (int j = arity; j < names.length; j++) {
1.956 - int i = j - arity + arity2;
1.957 - // replace names2[i] by names[j]
1.958 - Name n = names[j];
1.959 - Name n2 = names2[i];
1.960 - if (n != n2) {
1.961 - for (int k = i+1; k < names2.length; k++) {
1.962 - names2[k] = names2[k].replaceName(n, n2);
1.963 - }
1.964 - }
1.965 - }
1.966 - return new LambdaForm(debugName, arity2, names2, result2);
1.967 - }
1.968 -
1.969 - static boolean permutedTypesMatch(int[] reorder, char[] types, Name[] names, int skip) {
1.970 - int inTypes = types.length;
1.971 - int outArgs = reorder.length;
1.972 - for (int i = 0; i < outArgs; i++) {
1.973 - assert(names[skip+i].isParam());
1.974 - assert(names[skip+i].type == types[reorder[i]]);
1.975 - }
1.976 - return true;
1.977 - }
1.978 -
1.979 - static class NamedFunction {
1.980 - final MemberName member;
1.981 - @Stable MethodHandle resolvedHandle;
1.982 - @Stable MethodHandle invoker;
1.983 -
1.984 - NamedFunction(MethodHandle resolvedHandle) {
1.985 - this(resolvedHandle.internalMemberName(), resolvedHandle);
1.986 - }
1.987 - NamedFunction(MemberName member, MethodHandle resolvedHandle) {
1.988 - this.member = member;
1.989 - //resolvedHandle = eraseSubwordTypes(resolvedHandle);
1.990 - this.resolvedHandle = resolvedHandle;
1.991 - }
1.992 - NamedFunction(MethodType basicInvokerType) {
1.993 - assert(basicInvokerType == basicInvokerType.basicType()) : basicInvokerType;
1.994 - if (basicInvokerType.parameterSlotCount() < MethodType.MAX_MH_INVOKER_ARITY) {
1.995 - this.resolvedHandle = basicInvokerType.invokers().basicInvoker();
1.996 - this.member = resolvedHandle.internalMemberName();
1.997 - } else {
1.998 - // necessary to pass BigArityTest
1.999 - this.member = Invokers.invokeBasicMethod(basicInvokerType);
1.1000 - }
1.1001 - }
1.1002 -
1.1003 - // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc.
1.1004 - // Any LambdaForm containing such a member is not interpretable.
1.1005 - // This is OK, since all such LFs are prepared with special primitive vmentry points.
1.1006 - // And even without the resolvedHandle, the name can still be compiled and optimized.
1.1007 - NamedFunction(Method method) {
1.1008 - this(new MemberName(method));
1.1009 - }
1.1010 - NamedFunction(Field field) {
1.1011 - this(new MemberName(field));
1.1012 - }
1.1013 - NamedFunction(MemberName member) {
1.1014 - this.member = member;
1.1015 - this.resolvedHandle = null;
1.1016 - }
1.1017 -
1.1018 - MethodHandle resolvedHandle() {
1.1019 - if (resolvedHandle == null) resolve();
1.1020 - return resolvedHandle;
1.1021 - }
1.1022 -
1.1023 - void resolve() {
1.1024 - resolvedHandle = DirectMethodHandle.make(member);
1.1025 - }
1.1026 -
1.1027 - @Override
1.1028 - public boolean equals(Object other) {
1.1029 - if (this == other) return true;
1.1030 - if (other == null) return false;
1.1031 - if (!(other instanceof NamedFunction)) return false;
1.1032 - NamedFunction that = (NamedFunction) other;
1.1033 - return this.member != null && this.member.equals(that.member);
1.1034 - }
1.1035 -
1.1036 - @Override
1.1037 - public int hashCode() {
1.1038 - if (member != null)
1.1039 - return member.hashCode();
1.1040 - return super.hashCode();
1.1041 - }
1.1042 -
1.1043 - // Put the predefined NamedFunction invokers into the table.
1.1044 - static void initializeInvokers() {
1.1045 - for (MemberName m : MemberName.getFactory().getMethods(NamedFunction.class, false, null, null, null)) {
1.1046 - if (!m.isStatic() || !m.isPackage()) continue;
1.1047 - MethodType type = m.getMethodType();
1.1048 - if (type.equals(INVOKER_METHOD_TYPE) &&
1.1049 - m.getName().startsWith("invoke_")) {
1.1050 - String sig = m.getName().substring("invoke_".length());
1.1051 - int arity = LambdaForm.signatureArity(sig);
1.1052 - MethodType srcType = MethodType.genericMethodType(arity);
1.1053 - if (LambdaForm.signatureReturn(sig) == 'V')
1.1054 - srcType = srcType.changeReturnType(void.class);
1.1055 - MethodTypeForm typeForm = srcType.form();
1.1056 - typeForm.namedFunctionInvoker = DirectMethodHandle.make(m);
1.1057 - }
1.1058 - }
1.1059 - }
1.1060 -
1.1061 - // The following are predefined NamedFunction invokers. The system must build
1.1062 - // a separate invoker for each distinct signature.
1.1063 - /** void return type invokers. */
1.1064 - @Hidden
1.1065 - static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable {
1.1066 - assert(a.length == 0);
1.1067 - mh.invokeBasic();
1.1068 - return null;
1.1069 - }
1.1070 - @Hidden
1.1071 - static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable {
1.1072 - assert(a.length == 1);
1.1073 - mh.invokeBasic(a[0]);
1.1074 - return null;
1.1075 - }
1.1076 - @Hidden
1.1077 - static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable {
1.1078 - assert(a.length == 2);
1.1079 - mh.invokeBasic(a[0], a[1]);
1.1080 - return null;
1.1081 - }
1.1082 - @Hidden
1.1083 - static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable {
1.1084 - assert(a.length == 3);
1.1085 - mh.invokeBasic(a[0], a[1], a[2]);
1.1086 - return null;
1.1087 - }
1.1088 - @Hidden
1.1089 - static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable {
1.1090 - assert(a.length == 4);
1.1091 - mh.invokeBasic(a[0], a[1], a[2], a[3]);
1.1092 - return null;
1.1093 - }
1.1094 - @Hidden
1.1095 - static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable {
1.1096 - assert(a.length == 5);
1.1097 - mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
1.1098 - return null;
1.1099 - }
1.1100 - /** Object return type invokers. */
1.1101 - @Hidden
1.1102 - static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable {
1.1103 - assert(a.length == 0);
1.1104 - return mh.invokeBasic();
1.1105 - }
1.1106 - @Hidden
1.1107 - static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable {
1.1108 - assert(a.length == 1);
1.1109 - return mh.invokeBasic(a[0]);
1.1110 - }
1.1111 - @Hidden
1.1112 - static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable {
1.1113 - assert(a.length == 2);
1.1114 - return mh.invokeBasic(a[0], a[1]);
1.1115 - }
1.1116 - @Hidden
1.1117 - static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable {
1.1118 - assert(a.length == 3);
1.1119 - return mh.invokeBasic(a[0], a[1], a[2]);
1.1120 - }
1.1121 - @Hidden
1.1122 - static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable {
1.1123 - assert(a.length == 4);
1.1124 - return mh.invokeBasic(a[0], a[1], a[2], a[3]);
1.1125 - }
1.1126 - @Hidden
1.1127 - static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable {
1.1128 - assert(a.length == 5);
1.1129 - return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
1.1130 - }
1.1131 -
1.1132 - static final MethodType INVOKER_METHOD_TYPE =
1.1133 - MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
1.1134 -
1.1135 - private static MethodHandle computeInvoker(MethodTypeForm typeForm) {
1.1136 - MethodHandle mh = typeForm.namedFunctionInvoker;
1.1137 - if (mh != null) return mh;
1.1138 -// MemberName invoker = InvokerBytecodeGenerator.generateNamedFunctionInvoker(typeForm); // this could take a while
1.1139 - if (true) throw new IllegalStateException();
1.1140 -// mh = DirectMethodHandle.make(invoker);
1.1141 - MethodHandle mh2 = typeForm.namedFunctionInvoker;
1.1142 - if (mh2 != null) return mh2; // benign race
1.1143 - if (!mh.type().equals(INVOKER_METHOD_TYPE))
1.1144 - throw new InternalError(mh.debugString());
1.1145 - return typeForm.namedFunctionInvoker = mh;
1.1146 - }
1.1147 -
1.1148 - @Hidden
1.1149 - Object invokeWithArguments(Object... arguments) throws Throwable {
1.1150 - // If we have a cached invoker, call it right away.
1.1151 - // NOTE: The invoker always returns a reference value.
1.1152 - if (TRACE_INTERPRETER) return invokeWithArgumentsTracing(arguments);
1.1153 - assert(checkArgumentTypes(arguments, methodType()));
1.1154 - return invoker().invokeBasic(resolvedHandle(), arguments);
1.1155 - }
1.1156 -
1.1157 - @Hidden
1.1158 - Object invokeWithArgumentsTracing(Object[] arguments) throws Throwable {
1.1159 - Object rval;
1.1160 - try {
1.1161 - traceInterpreter("[ call", this, arguments);
1.1162 - if (invoker == null) {
1.1163 - traceInterpreter("| getInvoker", this);
1.1164 - invoker();
1.1165 - }
1.1166 - if (resolvedHandle == null) {
1.1167 - traceInterpreter("| resolve", this);
1.1168 - resolvedHandle();
1.1169 - }
1.1170 - assert(checkArgumentTypes(arguments, methodType()));
1.1171 - rval = invoker().invokeBasic(resolvedHandle(), arguments);
1.1172 - } catch (Throwable ex) {
1.1173 - traceInterpreter("] throw =>", ex);
1.1174 - throw ex;
1.1175 - }
1.1176 - traceInterpreter("] return =>", rval);
1.1177 - return rval;
1.1178 - }
1.1179 -
1.1180 - private MethodHandle invoker() {
1.1181 - if (invoker != null) return invoker;
1.1182 - // Get an invoker and cache it.
1.1183 - return invoker = computeInvoker(methodType().form());
1.1184 - }
1.1185 -
1.1186 - private static boolean checkArgumentTypes(Object[] arguments, MethodType methodType) {
1.1187 - if (true) return true; // FIXME
1.1188 - MethodType dstType = methodType.form().erasedType();
1.1189 - MethodType srcType = dstType.basicType().wrap();
1.1190 - Class<?>[] ptypes = new Class<?>[arguments.length];
1.1191 - for (int i = 0; i < arguments.length; i++) {
1.1192 - Object arg = arguments[i];
1.1193 - Class<?> ptype = arg == null ? Object.class : arg.getClass();
1.1194 - // If the dest. type is a primitive we keep the
1.1195 - // argument type.
1.1196 - ptypes[i] = dstType.parameterType(i).isPrimitive() ? ptype : Object.class;
1.1197 - }
1.1198 - MethodType argType = MethodType.methodType(srcType.returnType(), ptypes).wrap();
1.1199 - assert(argType.isConvertibleTo(srcType)) : "wrong argument types: cannot convert " + argType + " to " + srcType;
1.1200 - return true;
1.1201 - }
1.1202 -
1.1203 - String basicTypeSignature() {
1.1204 - //return LambdaForm.basicTypeSignature(resolvedHandle.type());
1.1205 - return LambdaForm.basicTypeSignature(methodType());
1.1206 - }
1.1207 -
1.1208 - MethodType methodType() {
1.1209 - if (resolvedHandle != null)
1.1210 - return resolvedHandle.type();
1.1211 - else
1.1212 - // only for certain internal LFs during bootstrapping
1.1213 - return member.getInvocationType();
1.1214 - }
1.1215 -
1.1216 - MemberName member() {
1.1217 - assert(assertMemberIsConsistent());
1.1218 - return member;
1.1219 - }
1.1220 -
1.1221 - // Called only from assert.
1.1222 - private boolean assertMemberIsConsistent() {
1.1223 - if (resolvedHandle instanceof DirectMethodHandle) {
1.1224 - MemberName m = resolvedHandle.internalMemberName();
1.1225 - assert(m.equals(member));
1.1226 - }
1.1227 - return true;
1.1228 - }
1.1229 -
1.1230 - Class<?> memberDeclaringClassOrNull() {
1.1231 - return (member == null) ? null : member.getDeclaringClass();
1.1232 - }
1.1233 -
1.1234 - char returnType() {
1.1235 - return basicType(methodType().returnType());
1.1236 - }
1.1237 -
1.1238 - char parameterType(int n) {
1.1239 - return basicType(methodType().parameterType(n));
1.1240 - }
1.1241 -
1.1242 - int arity() {
1.1243 - //int siglen = member.getMethodType().parameterCount();
1.1244 - //if (!member.isStatic()) siglen += 1;
1.1245 - //return siglen;
1.1246 - return methodType().parameterCount();
1.1247 - }
1.1248 -
1.1249 - public String toString() {
1.1250 - if (member == null) return String.valueOf(resolvedHandle);
1.1251 - return member.getDeclaringClass().getSimpleName()+"."+member.getName();
1.1252 - }
1.1253 - }
1.1254 -
1.1255 - void resolve() {
1.1256 - for (Name n : names) n.resolve();
1.1257 - }
1.1258 -
1.1259 - public static char basicType(Class<?> type) {
1.1260 - char c = Wrapper.basicTypeChar(type);
1.1261 - if ("ZBSC".indexOf(c) >= 0) c = 'I';
1.1262 - assert("LIJFDV".indexOf(c) >= 0);
1.1263 - return c;
1.1264 - }
1.1265 - public static char[] basicTypes(List<Class<?>> types) {
1.1266 - char[] btypes = new char[types.size()];
1.1267 - for (int i = 0; i < btypes.length; i++) {
1.1268 - btypes[i] = basicType(types.get(i));
1.1269 - }
1.1270 - return btypes;
1.1271 - }
1.1272 - public static String basicTypeSignature(MethodType type) {
1.1273 - char[] sig = new char[type.parameterCount() + 2];
1.1274 - int sigp = 0;
1.1275 - for (Class<?> pt : type.parameterList()) {
1.1276 - sig[sigp++] = basicType(pt);
1.1277 - }
1.1278 - sig[sigp++] = '_';
1.1279 - sig[sigp++] = basicType(type.returnType());
1.1280 - assert(sigp == sig.length);
1.1281 - return String.valueOf(sig);
1.1282 - }
1.1283 -
1.1284 - static final class Name {
1.1285 - final char type;
1.1286 - private short index;
1.1287 - final NamedFunction function;
1.1288 - @Stable final Object[] arguments;
1.1289 -
1.1290 - private Name(int index, char type, NamedFunction function, Object[] arguments) {
1.1291 - this.index = (short)index;
1.1292 - this.type = type;
1.1293 - this.function = function;
1.1294 - this.arguments = arguments;
1.1295 - assert(this.index == index);
1.1296 - }
1.1297 - Name(MethodHandle function, Object... arguments) {
1.1298 - this(new NamedFunction(function), arguments);
1.1299 - }
1.1300 - Name(MethodType functionType, Object... arguments) {
1.1301 - this(new NamedFunction(functionType), arguments);
1.1302 - assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == 'L');
1.1303 - }
1.1304 - Name(MemberName function, Object... arguments) {
1.1305 - this(new NamedFunction(function), arguments);
1.1306 - }
1.1307 - Name(NamedFunction function, Object... arguments) {
1.1308 - this(-1, function.returnType(), function, arguments = arguments.clone());
1.1309 - assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString();
1.1310 - for (int i = 0; i < arguments.length; i++)
1.1311 - assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString();
1.1312 - }
1.1313 - Name(int index, char type) {
1.1314 - this(index, type, null, null);
1.1315 - }
1.1316 - Name(char type) {
1.1317 - this(-1, type);
1.1318 - }
1.1319 -
1.1320 - char type() { return type; }
1.1321 - int index() { return index; }
1.1322 - boolean initIndex(int i) {
1.1323 - if (index != i) {
1.1324 - if (index != -1) return false;
1.1325 - index = (short)i;
1.1326 - }
1.1327 - return true;
1.1328 - }
1.1329 -
1.1330 -
1.1331 - void resolve() {
1.1332 - if (function != null)
1.1333 - function.resolve();
1.1334 - }
1.1335 -
1.1336 - Name newIndex(int i) {
1.1337 - if (initIndex(i)) return this;
1.1338 - return cloneWithIndex(i);
1.1339 - }
1.1340 - Name cloneWithIndex(int i) {
1.1341 - Object[] newArguments = (arguments == null) ? null : arguments.clone();
1.1342 - return new Name(i, type, function, newArguments);
1.1343 - }
1.1344 - Name replaceName(Name oldName, Name newName) { // FIXME: use replaceNames uniformly
1.1345 - if (oldName == newName) return this;
1.1346 - @SuppressWarnings("LocalVariableHidesMemberVariable")
1.1347 - Object[] arguments = this.arguments;
1.1348 - if (arguments == null) return this;
1.1349 - boolean replaced = false;
1.1350 - for (int j = 0; j < arguments.length; j++) {
1.1351 - if (arguments[j] == oldName) {
1.1352 - if (!replaced) {
1.1353 - replaced = true;
1.1354 - arguments = arguments.clone();
1.1355 - }
1.1356 - arguments[j] = newName;
1.1357 - }
1.1358 - }
1.1359 - if (!replaced) return this;
1.1360 - return new Name(function, arguments);
1.1361 - }
1.1362 - Name replaceNames(Name[] oldNames, Name[] newNames, int start, int end) {
1.1363 - @SuppressWarnings("LocalVariableHidesMemberVariable")
1.1364 - Object[] arguments = this.arguments;
1.1365 - boolean replaced = false;
1.1366 - eachArg:
1.1367 - for (int j = 0; j < arguments.length; j++) {
1.1368 - if (arguments[j] instanceof Name) {
1.1369 - Name n = (Name) arguments[j];
1.1370 - int check = n.index;
1.1371 - // harmless check to see if the thing is already in newNames:
1.1372 - if (check >= 0 && check < newNames.length && n == newNames[check])
1.1373 - continue eachArg;
1.1374 - // n might not have the correct index: n != oldNames[n.index].
1.1375 - for (int i = start; i < end; i++) {
1.1376 - if (n == oldNames[i]) {
1.1377 - if (n == newNames[i])
1.1378 - continue eachArg;
1.1379 - if (!replaced) {
1.1380 - replaced = true;
1.1381 - arguments = arguments.clone();
1.1382 - }
1.1383 - arguments[j] = newNames[i];
1.1384 - continue eachArg;
1.1385 - }
1.1386 - }
1.1387 - }
1.1388 - }
1.1389 - if (!replaced) return this;
1.1390 - return new Name(function, arguments);
1.1391 - }
1.1392 - void internArguments() {
1.1393 - @SuppressWarnings("LocalVariableHidesMemberVariable")
1.1394 - Object[] arguments = this.arguments;
1.1395 - for (int j = 0; j < arguments.length; j++) {
1.1396 - if (arguments[j] instanceof Name) {
1.1397 - Name n = (Name) arguments[j];
1.1398 - if (n.isParam() && n.index < INTERNED_ARGUMENT_LIMIT)
1.1399 - arguments[j] = internArgument(n);
1.1400 - }
1.1401 - }
1.1402 - }
1.1403 - boolean isParam() {
1.1404 - return function == null;
1.1405 - }
1.1406 - boolean isConstantZero() {
1.1407 - return !isParam() && arguments.length == 0 && function.equals(constantZero(0, type).function);
1.1408 - }
1.1409 -
1.1410 - public String toString() {
1.1411 - return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+type;
1.1412 - }
1.1413 - public String debugString() {
1.1414 - String s = toString();
1.1415 - return (function == null) ? s : s + "=" + exprString();
1.1416 - }
1.1417 - public String exprString() {
1.1418 - if (function == null) return "null";
1.1419 - StringBuilder buf = new StringBuilder(function.toString());
1.1420 - buf.append("(");
1.1421 - String cma = "";
1.1422 - for (Object a : arguments) {
1.1423 - buf.append(cma); cma = ",";
1.1424 - if (a instanceof Name || a instanceof Integer)
1.1425 - buf.append(a);
1.1426 - else
1.1427 - buf.append("(").append(a).append(")");
1.1428 - }
1.1429 - buf.append(")");
1.1430 - return buf.toString();
1.1431 - }
1.1432 -
1.1433 - private static boolean typesMatch(char parameterType, Object object) {
1.1434 - if (object instanceof Name) {
1.1435 - return ((Name)object).type == parameterType;
1.1436 - }
1.1437 - switch (parameterType) {
1.1438 - case 'I': return object instanceof Integer;
1.1439 - case 'J': return object instanceof Long;
1.1440 - case 'F': return object instanceof Float;
1.1441 - case 'D': return object instanceof Double;
1.1442 - }
1.1443 - assert(parameterType == 'L');
1.1444 - return true;
1.1445 - }
1.1446 -
1.1447 - /**
1.1448 - * Does this Name precede the given binding node in some canonical order?
1.1449 - * This predicate is used to order data bindings (via insertion sort)
1.1450 - * with some stability.
1.1451 - */
1.1452 - boolean isSiblingBindingBefore(Name binding) {
1.1453 - assert(!binding.isParam());
1.1454 - if (isParam()) return true;
1.1455 - if (function.equals(binding.function) &&
1.1456 - arguments.length == binding.arguments.length) {
1.1457 - boolean sawInt = false;
1.1458 - for (int i = 0; i < arguments.length; i++) {
1.1459 - Object a1 = arguments[i];
1.1460 - Object a2 = binding.arguments[i];
1.1461 - if (!a1.equals(a2)) {
1.1462 - if (a1 instanceof Integer && a2 instanceof Integer) {
1.1463 - if (sawInt) continue;
1.1464 - sawInt = true;
1.1465 - if ((int)a1 < (int)a2) continue; // still might be true
1.1466 - }
1.1467 - return false;
1.1468 - }
1.1469 - }
1.1470 - return sawInt;
1.1471 - }
1.1472 - return false;
1.1473 - }
1.1474 -
1.1475 - public boolean equals(Name that) {
1.1476 - if (this == that) return true;
1.1477 - if (isParam())
1.1478 - // each parameter is a unique atom
1.1479 - return false; // this != that
1.1480 - return
1.1481 - //this.index == that.index &&
1.1482 - this.type == that.type &&
1.1483 - this.function.equals(that.function) &&
1.1484 - Arrays.equals(this.arguments, that.arguments);
1.1485 - }
1.1486 - @Override
1.1487 - public boolean equals(Object x) {
1.1488 - return x instanceof Name && equals((Name)x);
1.1489 - }
1.1490 - @Override
1.1491 - public int hashCode() {
1.1492 - if (isParam())
1.1493 - return index | (type << 8);
1.1494 - return function.hashCode() ^ Arrays.hashCode(arguments);
1.1495 - }
1.1496 - }
1.1497 -
1.1498 - static Name argument(int which, char type) {
1.1499 - int tn = ALL_TYPES.indexOf(type);
1.1500 - if (tn < 0 || which >= INTERNED_ARGUMENT_LIMIT)
1.1501 - return new Name(which, type);
1.1502 - return INTERNED_ARGUMENTS[tn][which];
1.1503 - }
1.1504 - static Name internArgument(Name n) {
1.1505 - assert(n.isParam()) : "not param: " + n;
1.1506 - assert(n.index < INTERNED_ARGUMENT_LIMIT);
1.1507 - return argument(n.index, n.type);
1.1508 - }
1.1509 - static Name[] arguments(int extra, String types) {
1.1510 - int length = types.length();
1.1511 - Name[] names = new Name[length + extra];
1.1512 - for (int i = 0; i < length; i++)
1.1513 - names[i] = argument(i, types.charAt(i));
1.1514 - return names;
1.1515 - }
1.1516 - static Name[] arguments(int extra, char... types) {
1.1517 - int length = types.length;
1.1518 - Name[] names = new Name[length + extra];
1.1519 - for (int i = 0; i < length; i++)
1.1520 - names[i] = argument(i, types[i]);
1.1521 - return names;
1.1522 - }
1.1523 - static Name[] arguments(int extra, List<Class<?>> types) {
1.1524 - int length = types.size();
1.1525 - Name[] names = new Name[length + extra];
1.1526 - for (int i = 0; i < length; i++)
1.1527 - names[i] = argument(i, basicType(types.get(i)));
1.1528 - return names;
1.1529 - }
1.1530 - static Name[] arguments(int extra, Class<?>... types) {
1.1531 - int length = types.length;
1.1532 - Name[] names = new Name[length + extra];
1.1533 - for (int i = 0; i < length; i++)
1.1534 - names[i] = argument(i, basicType(types[i]));
1.1535 - return names;
1.1536 - }
1.1537 - static Name[] arguments(int extra, MethodType types) {
1.1538 - int length = types.parameterCount();
1.1539 - Name[] names = new Name[length + extra];
1.1540 - for (int i = 0; i < length; i++)
1.1541 - names[i] = argument(i, basicType(types.parameterType(i)));
1.1542 - return names;
1.1543 - }
1.1544 - static final String ALL_TYPES = "LIJFD"; // omit V, not an argument type
1.1545 - static final int INTERNED_ARGUMENT_LIMIT = 10;
1.1546 - private static final Name[][] INTERNED_ARGUMENTS
1.1547 - = new Name[ALL_TYPES.length()][INTERNED_ARGUMENT_LIMIT];
1.1548 - static {
1.1549 - for (int tn = 0; tn < ALL_TYPES.length(); tn++) {
1.1550 - for (int i = 0; i < INTERNED_ARGUMENTS[tn].length; i++) {
1.1551 - char type = ALL_TYPES.charAt(tn);
1.1552 - INTERNED_ARGUMENTS[tn][i] = new Name(i, type);
1.1553 - }
1.1554 - }
1.1555 - }
1.1556 -
1.1557 - private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
1.1558 -
1.1559 - static Name constantZero(int which, char type) {
1.1560 - return CONSTANT_ZERO[ALL_TYPES.indexOf(type)].newIndex(which);
1.1561 - }
1.1562 - private static final Name[] CONSTANT_ZERO
1.1563 - = new Name[ALL_TYPES.length()];
1.1564 - static {
1.1565 - for (int tn = 0; tn < ALL_TYPES.length(); tn++) {
1.1566 - char bt = ALL_TYPES.charAt(tn);
1.1567 - Wrapper wrap = Wrapper.forBasicType(bt);
1.1568 - MemberName zmem = new MemberName(LambdaForm.class, "zero"+bt, MethodType.methodType(wrap.primitiveType()), REF_invokeStatic);
1.1569 - try {
1.1570 - zmem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zmem, null, NoSuchMethodException.class);
1.1571 - } catch (IllegalAccessException|NoSuchMethodException ex) {
1.1572 - throw newInternalError(ex);
1.1573 - }
1.1574 - NamedFunction zcon = new NamedFunction(zmem);
1.1575 - Name n = new Name(zcon).newIndex(0);
1.1576 - assert(n.type == ALL_TYPES.charAt(tn));
1.1577 - CONSTANT_ZERO[tn] = n;
1.1578 - assert(n.isConstantZero());
1.1579 - }
1.1580 - }
1.1581 -
1.1582 - // Avoid appealing to ValueConversions at bootstrap time:
1.1583 - private static int zeroI() { return 0; }
1.1584 - private static long zeroJ() { return 0; }
1.1585 - private static float zeroF() { return 0; }
1.1586 - private static double zeroD() { return 0; }
1.1587 - private static Object zeroL() { return null; }
1.1588 -
1.1589 - // Put this last, so that previous static inits can run before.
1.1590 - static {
1.1591 - if (USE_PREDEFINED_INTERPRET_METHODS)
1.1592 - PREPARED_FORMS.putAll(computeInitialPreparedForms());
1.1593 - }
1.1594 -
1.1595 - /**
1.1596 - * Internal marker for byte-compiled LambdaForms.
1.1597 - */
1.1598 - /*non-public*/
1.1599 - @Target(ElementType.METHOD)
1.1600 - @Retention(RetentionPolicy.RUNTIME)
1.1601 - @interface Compiled {
1.1602 - }
1.1603 -
1.1604 - /**
1.1605 - * Internal marker for LambdaForm interpreter frames.
1.1606 - */
1.1607 - /*non-public*/
1.1608 - @Target(ElementType.METHOD)
1.1609 - @Retention(RetentionPolicy.RUNTIME)
1.1610 - @interface Hidden {
1.1611 - }
1.1612 -
1.1613 -
1.1614 -/*
1.1615 - // Smoke-test for the invokers used in this file.
1.1616 - static void testMethodHandleLinkers() throws Throwable {
1.1617 - MemberName.Factory lookup = MemberName.getFactory();
1.1618 - MemberName asList_MN = new MemberName(Arrays.class, "asList",
1.1619 - MethodType.methodType(List.class, Object[].class),
1.1620 - REF_invokeStatic);
1.1621 - //MethodHandleNatives.resolve(asList_MN, null);
1.1622 - asList_MN = lookup.resolveOrFail(asList_MN, REF_invokeStatic, null, NoSuchMethodException.class);
1.1623 - System.out.println("about to call "+asList_MN);
1.1624 - Object[] abc = { "a", "bc" };
1.1625 - List<?> lst = (List<?>) MethodHandle.linkToStatic(abc, asList_MN);
1.1626 - System.out.println("lst="+lst);
1.1627 - MemberName toString_MN = new MemberName(Object.class.getMethod("toString"));
1.1628 - String s1 = (String) MethodHandle.linkToVirtual(lst, toString_MN);
1.1629 - toString_MN = new MemberName(Object.class.getMethod("toString"), true);
1.1630 - String s2 = (String) MethodHandle.linkToSpecial(lst, toString_MN);
1.1631 - System.out.println("[s1,s2,lst]="+Arrays.asList(s1, s2, lst.toString()));
1.1632 - MemberName toArray_MN = new MemberName(List.class.getMethod("toArray"));
1.1633 - Object[] arr = (Object[]) MethodHandle.linkToInterface(lst, toArray_MN);
1.1634 - System.out.println("toArray="+Arrays.toString(arr));
1.1635 - }
1.1636 - static { try { testMethodHandleLinkers(); } catch (Throwable ex) { throw new RuntimeException(ex); } }
1.1637 - // Requires these definitions in MethodHandle:
1.1638 - static final native Object linkToStatic(Object x1, MemberName mn) throws Throwable;
1.1639 - static final native Object linkToVirtual(Object x1, MemberName mn) throws Throwable;
1.1640 - static final native Object linkToSpecial(Object x1, MemberName mn) throws Throwable;
1.1641 - static final native Object linkToInterface(Object x1, MemberName mn) throws Throwable;
1.1642 - */
1.1643 -
1.1644 - static { NamedFunction.initializeInvokers(); }
1.1645 -
1.1646 - // The following hack is necessary in order to suppress TRACE_INTERPRETER
1.1647 - // during execution of the static initializes of this class.
1.1648 - // Turning on TRACE_INTERPRETER too early will cause
1.1649 - // stack overflows and other misbehavior during attempts to trace events
1.1650 - // that occur during LambdaForm.<clinit>.
1.1651 - // Therefore, do not move this line higher in this file, and do not remove.
1.1652 - private static final boolean TRACE_INTERPRETER = MethodHandleStatics.TRACE_INTERPRETER;
1.1653 -}