7012648: move JSR 292 to package java.lang.invoke and adjust names
Summary: package and class renaming only; delete unused methods and classes; add @since tags; no code changes
Reviewed-by: twisti
--- a/jdk/make/common/Release.gmk Fri Mar 18 00:03:24 2011 -0700
+++ b/jdk/make/common/Release.gmk Wed Mar 23 23:02:31 2011 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -54,9 +54,6 @@
com.sun.java.swing.plaf.motif \
com.sun.java.swing.plaf.gtk
-# This is a stopgap until 6839872 is fixed.
-EXCLUDE_PROPWARN_PKGS += sun.dyn
-
#
# Include the exported private packages in ct.sym.
# This is an interim solution until the ct.sym is replaced
--- a/jdk/make/docs/CORE_PKGS.gmk Fri Mar 18 00:03:24 2011 -0700
+++ b/jdk/make/docs/CORE_PKGS.gmk Wed Mar 23 23:02:31 2011 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -55,7 +55,7 @@
# This is a list of regular expressions. So foo.* matches "foo" and "foo.bar".
#
ACTIVE_JSR_PKGS= \
- java.dyn \
+ java.lang.invoke \
java.sql \
javax.activation \
javax.annotation.* \
@@ -97,11 +97,11 @@
java.awt.print \
java.beans \
java.beans.beancontext \
- java.dyn \
java.io \
java.lang \
java.lang.annotation \
java.lang.instrument \
+ java.lang.invoke \
java.lang.management \
java.lang.ref \
java.lang.reflect \
--- a/jdk/make/java/Makefile Fri Mar 18 00:03:24 2011 -0700
+++ b/jdk/make/java/Makefile Wed Mar 23 23:02:31 2011 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
SUBDIRS_desktop = awt applet beans
SUBDIRS_management = management
SUBDIRS_misc = npt java_crw_demo java_hprof_demo \
- logging instrument dyn sql rmi
+ logging instrument invoke sql rmi
ifeq ($(PLATFORM), solaris)
--- a/jdk/make/java/dyn/Makefile Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#
-# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-BUILDDIR = ../..
-
-PACKAGE = java.dyn
-PRODUCT = java
-include $(BUILDDIR)/common/Defs.gmk
-
-AUTO_FILES_JAVA_DIRS = java/dyn sun/dyn
-
-# The sources built here use new language syntax to generate
-# method handle calls. Let's be sure we are using that format.
-LANGUAGE_VERSION = -source 7
-CLASS_VERSION = -target 7
-
-# Tell the compiler not to accept transitional forms.
-OTHER_JAVACFLAGS = -XDallowTransitionalJSR292=no
-
-include $(BUILDDIR)/common/Classes.gmk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/java/invoke/Makefile Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+BUILDDIR = ../..
+
+PACKAGE = java.lang.invoke
+PRODUCT = java
+include $(BUILDDIR)/common/Defs.gmk
+
+AUTO_FILES_JAVA_DIRS = java/lang/invoke sun/invoke
+FILES_java = \
+ java/lang/ClassValue.java \
+ java/lang/BootstrapMethodError.java
+
+# The sources built here use new language syntax to generate
+# method handle calls. Let's be sure we are using that format.
+LANGUAGE_VERSION = -source 7
+CLASS_VERSION = -target 7
+
+include $(BUILDDIR)/common/Classes.gmk
--- a/jdk/src/share/classes/java/dyn/AdapterMethodHandle.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,943 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.util.VerifyType;
-import sun.dyn.util.Wrapper;
-import java.util.Arrays;
-import static java.dyn.MethodHandleNatives.Constants.*;
-import static java.dyn.MethodHandleStatics.*;
-
-/**
- * This method handle performs simple conversion or checking of a single argument.
- * @author jrose
- */
-class AdapterMethodHandle extends BoundMethodHandle {
-
- //MethodHandle vmtarget; // next AMH or BMH in chain or final DMH
- //Object argument; // parameter to the conversion if needed
- //int vmargslot; // which argument slot is affected
- private final int conversion; // the type of conversion: RETYPE_ONLY, etc.
-
- // Constructors in this class *must* be package scoped or private.
- private AdapterMethodHandle(MethodHandle target, MethodType newType,
- long conv, Object convArg) {
- super(newType, convArg, newType.parameterSlotDepth(1+convArgPos(conv)));
- this.conversion = convCode(conv);
- // JVM might update VM-specific bits of conversion (ignore)
- MethodHandleNatives.init(this, target, convArgPos(conv));
- }
- private AdapterMethodHandle(MethodHandle target, MethodType newType,
- long conv) {
- this(target, newType, conv, null);
- }
-
- // TO DO: When adapting another MH with a null conversion, clone
- // the target and change its type, instead of adding another layer.
-
- /** Can a JVM-level adapter directly implement the proposed
- * argument conversions, as if by MethodHandles.convertArguments?
- */
- static boolean canPairwiseConvert(MethodType newType, MethodType oldType) {
- // same number of args, of course
- int len = newType.parameterCount();
- if (len != oldType.parameterCount())
- return false;
-
- // Check return type. (Not much can be done with it.)
- Class<?> exp = newType.returnType();
- Class<?> ret = oldType.returnType();
- if (!VerifyType.isNullConversion(ret, exp))
- return false;
-
- // Check args pairwise.
- for (int i = 0; i < len; i++) {
- Class<?> src = newType.parameterType(i); // source type
- Class<?> dst = oldType.parameterType(i); // destination type
- if (!canConvertArgument(src, dst))
- return false;
- }
-
- return true;
- }
-
- /** Can a JVM-level adapter directly implement the proposed
- * argument conversion, as if by MethodHandles.convertArguments?
- */
- static boolean canConvertArgument(Class<?> src, Class<?> dst) {
- // ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
- // so we don't need to repeat so much decision making.
- if (VerifyType.isNullConversion(src, dst)) {
- return true;
- } else if (src.isPrimitive()) {
- if (dst.isPrimitive())
- return canPrimCast(src, dst);
- else
- return canBoxArgument(src, dst);
- } else {
- if (dst.isPrimitive())
- return canUnboxArgument(src, dst);
- else
- return true; // any two refs can be interconverted
- }
- }
-
- /**
- * Create a JVM-level adapter method handle to conform the given method
- * handle to the similar newType, using only pairwise argument conversions.
- * For each argument, convert incoming argument to the exact type needed.
- * Only null conversions are allowed on the return value (until
- * the JVM supports ricochet adapters).
- * The argument conversions allowed are casting, unboxing,
- * integral widening or narrowing, and floating point widening or narrowing.
- * @param newType required call type
- * @param target original method handle
- * @return an adapter to the original handle with the desired new type,
- * or the original target if the types are already identical
- * or null if the adaptation cannot be made
- */
- static MethodHandle makePairwiseConvert(MethodType newType, MethodHandle target) {
- MethodType oldType = target.type();
- if (newType == oldType) return target;
-
- if (!canPairwiseConvert(newType, oldType))
- return null;
- // (after this point, it is an assertion error to fail to convert)
-
- // Find last non-trivial conversion (if any).
- int lastConv = newType.parameterCount()-1;
- while (lastConv >= 0) {
- Class<?> src = newType.parameterType(lastConv); // source type
- Class<?> dst = oldType.parameterType(lastConv); // destination type
- if (VerifyType.isNullConversion(src, dst)) {
- --lastConv;
- } else {
- break;
- }
- }
- // Now build a chain of one or more adapters.
- MethodHandle adapter = target;
- MethodType midType = oldType.changeReturnType(newType.returnType());
- for (int i = 0; i <= lastConv; i++) {
- Class<?> src = newType.parameterType(i); // source type
- Class<?> dst = midType.parameterType(i); // destination type
- if (VerifyType.isNullConversion(src, dst)) {
- // do nothing: difference is trivial
- continue;
- }
- // Work the current type backward toward the desired caller type:
- if (i != lastConv) {
- midType = midType.changeParameterType(i, src);
- } else {
- // When doing the last (or only) real conversion,
- // force all remaining null conversions to happen also.
- assert(VerifyType.isNullConversion(newType, midType.changeParameterType(i, src)));
- midType = newType;
- }
-
- // Tricky case analysis follows.
- // It parallels canConvertArgument() above.
- if (src.isPrimitive()) {
- if (dst.isPrimitive()) {
- adapter = makePrimCast(midType, adapter, i, dst);
- } else {
- adapter = makeBoxArgument(midType, adapter, i, dst);
- }
- } else {
- if (dst.isPrimitive()) {
- // Caller has boxed a primitive. Unbox it for the target.
- // The box type must correspond exactly to the primitive type.
- // This is simpler than the powerful set of widening
- // conversions supported by reflect.Method.invoke.
- // Those conversions require a big nest of if/then/else logic,
- // which we prefer to make a user responsibility.
- adapter = makeUnboxArgument(midType, adapter, i, dst);
- } else {
- // Simple reference conversion.
- // Note: Do not check for a class hierarchy relation
- // between src and dst. In all cases a 'null' argument
- // will pass the cast conversion.
- adapter = makeCheckCast(midType, adapter, i, dst);
- }
- }
- assert(adapter != null);
- assert(adapter.type() == midType);
- }
- if (adapter.type() != newType) {
- // Only trivial conversions remain.
- adapter = makeRetypeOnly(newType, adapter);
- assert(adapter != null);
- // Actually, that's because there were no non-trivial ones:
- assert(lastConv == -1);
- }
- assert(adapter.type() == newType);
- return adapter;
- }
-
- /**
- * Create a JVM-level adapter method handle to permute the arguments
- * of the given method.
- * @param newType required call type
- * @param target original method handle
- * @param argumentMap for each target argument, position of its source in newType
- * @return an adapter to the original handle with the desired new type,
- * or the original target if the types are already identical
- * and the permutation is null
- * @throws IllegalArgumentException if the adaptation cannot be made
- * directly by a JVM-level adapter, without help from Java code
- */
- static MethodHandle makePermutation(MethodType newType, MethodHandle target,
- int[] argumentMap) {
- MethodType oldType = target.type();
- boolean nullPermutation = true;
- for (int i = 0; i < argumentMap.length; i++) {
- int pos = argumentMap[i];
- if (pos != i)
- nullPermutation = false;
- if (pos < 0 || pos >= newType.parameterCount()) {
- argumentMap = new int[0]; break;
- }
- }
- if (argumentMap.length != oldType.parameterCount())
- throw newIllegalArgumentException("bad permutation: "+Arrays.toString(argumentMap));
- if (nullPermutation) {
- MethodHandle res = makePairwiseConvert(newType, target);
- // well, that was easy
- if (res == null)
- throw newIllegalArgumentException("cannot convert pairwise: "+newType);
- return res;
- }
-
- // Check return type. (Not much can be done with it.)
- Class<?> exp = newType.returnType();
- Class<?> ret = oldType.returnType();
- if (!VerifyType.isNullConversion(ret, exp))
- throw newIllegalArgumentException("bad return conversion for "+newType);
-
- // See if the argument types match up.
- for (int i = 0; i < argumentMap.length; i++) {
- int j = argumentMap[i];
- Class<?> src = newType.parameterType(j);
- Class<?> dst = oldType.parameterType(i);
- if (!VerifyType.isNullConversion(src, dst))
- throw newIllegalArgumentException("bad argument #"+j+" conversion for "+newType);
- }
-
- // Now figure out a nice mix of SWAP, ROT, DUP, and DROP adapters.
- // A workable greedy algorithm is as follows:
- // Drop unused outgoing arguments (right to left: shallowest first).
- // Duplicate doubly-used outgoing arguments (left to right: deepest first).
- // Then the remaining problem is a true argument permutation.
- // Marshal the outgoing arguments as required from left to right.
- // That is, find the deepest outgoing stack position that does not yet
- // have the correct argument value, and correct at least that position
- // by swapping or rotating in the misplaced value (from a shallower place).
- // If the misplaced value is followed by one or more consecutive values
- // (also misplaced) issue a rotation which brings as many as possible
- // into position. Otherwise make progress with either a swap or a
- // rotation. Prefer the swap as cheaper, but do not use it if it
- // breaks a slot pair. Prefer the rotation over the swap if it would
- // preserve more consecutive values shallower than the target position.
- // When more than one rotation will work (because the required value
- // is already adjacent to the target position), then use a rotation
- // which moves the old value in the target position adjacent to
- // one of its consecutive values. Also, prefer shorter rotation
- // spans, since they use fewer memory cycles for shuffling.
-
- throw new UnsupportedOperationException("NYI");
- }
-
- private static byte basicType(Class<?> type) {
- if (type == null) return T_VOID;
- switch (Wrapper.forBasicType(type)) {
- case BOOLEAN: return T_BOOLEAN;
- case CHAR: return T_CHAR;
- case FLOAT: return T_FLOAT;
- case DOUBLE: return T_DOUBLE;
- case BYTE: return T_BYTE;
- case SHORT: return T_SHORT;
- case INT: return T_INT;
- case LONG: return T_LONG;
- case OBJECT: return T_OBJECT;
- case VOID: return T_VOID;
- }
- return 99; // T_ILLEGAL or some such
- }
-
- /** Number of stack slots for the given type.
- * Two for T_DOUBLE and T_FLOAT, one for the rest.
- */
- private static int type2size(int type) {
- assert(type >= T_BOOLEAN && type <= T_OBJECT);
- return (type == T_LONG || type == T_DOUBLE) ? 2 : 1;
- }
- private static int type2size(Class<?> type) {
- return type2size(basicType(type));
- }
-
- /** The given stackMove is the number of slots pushed.
- * It might be negative. Scale it (multiply) by the
- * VM's notion of how an address changes with a push,
- * to get the raw SP change for stackMove.
- * Then shift and mask it into the correct field.
- */
- private static long insertStackMove(int stackMove) {
- // following variable must be long to avoid sign extension after '<<'
- long spChange = stackMove * MethodHandleNatives.JVM_STACK_MOVE_UNIT;
- return (spChange & CONV_STACK_MOVE_MASK) << CONV_STACK_MOVE_SHIFT;
- }
-
- /** Construct an adapter conversion descriptor for a single-argument conversion. */
- private static long makeConv(int convOp, int argnum, int src, int dest) {
- assert(src == (src & 0xF));
- assert(dest == (dest & 0xF));
- assert(convOp >= OP_CHECK_CAST && convOp <= OP_PRIM_TO_REF);
- int stackMove = type2size(dest) - type2size(src);
- return ((long) argnum << 32 |
- (long) convOp << CONV_OP_SHIFT |
- (int) src << CONV_SRC_TYPE_SHIFT |
- (int) dest << CONV_DEST_TYPE_SHIFT |
- insertStackMove(stackMove)
- );
- }
- private static long makeConv(int convOp, int argnum, int stackMove) {
- assert(convOp >= OP_DUP_ARGS && convOp <= OP_SPREAD_ARGS);
- byte src = 0, dest = 0;
- if (convOp >= OP_COLLECT_ARGS && convOp <= OP_SPREAD_ARGS)
- src = dest = T_OBJECT;
- return ((long) argnum << 32 |
- (long) convOp << CONV_OP_SHIFT |
- (int) src << CONV_SRC_TYPE_SHIFT |
- (int) dest << CONV_DEST_TYPE_SHIFT |
- insertStackMove(stackMove)
- );
- }
- private static long makeSwapConv(int convOp, int srcArg, byte type, int destSlot) {
- assert(convOp >= OP_SWAP_ARGS && convOp <= OP_ROT_ARGS);
- return ((long) srcArg << 32 |
- (long) convOp << CONV_OP_SHIFT |
- (int) type << CONV_SRC_TYPE_SHIFT |
- (int) type << CONV_DEST_TYPE_SHIFT |
- (int) destSlot << CONV_VMINFO_SHIFT
- );
- }
- private static long makeConv(int convOp) {
- assert(convOp == OP_RETYPE_ONLY || convOp == OP_RETYPE_RAW);
- return ((long)-1 << 32) | (convOp << CONV_OP_SHIFT); // stackMove, src, dst all zero
- }
- private static int convCode(long conv) {
- return (int)conv;
- }
- private static int convArgPos(long conv) {
- return (int)(conv >>> 32);
- }
- private static boolean convOpSupported(int convOp) {
- assert(convOp >= 0 && convOp <= CONV_OP_LIMIT);
- return ((1<<convOp) & MethodHandleNatives.CONV_OP_IMPLEMENTED_MASK) != 0;
- }
-
- /** One of OP_RETYPE_ONLY, etc. */
- int conversionOp() { return (conversion & CONV_OP_MASK) >> CONV_OP_SHIFT; }
-
- /* Return one plus the position of the first non-trivial difference
- * between the given types. This is not a symmetric operation;
- * we are considering adapting the targetType to adapterType.
- * Trivial differences are those which could be ignored by the JVM
- * without subverting the verifier. Otherwise, adaptable differences
- * are ones for which we could create an adapter to make the type change.
- * Return zero if there are no differences (other than trivial ones).
- * Return 1+N if N is the only adaptable argument difference.
- * Return the -2-N where N is the first of several adaptable
- * argument differences.
- * Return -1 if there there are differences which are not adaptable.
- */
- private static int diffTypes(MethodType adapterType,
- MethodType targetType,
- boolean raw) {
- int diff;
- diff = diffReturnTypes(adapterType, targetType, raw);
- if (diff != 0) return diff;
- int nargs = adapterType.parameterCount();
- if (nargs != targetType.parameterCount())
- return -1;
- diff = diffParamTypes(adapterType, 0, targetType, 0, nargs, raw);
- //System.out.println("diff "+adapterType);
- //System.out.println(" "+diff+" "+targetType);
- return diff;
- }
- private static int diffReturnTypes(MethodType adapterType,
- MethodType targetType,
- boolean raw) {
- Class<?> src = targetType.returnType();
- Class<?> dst = adapterType.returnType();
- if ((!raw
- ? VerifyType.canPassUnchecked(src, dst)
- : VerifyType.canPassRaw(src, dst)
- ) > 0)
- return 0; // no significant difference
- if (raw && !src.isPrimitive() && !dst.isPrimitive())
- return 0; // can force a reference return (very carefully!)
- //if (false) return 1; // never adaptable!
- return -1; // some significant difference
- }
- private static int diffParamTypes(MethodType adapterType, int astart,
- MethodType targetType, int tstart,
- int nargs, boolean raw) {
- assert(nargs >= 0);
- int res = 0;
- for (int i = 0; i < nargs; i++) {
- Class<?> src = adapterType.parameterType(astart+i);
- Class<?> dest = targetType.parameterType(tstart+i);
- if ((!raw
- ? VerifyType.canPassUnchecked(src, dest)
- : VerifyType.canPassRaw(src, dest)
- ) <= 0) {
- // found a difference; is it the only one so far?
- if (res != 0)
- return -1-res; // return -2-i for prev. i
- res = 1+i;
- }
- }
- return res;
- }
-
- /** Can a retyping adapter (alone) validly convert the target to newType? */
- static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
- return canRetype(newType, targetType, false);
- }
- /** Can a retyping adapter (alone) convert the target to newType?
- * It is allowed to widen subword types and void to int, to make bitwise
- * conversions between float/int and double/long, and to perform unchecked
- * reference conversions on return. This last feature requires that the
- * caller be trusted, and perform explicit cast conversions on return values.
- */
- static boolean canRetypeRaw(MethodType newType, MethodType targetType) {
- return canRetype(newType, targetType, true);
- }
- static boolean canRetype(MethodType newType, MethodType targetType, boolean raw) {
- if (!convOpSupported(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY)) return false;
- int diff = diffTypes(newType, targetType, raw);
- // %%% This assert is too strong. Factor diff into VerifyType and reconcile.
- assert(raw || (diff == 0) == VerifyType.isNullConversion(newType, targetType));
- return diff == 0;
- }
-
- /** Factory method: Performs no conversions; simply retypes the adapter.
- * Allows unchecked argument conversions pairwise, if they are safe.
- * Returns null if not possible.
- */
- static MethodHandle makeRetypeOnly(MethodType newType, MethodHandle target) {
- return makeRetype(newType, target, false);
- }
- static MethodHandle makeRetypeRaw(MethodType newType, MethodHandle target) {
- return makeRetype(newType, target, true);
- }
- static MethodHandle makeRetype(MethodType newType, MethodHandle target, boolean raw) {
- MethodType oldType = target.type();
- if (oldType == newType) return target;
- if (!canRetype(newType, oldType, raw))
- return null;
- // TO DO: clone the target guy, whatever he is, with new type.
- return new AdapterMethodHandle(target, newType, makeConv(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY));
- }
-
- static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
- return new AsVarargsCollector(target, arrayType);
- }
-
- static class AsVarargsCollector extends AdapterMethodHandle {
- final MethodHandle target;
- final Class<?> arrayType;
- MethodHandle cache;
-
- AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
- super(target, target.type(), makeConv(OP_RETYPE_ONLY));
- this.target = target;
- this.arrayType = arrayType;
- this.cache = target.asCollector(arrayType, 0);
- }
-
- @Override
- public boolean isVarargsCollector() {
- return true;
- }
-
- @Override
- public MethodHandle asType(MethodType newType) {
- MethodType type = this.type();
- int collectArg = type.parameterCount() - 1;
- int newArity = newType.parameterCount();
- if (newArity == collectArg+1 &&
- type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
- // if arity and trailing parameter are compatible, do normal thing
- return super.asType(newType);
- }
- // check cache
- if (cache.type().parameterCount() == newArity)
- return cache.asType(newType);
- // build and cache a collector
- int arrayLength = newArity - collectArg;
- MethodHandle collector;
- try {
- collector = target.asCollector(arrayType, arrayLength);
- } catch (IllegalArgumentException ex) {
- throw new WrongMethodTypeException("cannot build collector");
- }
- cache = collector;
- return collector.asType(newType);
- }
-
- @Override
- public MethodHandle asVarargsCollector(Class<?> arrayType) {
- MethodType type = this.type();
- if (type.parameterType(type.parameterCount()-1) == arrayType)
- return this;
- return super.asVarargsCollector(arrayType);
- }
- }
-
- /** Can a checkcast adapter validly convert the target to newType?
- * The JVM supports all kind of reference casts, even silly ones.
- */
- static boolean canCheckCast(MethodType newType, MethodType targetType,
- int arg, Class<?> castType) {
- if (!convOpSupported(OP_CHECK_CAST)) return false;
- Class<?> src = newType.parameterType(arg);
- Class<?> dst = targetType.parameterType(arg);
- if (!canCheckCast(src, castType)
- || !VerifyType.isNullConversion(castType, dst))
- return false;
- int diff = diffTypes(newType, targetType, false);
- return (diff == arg+1); // arg is sole non-trivial diff
- }
- /** Can an primitive conversion adapter validly convert src to dst? */
- static boolean canCheckCast(Class<?> src, Class<?> dst) {
- return (!src.isPrimitive() && !dst.isPrimitive());
- }
-
- /** Factory method: Forces a cast at the given argument.
- * The castType is the target of the cast, and can be any type
- * with a null conversion to the corresponding target parameter.
- * Return null if this cannot be done.
- */
- static MethodHandle makeCheckCast(MethodType newType, MethodHandle target,
- int arg, Class<?> castType) {
- if (!canCheckCast(newType, target.type(), arg, castType))
- return null;
- long conv = makeConv(OP_CHECK_CAST, arg, T_OBJECT, T_OBJECT);
- return new AdapterMethodHandle(target, newType, conv, castType);
- }
-
- /** Can an primitive conversion adapter validly convert the target to newType?
- * The JVM currently supports all conversions except those between
- * floating and integral types.
- */
- static boolean canPrimCast(MethodType newType, MethodType targetType,
- int arg, Class<?> convType) {
- if (!convOpSupported(OP_PRIM_TO_PRIM)) return false;
- Class<?> src = newType.parameterType(arg);
- Class<?> dst = targetType.parameterType(arg);
- if (!canPrimCast(src, convType)
- || !VerifyType.isNullConversion(convType, dst))
- return false;
- int diff = diffTypes(newType, targetType, false);
- return (diff == arg+1); // arg is sole non-trivial diff
- }
- /** Can an primitive conversion adapter validly convert src to dst? */
- static boolean canPrimCast(Class<?> src, Class<?> dst) {
- if (src == dst || !src.isPrimitive() || !dst.isPrimitive()) {
- return false;
- } else if (Wrapper.forPrimitiveType(dst).isFloating()) {
- // both must be floating types
- return Wrapper.forPrimitiveType(src).isFloating();
- } else {
- // both are integral, and all combinations work fine
- assert(Wrapper.forPrimitiveType(src).isIntegral() &&
- Wrapper.forPrimitiveType(dst).isIntegral());
- return true;
- }
- }
-
- /** Factory method: Truncate the given argument with zero or sign extension,
- * and/or convert between single and doubleword versions of integer or float.
- * The convType is the target of the conversion, and can be any type
- * with a null conversion to the corresponding target parameter.
- * Return null if this cannot be done.
- */
- static MethodHandle makePrimCast(MethodType newType, MethodHandle target,
- int arg, Class<?> convType) {
- MethodType oldType = target.type();
- if (!canPrimCast(newType, oldType, arg, convType))
- return null;
- Class<?> src = newType.parameterType(arg);
- long conv = makeConv(OP_PRIM_TO_PRIM, arg, basicType(src), basicType(convType));
- return new AdapterMethodHandle(target, newType, conv);
- }
-
- /** Can an unboxing conversion validly convert src to dst?
- * The JVM currently supports all kinds of casting and unboxing.
- * The convType is the unboxed type; it can be either a primitive or wrapper.
- */
- static boolean canUnboxArgument(MethodType newType, MethodType targetType,
- int arg, Class<?> convType) {
- if (!convOpSupported(OP_REF_TO_PRIM)) return false;
- Class<?> src = newType.parameterType(arg);
- Class<?> dst = targetType.parameterType(arg);
- Class<?> boxType = Wrapper.asWrapperType(convType);
- convType = Wrapper.asPrimitiveType(convType);
- if (!canCheckCast(src, boxType)
- || boxType == convType
- || !VerifyType.isNullConversion(convType, dst))
- return false;
- int diff = diffTypes(newType, targetType, false);
- return (diff == arg+1); // arg is sole non-trivial diff
- }
- /** Can an primitive unboxing adapter validly convert src to dst? */
- static boolean canUnboxArgument(Class<?> src, Class<?> dst) {
- return (!src.isPrimitive() && Wrapper.asPrimitiveType(dst).isPrimitive());
- }
-
- /** Factory method: Unbox the given argument.
- * Return null if this cannot be done.
- */
- static MethodHandle makeUnboxArgument(MethodType newType, MethodHandle target,
- int arg, Class<?> convType) {
- MethodType oldType = target.type();
- Class<?> src = newType.parameterType(arg);
- Class<?> dst = oldType.parameterType(arg);
- Class<?> boxType = Wrapper.asWrapperType(convType);
- Class<?> primType = Wrapper.asPrimitiveType(convType);
- if (!canUnboxArgument(newType, oldType, arg, convType))
- return null;
- MethodType castDone = newType;
- if (!VerifyType.isNullConversion(src, boxType))
- castDone = newType.changeParameterType(arg, boxType);
- long conv = makeConv(OP_REF_TO_PRIM, arg, T_OBJECT, basicType(primType));
- MethodHandle adapter = new AdapterMethodHandle(target, castDone, conv, boxType);
- if (castDone == newType)
- return adapter;
- return makeCheckCast(newType, adapter, arg, boxType);
- }
-
- /** Can an primitive boxing adapter validly convert src to dst? */
- static boolean canBoxArgument(Class<?> src, Class<?> dst) {
- if (!convOpSupported(OP_PRIM_TO_REF)) return false;
- throw new UnsupportedOperationException("NYI");
- }
-
- /** Factory method: Unbox the given argument.
- * Return null if this cannot be done.
- */
- static MethodHandle makeBoxArgument(MethodType newType, MethodHandle target,
- int arg, Class<?> convType) {
- // this is difficult to do in the JVM because it must GC
- return null;
- }
-
- /** Can an adapter simply drop arguments to convert the target to newType? */
- static boolean canDropArguments(MethodType newType, MethodType targetType,
- int dropArgPos, int dropArgCount) {
- if (dropArgCount == 0)
- return canRetypeOnly(newType, targetType);
- if (!convOpSupported(OP_DROP_ARGS)) return false;
- if (diffReturnTypes(newType, targetType, false) != 0)
- return false;
- int nptypes = newType.parameterCount();
- // parameter types must be the same up to the drop point
- if (dropArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, dropArgPos, false) != 0)
- return false;
- int afterPos = dropArgPos + dropArgCount;
- int afterCount = nptypes - afterPos;
- if (dropArgPos < 0 || dropArgPos >= nptypes ||
- dropArgCount < 1 || afterPos > nptypes ||
- targetType.parameterCount() != nptypes - dropArgCount)
- return false;
- // parameter types after the drop point must also be the same
- if (afterCount != 0 && diffParamTypes(newType, afterPos, targetType, dropArgPos, afterCount, false) != 0)
- return false;
- return true;
- }
-
- /** Factory method: Drop selected arguments.
- * Allow unchecked retyping of remaining arguments, pairwise.
- * Return null if this is not possible.
- */
- static MethodHandle makeDropArguments(MethodType newType, MethodHandle target,
- int dropArgPos, int dropArgCount) {
- if (dropArgCount == 0)
- return makeRetypeOnly(newType, target);
- if (!canDropArguments(newType, target.type(), dropArgPos, dropArgCount))
- return null;
- // in arglist: [0: ...keep1 | dpos: drop... | dpos+dcount: keep2... ]
- // out arglist: [0: ...keep1 | dpos: keep2... ]
- int keep2InPos = dropArgPos + dropArgCount;
- int dropSlot = newType.parameterSlotDepth(keep2InPos);
- int keep1InSlot = newType.parameterSlotDepth(dropArgPos);
- int slotCount = keep1InSlot - dropSlot;
- assert(slotCount >= dropArgCount);
- assert(target.type().parameterSlotCount() + slotCount == newType.parameterSlotCount());
- long conv = makeConv(OP_DROP_ARGS, dropArgPos + dropArgCount - 1, -slotCount);
- return new AdapterMethodHandle(target, newType, conv);
- }
-
- /** Can an adapter duplicate an argument to convert the target to newType? */
- static boolean canDupArguments(MethodType newType, MethodType targetType,
- int dupArgPos, int dupArgCount) {
- if (!convOpSupported(OP_DUP_ARGS)) return false;
- if (diffReturnTypes(newType, targetType, false) != 0)
- return false;
- int nptypes = newType.parameterCount();
- if (dupArgCount < 0 || dupArgPos + dupArgCount > nptypes)
- return false;
- if (targetType.parameterCount() != nptypes + dupArgCount)
- return false;
- // parameter types must be the same up to the duplicated arguments
- if (diffParamTypes(newType, 0, targetType, 0, nptypes, false) != 0)
- return false;
- // duplicated types must be, well, duplicates
- if (diffParamTypes(newType, dupArgPos, targetType, nptypes, dupArgCount, false) != 0)
- return false;
- return true;
- }
-
- /** Factory method: Duplicate the selected argument.
- * Return null if this is not possible.
- */
- static MethodHandle makeDupArguments(MethodType newType, MethodHandle target,
- int dupArgPos, int dupArgCount) {
- if (!canDupArguments(newType, target.type(), dupArgPos, dupArgCount))
- return null;
- if (dupArgCount == 0)
- return target;
- // in arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... ]
- // out arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... | dup... ]
- int keep2InPos = dupArgPos + dupArgCount;
- int dupSlot = newType.parameterSlotDepth(keep2InPos);
- int keep1InSlot = newType.parameterSlotDepth(dupArgPos);
- int slotCount = keep1InSlot - dupSlot;
- assert(target.type().parameterSlotCount() - slotCount == newType.parameterSlotCount());
- long conv = makeConv(OP_DUP_ARGS, dupArgPos + dupArgCount - 1, slotCount);
- return new AdapterMethodHandle(target, newType, conv);
- }
-
- /** Can an adapter swap two arguments to convert the target to newType? */
- static boolean canSwapArguments(MethodType newType, MethodType targetType,
- int swapArg1, int swapArg2) {
- if (!convOpSupported(OP_SWAP_ARGS)) return false;
- if (diffReturnTypes(newType, targetType, false) != 0)
- return false;
- if (swapArg1 >= swapArg2) return false; // caller resp
- int nptypes = newType.parameterCount();
- if (targetType.parameterCount() != nptypes)
- return false;
- if (swapArg1 < 0 || swapArg2 >= nptypes)
- return false;
- if (diffParamTypes(newType, 0, targetType, 0, swapArg1, false) != 0)
- return false;
- if (diffParamTypes(newType, swapArg1, targetType, swapArg2, 1, false) != 0)
- return false;
- if (diffParamTypes(newType, swapArg1+1, targetType, swapArg1+1, swapArg2-swapArg1-1, false) != 0)
- return false;
- if (diffParamTypes(newType, swapArg2, targetType, swapArg1, 1, false) != 0)
- return false;
- if (diffParamTypes(newType, swapArg2+1, targetType, swapArg2+1, nptypes-swapArg2-1, false) != 0)
- return false;
- return true;
- }
-
- /** Factory method: Swap the selected arguments.
- * Return null if this is not possible.
- */
- static MethodHandle makeSwapArguments(MethodType newType, MethodHandle target,
- int swapArg1, int swapArg2) {
- if (swapArg1 == swapArg2)
- return target;
- if (swapArg1 > swapArg2) { int t = swapArg1; swapArg1 = swapArg2; swapArg2 = t; }
- if (!canSwapArguments(newType, target.type(), swapArg1, swapArg2))
- return null;
- Class<?> swapType = newType.parameterType(swapArg1);
- // in arglist: [0: ...keep1 | pos1: a1 | pos1+1: keep2... | pos2: a2 | pos2+1: keep3... ]
- // out arglist: [0: ...keep1 | pos1: a2 | pos1+1: keep2... | pos2: a1 | pos2+1: keep3... ]
- int swapSlot2 = newType.parameterSlotDepth(swapArg2 + 1);
- long conv = makeSwapConv(OP_SWAP_ARGS, swapArg1, basicType(swapType), swapSlot2);
- return new AdapterMethodHandle(target, newType, conv);
- }
-
- static int positiveRotation(int argCount, int rotateBy) {
- assert(argCount > 0);
- if (rotateBy >= 0) {
- if (rotateBy < argCount)
- return rotateBy;
- return rotateBy % argCount;
- } else if (rotateBy >= -argCount) {
- return rotateBy + argCount;
- } else {
- return (-1-((-1-rotateBy) % argCount)) + argCount;
- }
- }
-
- final static int MAX_ARG_ROTATION = 1;
-
- /** Can an adapter rotate arguments to convert the target to newType? */
- static boolean canRotateArguments(MethodType newType, MethodType targetType,
- int firstArg, int argCount, int rotateBy) {
- if (!convOpSupported(OP_ROT_ARGS)) return false;
- if (argCount <= 2) return false; // must be a swap, not a rotate
- rotateBy = positiveRotation(argCount, rotateBy);
- if (rotateBy == 0) return false; // no rotation
- if (rotateBy > MAX_ARG_ROTATION && rotateBy < argCount - MAX_ARG_ROTATION)
- return false; // too many argument positions
- // Rotate incoming args right N to the out args, N in 1..(argCouunt-1).
- if (diffReturnTypes(newType, targetType, false) != 0)
- return false;
- int nptypes = newType.parameterCount();
- if (targetType.parameterCount() != nptypes)
- return false;
- if (firstArg < 0 || firstArg >= nptypes) return false;
- int argLimit = firstArg + argCount;
- if (argLimit > nptypes) return false;
- if (diffParamTypes(newType, 0, targetType, 0, firstArg, false) != 0)
- return false;
- int newChunk1 = argCount - rotateBy, newChunk2 = rotateBy;
- // swap new chunk1 with target chunk2
- if (diffParamTypes(newType, firstArg, targetType, argLimit-newChunk1, newChunk1, false) != 0)
- return false;
- // swap new chunk2 with target chunk1
- if (diffParamTypes(newType, firstArg+newChunk1, targetType, firstArg, newChunk2, false) != 0)
- return false;
- return true;
- }
-
- /** Factory method: Rotate the selected argument range.
- * Return null if this is not possible.
- */
- static MethodHandle makeRotateArguments(MethodType newType, MethodHandle target,
- int firstArg, int argCount, int rotateBy) {
- rotateBy = positiveRotation(argCount, rotateBy);
- if (!canRotateArguments(newType, target.type(), firstArg, argCount, rotateBy))
- return null;
- // Decide whether it should be done as a right or left rotation,
- // on the JVM stack. Return the number of stack slots to rotate by,
- // positive if right, negative if left.
- int limit = firstArg + argCount;
- int depth0 = newType.parameterSlotDepth(firstArg);
- int depth1 = newType.parameterSlotDepth(limit-rotateBy);
- int depth2 = newType.parameterSlotDepth(limit);
- int chunk1Slots = depth0 - depth1; assert(chunk1Slots > 0);
- int chunk2Slots = depth1 - depth2; assert(chunk2Slots > 0);
- // From here on out, it assumes a single-argument shift.
- assert(MAX_ARG_ROTATION == 1);
- int srcArg, dstArg;
- byte basicType;
- if (chunk2Slots <= chunk1Slots) {
- // Rotate right/down N (rotateBy = +N, N small, c2 small):
- // in arglist: [0: ...keep1 | arg1: c1... | limit-N: c2 | limit: keep2... ]
- // out arglist: [0: ...keep1 | arg1: c2 | arg1+N: c1... | limit: keep2... ]
- srcArg = limit-1;
- dstArg = firstArg;
- basicType = basicType(newType.parameterType(srcArg));
- assert(chunk2Slots == type2size(basicType));
- } else {
- // Rotate left/up N (rotateBy = -N, N small, c1 small):
- // in arglist: [0: ...keep1 | arg1: c1 | arg1+N: c2... | limit: keep2... ]
- // out arglist: [0: ...keep1 | arg1: c2 ... | limit-N: c1 | limit: keep2... ]
- srcArg = firstArg;
- dstArg = limit-1;
- basicType = basicType(newType.parameterType(srcArg));
- assert(chunk1Slots == type2size(basicType));
- }
- int dstSlot = newType.parameterSlotDepth(dstArg + 1);
- long conv = makeSwapConv(OP_ROT_ARGS, srcArg, basicType, dstSlot);
- return new AdapterMethodHandle(target, newType, conv);
- }
-
- /** Can an adapter spread an argument to convert the target to newType? */
- static boolean canSpreadArguments(MethodType newType, MethodType targetType,
- Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
- if (!convOpSupported(OP_SPREAD_ARGS)) return false;
- if (diffReturnTypes(newType, targetType, false) != 0)
- return false;
- int nptypes = newType.parameterCount();
- // parameter types must be the same up to the spread point
- if (spreadArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, spreadArgPos, false) != 0)
- return false;
- int afterPos = spreadArgPos + spreadArgCount;
- int afterCount = nptypes - (spreadArgPos + 1);
- if (spreadArgPos < 0 || spreadArgPos >= nptypes ||
- spreadArgCount < 0 ||
- targetType.parameterCount() != afterPos + afterCount)
- return false;
- // parameter types after the spread point must also be the same
- if (afterCount != 0 && diffParamTypes(newType, spreadArgPos+1, targetType, afterPos, afterCount, false) != 0)
- return false;
- // match the array element type to the spread arg types
- Class<?> rawSpreadArgType = newType.parameterType(spreadArgPos);
- if (rawSpreadArgType != spreadArgType && !canCheckCast(rawSpreadArgType, spreadArgType))
- return false;
- for (int i = 0; i < spreadArgCount; i++) {
- Class<?> src = VerifyType.spreadArgElementType(spreadArgType, i);
- Class<?> dst = targetType.parameterType(spreadArgPos + i);
- if (src == null || !VerifyType.isNullConversion(src, dst))
- return false;
- }
- return true;
- }
-
-
- /** Factory method: Spread selected argument. */
- static MethodHandle makeSpreadArguments(MethodType newType, MethodHandle target,
- Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
- MethodType targetType = target.type();
- if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
- return null;
- // in arglist: [0: ...keep1 | spos: spreadArg | spos+1: keep2... ]
- // out arglist: [0: ...keep1 | spos: spread... | spos+scount: keep2... ]
- int keep2OutPos = spreadArgPos + spreadArgCount;
- int spreadSlot = targetType.parameterSlotDepth(keep2OutPos);
- int keep1OutSlot = targetType.parameterSlotDepth(spreadArgPos);
- int slotCount = keep1OutSlot - spreadSlot;
- assert(spreadSlot == newType.parameterSlotDepth(spreadArgPos+1));
- assert(slotCount >= spreadArgCount);
- long conv = makeConv(OP_SPREAD_ARGS, spreadArgPos, slotCount-1);
- MethodHandle res = new AdapterMethodHandle(target, newType, conv, spreadArgType);
- assert(res.type().parameterType(spreadArgPos) == spreadArgType);
- return res;
- }
-
- // TO DO: makeCollectArguments, makeFlyby, makeRicochet
-
- @Override
- public String toString() {
- return getNameString(nonAdapter((MethodHandle)vmtarget), this);
- }
-
- private static MethodHandle nonAdapter(MethodHandle mh) {
- while (mh instanceof AdapterMethodHandle) {
- mh = (MethodHandle) mh.vmtarget;
- }
- return mh;
- }
-}
--- a/jdk/src/share/classes/java/dyn/BoundMethodHandle.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.util.VerifyType;
-import sun.dyn.util.Wrapper;
-import static java.dyn.MethodHandleStatics.*;
-
-/**
- * The flavor of method handle which emulates an invoke instruction
- * on a predetermined argument. The JVM dispatches to the correct method
- * when the handle is created, not when it is invoked.
- * @author jrose
- */
-class BoundMethodHandle extends MethodHandle {
- //MethodHandle vmtarget; // next BMH or final DMH or methodOop
- private final Object argument; // argument to insert
- private final int vmargslot; // position at which it is inserted
-
- // Constructors in this class *must* be package scoped or private.
-
- /** Bind a direct MH to its receiver (or first ref. argument).
- * The JVM will pre-dispatch the MH if it is not already static.
- */
- /*non-public*/ BoundMethodHandle(DirectMethodHandle mh, Object argument) {
- super(mh.type().dropParameterTypes(0, 1));
- // check the type now, once for all:
- this.argument = checkReferenceArgument(argument, mh, 0);
- this.vmargslot = this.type().parameterSlotCount();
- initTarget(mh, 0);
- }
-
- /** Insert an argument into an arbitrary method handle.
- * If argnum is zero, inserts the first argument, etc.
- * The argument type must be a reference.
- */
- /*non-public*/ BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
- this(mh.type().dropParameterTypes(argnum, argnum+1),
- mh, argument, argnum);
- }
-
- /** Insert an argument into an arbitrary method handle.
- * If argnum is zero, inserts the first argument, etc.
- */
- /*non-public*/ BoundMethodHandle(MethodType type, MethodHandle mh, Object argument, int argnum) {
- super(type);
- if (mh.type().parameterType(argnum).isPrimitive())
- this.argument = bindPrimitiveArgument(argument, mh, argnum);
- else {
- this.argument = checkReferenceArgument(argument, mh, argnum);
- }
- this.vmargslot = type.parameterSlotDepth(argnum);
- initTarget(mh, argnum);
- }
-
- private void initTarget(MethodHandle mh, int argnum) {
- //this.vmtarget = mh; // maybe updated by JVM
- MethodHandleNatives.init(this, mh, argnum);
- }
-
- /** For the AdapterMethodHandle subclass.
- */
- /*non-public*/ BoundMethodHandle(MethodType type, Object argument, int vmargslot) {
- super(type);
- this.argument = argument;
- this.vmargslot = vmargslot;
- assert(this instanceof AdapterMethodHandle);
- }
-
- /** Initialize the current object as a self-bound method handle, binding it
- * as the first argument of the method handle {@code entryPoint}.
- * The invocation type of the resulting method handle will be the
- * same as {@code entryPoint}, except that the first argument
- * type will be dropped.
- */
- /*non-public*/ BoundMethodHandle(MethodHandle entryPoint) {
- super(entryPoint.type().dropParameterTypes(0, 1));
- this.argument = this; // kludge; get rid of
- this.vmargslot = this.type().parameterSlotDepth(0);
- initTarget(entryPoint, 0);
- }
-
- /** Make sure the given {@code argument} can be used as {@code argnum}-th
- * parameter of the given method handle {@code mh}, which must be a reference.
- * <p>
- * If this fails, throw a suitable {@code WrongMethodTypeException},
- * which will prevent the creation of an illegally typed bound
- * method handle.
- */
- final static Object checkReferenceArgument(Object argument, MethodHandle mh, int argnum) {
- Class<?> ptype = mh.type().parameterType(argnum);
- if (ptype.isPrimitive()) {
- // fail
- } else if (argument == null) {
- return null;
- } else if (VerifyType.isNullReferenceConversion(argument.getClass(), ptype)) {
- return argument;
- }
- throw badBoundArgumentException(argument, mh, argnum);
- }
-
- /** Make sure the given {@code argument} can be used as {@code argnum}-th
- * parameter of the given method handle {@code mh}, which must be a primitive.
- * <p>
- * If this fails, throw a suitable {@code WrongMethodTypeException},
- * which will prevent the creation of an illegally typed bound
- * method handle.
- */
- final static Object bindPrimitiveArgument(Object argument, MethodHandle mh, int argnum) {
- Class<?> ptype = mh.type().parameterType(argnum);
- Wrapper wrap = Wrapper.forPrimitiveType(ptype);
- Object zero = wrap.zero();
- if (zero == null) {
- // fail
- } else if (argument == null) {
- if (ptype != int.class && wrap.isSubwordOrInt())
- return Integer.valueOf(0);
- else
- return zero;
- } else if (VerifyType.isNullReferenceConversion(argument.getClass(), zero.getClass())) {
- if (ptype != int.class && wrap.isSubwordOrInt())
- return Wrapper.INT.wrap(argument);
- else
- return argument;
- }
- throw badBoundArgumentException(argument, mh, argnum);
- }
-
- final static RuntimeException badBoundArgumentException(Object argument, MethodHandle mh, int argnum) {
- String atype = (argument == null) ? "null" : argument.getClass().toString();
- return new WrongMethodTypeException("cannot bind "+atype+" argument to parameter #"+argnum+" of "+mh.type());
- }
-
- @Override
- public String toString() {
- return addTypeString(baseName(), this);
- }
-
- /** Component of toString() before the type string. */
- protected String baseName() {
- MethodHandle mh = this;
- while (mh instanceof BoundMethodHandle) {
- Object info = MethodHandleNatives.getTargetInfo(mh);
- if (info instanceof MethodHandle) {
- mh = (MethodHandle) info;
- } else {
- String name = null;
- if (info instanceof MemberName)
- name = ((MemberName)info).getName();
- if (name != null)
- return name;
- else
- return noParens(super.toString()); // "invoke", probably
- }
- assert(mh != this);
- }
- return noParens(mh.toString());
- }
-
- private static String noParens(String str) {
- int paren = str.indexOf('(');
- if (paren >= 0) str = str.substring(0, paren);
- return str;
- }
-}
--- a/jdk/src/share/classes/java/dyn/CallSite.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,363 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.empty.Empty;
-import sun.misc.Unsafe;
-import static java.dyn.MethodHandleStatics.*;
-import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
-
-/**
- * A {@code CallSite} is a holder for a variable {@link MethodHandle},
- * which is called its {@code target}.
- * An {@code invokedynamic} instruction linked to a {@code CallSite} delegates
- * all calls to the site's current target.
- * A {@code CallSite} may be associated with several {@code invokedynamic}
- * instructions, or it may be "free floating", associated with none.
- * In any case, it may be invoked through an associated method handle
- * called its {@linkplain #dynamicInvoker dynamic invoker}.
- * <p>
- * {@code CallSite} is an abstract class which does not allow
- * direct subclassing by users. It has three immediate,
- * concrete subclasses that may be either instantiated or subclassed.
- * <ul>
- * <li>If a mutable target is not required, an {@code invokedynamic} instruction
- * may be permanently bound by means of a {@linkplain ConstantCallSite constant call site}.
- * <li>If a mutable target is required which has volatile variable semantics,
- * because updates to the target must be immediately and reliably witnessed by other threads,
- * a {@linkplain VolatileCallSite volatile call site} may be used.
- * <li>Otherwise, if a mutable target is required,
- * a {@linkplain MutableCallSite mutable call site} may be used.
- * </ul>
- * <p>
- * A non-constant call site may be <em>relinked</em> by changing its target.
- * The new target must have the same {@linkplain MethodHandle#type() type}
- * as the previous target.
- * Thus, though a call site can be relinked to a series of
- * successive targets, it cannot change its type.
- * <p>
- * Here is a sample use of call sites and bootstrap methods which links every
- * dynamic call site to print its arguments:
-<blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java -->
-static void test() throws Throwable {
- // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION
- InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14);
-}
-private static void printArgs(Object... args) {
- System.out.println(java.util.Arrays.deepToString(args));
-}
-private static final MethodHandle printArgs;
-static {
- MethodHandles.Lookup lookup = MethodHandles.lookup();
- Class thisClass = lookup.lookupClass(); // (who am I?)
- printArgs = lookup.findStatic(thisClass,
- "printArgs", MethodType.methodType(void.class, Object[].class));
-}
-private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) {
- // ignore caller and name, but match the type:
- return new ConstantCallSite(printArgs.asType(type));
-}
-</pre></blockquote>
- * @author John Rose, JSR 292 EG
- */
-abstract
-public class CallSite {
- static { MethodHandleImpl.initStatics(); }
-
- // Fields used only by the JVM. Do not use or change.
- private MemberName vmmethod; // supplied by the JVM (ref. to calling method)
- private int vmindex; // supplied by the JVM (BCI within calling method)
-
- // The actual payload of this call site:
- /*package-private*/
- MethodHandle target;
-
- // Remove this field for PFD and delete deprecated methods:
- private MemberName calleeNameRemoveForPFD;
-
- /**
- * Make a blank call site object with the given method type.
- * An initial target method is supplied which will throw
- * an {@link IllegalStateException} if called.
- * <p>
- * Before this {@code CallSite} object is returned from a bootstrap method,
- * it is usually provided with a more useful target method,
- * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
- * @throws NullPointerException if the proposed type is null
- */
- /*package-private*/
- CallSite(MethodType type) {
- target = type.invokers().uninitializedCallSite();
- }
-
- /**
- * Make a blank call site object, possibly equipped with an initial target method handle.
- * @param target the method handle which will be the initial target of the call site
- * @throws NullPointerException if the proposed target is null
- */
- /*package-private*/
- CallSite(MethodHandle target) {
- target.type(); // null check
- this.target = target;
- }
-
- /**
- * Returns the type of this call site's target.
- * Although targets may change, any call site's type is permanent, and can never change to an unequal type.
- * The {@code setTarget} method enforces this invariant by refusing any new target that does
- * not have the previous target's type.
- * @return the type of the current target, which is also the type of any future target
- */
- public MethodType type() {
- return target.type();
- }
-
- /** Called from JVM (or low-level Java code) after the BSM returns the newly created CallSite.
- * The parameters are JVM-specific.
- */
- void initializeFromJVM(String name,
- MethodType type,
- MemberName callerMethod,
- int callerBCI) {
- if (this.vmmethod != null) {
- // FIXME
- throw new InvokeDynamicBootstrapError("call site has already been linked to an invokedynamic instruction");
- }
- if (!this.type().equals(type)) {
- throw wrongTargetType(target, type);
- }
- this.vmindex = callerBCI;
- this.vmmethod = callerMethod;
- }
-
- /**
- * Returns the target method of the call site, according to the
- * behavior defined by this call site's specific class.
- * The immediate subclasses of {@code CallSite} document the
- * class-specific behaviors of this method.
- *
- * @return the current linkage state of the call site, its target method handle
- * @see ConstantCallSite
- * @see VolatileCallSite
- * @see #setTarget
- * @see ConstantCallSite#getTarget
- * @see MutableCallSite#getTarget
- * @see VolatileCallSite#getTarget
- */
- public abstract MethodHandle getTarget();
-
- /**
- * Updates the target method of this call site, according to the
- * behavior defined by this call site's specific class.
- * The immediate subclasses of {@code CallSite} document the
- * class-specific behaviors of this method.
- * <p>
- * The type of the new target must be {@linkplain MethodType#equals equal to}
- * the type of the old target.
- *
- * @param newTarget the new target
- * @throws NullPointerException if the proposed new target is null
- * @throws WrongMethodTypeException if the proposed new target
- * has a method type that differs from the previous target
- * @see CallSite#getTarget
- * @see ConstantCallSite#setTarget
- * @see MutableCallSite#setTarget
- * @see VolatileCallSite#setTarget
- */
- public abstract void setTarget(MethodHandle newTarget);
-
- void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
- MethodType oldType = oldTarget.type();
- MethodType newType = newTarget.type(); // null check!
- if (!newType.equals(oldType))
- throw wrongTargetType(newTarget, oldType);
- }
-
- private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) {
- return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type);
- }
-
- /**
- * Produce a method handle equivalent to an invokedynamic instruction
- * which has been linked to this call site.
- * <p>
- * This method is equivalent to the following code:
- * <blockquote><pre>
- * MethodHandle getTarget, invoker, result;
- * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
- * invoker = MethodHandles.exactInvoker(this.type());
- * result = MethodHandles.foldArguments(invoker, getTarget)
- * </pre></blockquote>
- *
- * @return a method handle which always invokes this call site's current target
- */
- public abstract MethodHandle dynamicInvoker();
-
- /*non-public*/ MethodHandle makeDynamicInvoker() {
- MethodHandle getTarget = MethodHandleImpl.bindReceiver(GET_TARGET, this);
- MethodHandle invoker = MethodHandles.exactInvoker(this.type());
- return MethodHandles.foldArguments(invoker, getTarget);
- }
-
- private static final MethodHandle GET_TARGET;
- static {
- try {
- GET_TARGET = IMPL_LOOKUP.
- findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
- } catch (ReflectiveOperationException ignore) {
- throw new InternalError();
- }
- }
-
- /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
- /*package-private*/
- static Empty uninitializedCallSite() {
- throw new IllegalStateException("uninitialized call site");
- }
-
- // unsafe stuff:
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static final long TARGET_OFFSET;
-
- static {
- try {
- TARGET_OFFSET = unsafe.objectFieldOffset(CallSite.class.getDeclaredField("target"));
- } catch (Exception ex) { throw new Error(ex); }
- }
-
- /*package-private*/
- void setTargetNormal(MethodHandle newTarget) {
- target = newTarget;
- }
- /*package-private*/
- MethodHandle getTargetVolatile() {
- return (MethodHandle) unsafe.getObjectVolatile(this, TARGET_OFFSET);
- }
- /*package-private*/
- void setTargetVolatile(MethodHandle newTarget) {
- unsafe.putObjectVolatile(this, TARGET_OFFSET, newTarget);
- }
-
- // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
- static CallSite makeSite(MethodHandle bootstrapMethod,
- // Callee information:
- String name, MethodType type,
- // Extra arguments for BSM, if any:
- Object info,
- // Caller information:
- MemberName callerMethod, int callerBCI) {
- Class<?> callerClass = callerMethod.getDeclaringClass();
- Object caller;
- if (bootstrapMethod.type().parameterType(0) == Class.class && TRANSITIONAL_BEFORE_PFD)
- caller = callerClass; // remove for PFD
- else
- caller = IMPL_LOOKUP.in(callerClass);
- if (bootstrapMethod == null && TRANSITIONAL_BEFORE_PFD) {
- // If there is no bootstrap method, throw IncompatibleClassChangeError.
- // This is a valid generic error type for resolution (JLS 12.3.3).
- throw new IncompatibleClassChangeError
- ("Class "+callerClass.getName()+" has not declared a bootstrap method for invokedynamic");
- }
- CallSite site;
- try {
- Object binding;
- info = maybeReBox(info);
- if (info == null) {
- binding = bootstrapMethod.invokeGeneric(caller, name, type);
- } else if (!info.getClass().isArray()) {
- binding = bootstrapMethod.invokeGeneric(caller, name, type, info);
- } else {
- Object[] argv = (Object[]) info;
- maybeReBoxElements(argv);
- if (3 + argv.length > 255)
- throw new InvokeDynamicBootstrapError("too many bootstrap method arguments");
- MethodType bsmType = bootstrapMethod.type();
- if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class)
- binding = bootstrapMethod.invokeGeneric(caller, name, type, argv);
- else
- binding = MethodHandles.spreadInvoker(bsmType, 3)
- .invokeGeneric(bootstrapMethod, caller, name, type, argv);
- }
- //System.out.println("BSM for "+name+type+" => "+binding);
- if (binding instanceof CallSite) {
- site = (CallSite) binding;
- } else if (binding instanceof MethodHandle && TRANSITIONAL_BEFORE_PFD) {
- // Transitional!
- MethodHandle target = (MethodHandle) binding;
- site = new ConstantCallSite(target);
- } else {
- throw new ClassCastException("bootstrap method failed to produce a CallSite");
- }
- if (TRANSITIONAL_BEFORE_PFD)
- PRIVATE_INITIALIZE_CALL_SITE.invokeExact(site, name, type,
- callerMethod, callerBCI);
- assert(site.getTarget() != null);
- assert(site.getTarget().type().equals(type));
- } catch (Throwable ex) {
- InvokeDynamicBootstrapError bex;
- if (ex instanceof InvokeDynamicBootstrapError)
- bex = (InvokeDynamicBootstrapError) ex;
- else
- bex = new InvokeDynamicBootstrapError("call site initialization exception", ex);
- throw bex;
- }
- return site;
- }
-
- private static final boolean TRANSITIONAL_BEFORE_PFD = true; // FIXME: remove for PFD
- // booby trap to force removal after package rename:
- static { if (TRANSITIONAL_BEFORE_PFD) assert(CallSite.class.getName().startsWith("java.dyn.")); }
-
- private static Object maybeReBox(Object x) {
- if (x instanceof Integer) {
- int xi = (int) x;
- if (xi == (byte) xi)
- x = xi; // must rebox; see JLS 5.1.7
- }
- return x;
- }
- private static void maybeReBoxElements(Object[] xa) {
- for (int i = 0; i < xa.length; i++) {
- xa[i] = maybeReBox(xa[i]);
- }
- }
-
- // This method is private in CallSite because it touches private fields in CallSite.
- // These private fields (vmmethod, vmindex) are specific to the JVM.
- private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE;
- static {
- try {
- PRIVATE_INITIALIZE_CALL_SITE =
- !TRANSITIONAL_BEFORE_PFD ? null :
- IMPL_LOOKUP.findVirtual(CallSite.class, "initializeFromJVM",
- MethodType.methodType(void.class,
- String.class, MethodType.class,
- MemberName.class, int.class));
- } catch (ReflectiveOperationException ex) {
- throw uncaughtException(ex);
- }
- }
-}
--- a/jdk/src/share/classes/java/dyn/ClassValue.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.util.WeakHashMap;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * Lazily associate a computed value with (potentially) every type.
- * For example, if a dynamic language needs to construct a message dispatch
- * table for each class encountered at a message send call site,
- * it can use a {@code ClassValue} to cache information needed to
- * perform the message send quickly, for each class encountered.
- * @author John Rose, JSR 292 EG
- */
-public abstract class ClassValue<T> {
- /**
- * Compute the given class's derived value for this {@code ClassValue}.
- * <p>
- * This method will be invoked within the first thread that accesses
- * the value with the {@link #get get} method.
- * <p>
- * Normally, this method is invoked at most once per class,
- * but it may be invoked again if there has been a call to
- * {@link #remove remove}.
- * <p>
- * If this method throws an exception, the corresponding call to {@code get}
- * will terminate abnormally with that exception, and no class value will be recorded.
- *
- * @param type the type whose class value must be computed
- * @return the newly computed value associated with this {@code ClassValue}, for the given class or interface
- * @see #get
- * @see #remove
- */
- protected abstract T computeValue(Class<?> type);
-
- /**
- * Returns the value for the given class.
- * If no value has yet been computed, it is obtained by
- * an invocation of the {@link #computeValue computeValue} method.
- * <p>
- * The actual installation of the value on the class
- * is performed atomically.
- * At that point, if several racing threads have
- * computed values, one is chosen, and returned to
- * all the racing threads.
- * <p>
- * The {@code type} parameter is typically a class, but it may be any type,
- * such as an interface, a primitive type (like {@code int.class}), or {@code void.class}.
- * <p>
- * In the absence of {@code remove} calls, a class value has a simple
- * state diagram: uninitialized and initialized.
- * When {@code remove} calls are made,
- * the rules for value observation are more complex.
- * See the documentation for {@link #remove remove} for more information.
- *
- * @param type the type whose class value must be computed or retrieved
- * @return the current value associated with this {@code ClassValue}, for the given class or interface
- * @throws NullPointerException if the argument is null
- * @see #remove
- * @see #computeValue
- */
- public T get(Class<?> type) {
- ClassValueMap map = getMap(type);
- if (map != null) {
- Object x = map.get(this);
- if (x != null) {
- return (T) map.unmaskNull(x);
- }
- }
- return setComputedValue(type);
- }
-
- /**
- * Removes the associated value for the given class.
- * If this value is subsequently {@linkplain #get read} for the same class,
- * its value will be reinitialized by invoking its {@link #computeValue computeValue} method.
- * This may result in an additional invocation of the
- * {@code computeValue computeValue} method for the given class.
- * <p>
- * In order to explain the interaction between {@code get} and {@code remove} calls,
- * we must model the state transitions of a class value to take into account
- * the alternation between uninitialized and initialized states.
- * To do this, number these states sequentially from zero, and note that
- * uninitialized (or removed) states are numbered with even numbers,
- * while initialized (or re-initialized) states have odd numbers.
- * <p>
- * When a thread {@code T} removes a class value in state {@code 2N},
- * nothing happens, since the class value is already uninitialized.
- * Otherwise, the state is advanced atomically to {@code 2N+1}.
- * <p>
- * When a thread {@code T} queries a class value in state {@code 2N},
- * the thread first attempts to initialize the class value to state {@code 2N+1}
- * by invoking {@code computeValue} and installing the resulting value.
- * <p>
- * When {@code T} attempts to install the newly computed value,
- * if the state is still at {@code 2N}, the class value will be initialized
- * with the computed value, advancing it to state {@code 2N+1}.
- * <p>
- * Otherwise, whether the new state is even or odd,
- * {@code T} will discard the newly computed value
- * and retry the {@code get} operation.
- * <p>
- * Discarding and retrying is an important proviso,
- * since otherwise {@code T} could potentially install
- * a disastrously stale value. For example:
- * <ul>
- * <li>{@code T} calls {@code CV.get(C)} and sees state {@code 2N}
- * <li>{@code T} quickly computes a time-dependent value {@code V0} and gets ready to install it
- * <li>{@code T} is hit by an unlucky paging or scheduling event, and goes to sleep for a long time
- * <li>...meanwhile, {@code T2} also calls {@code CV.get(C)} and sees state {@code 2N}
- * <li>{@code T2} quickly computes a similar time-dependent value {@code V1} and installs it on {@code CV.get(C)}
- * <li>{@code T2} (or a third thread) then calls {@code CV.remove(C)}, undoing {@code T2}'s work
- * <li> the previous actions of {@code T2} are repeated several times
- * <li> also, the relevant computed values change over time: {@code V1}, {@code V2}, ...
- * <li>...meanwhile, {@code T} wakes up and attempts to install {@code V0}; <em>this must fail</em>
- * </ul>
- * We can assume in the above scenario that {@code CV.computeValue} uses locks to properly
- * observe the time-dependent states as it computes {@code V1}, etc.
- * This does not remove the threat of a stale value, since there is a window of time
- * between the return of {@code computeValue} in {@code T} and the installation
- * of the the new value. No user synchronization is possible during this time.
- *
- * @param type the type whose class value must be removed
- * @throws NullPointerException if the argument is null
- */
- public void remove(Class<?> type) {
- ClassValueMap map = getMap(type);
- if (map != null) {
- synchronized (map) {
- map.remove(this);
- }
- }
- }
-
- /// Implementation...
-
- // The hash code for this type is based on the identity of the object,
- // and is well-dispersed for power-of-two tables.
- /** @deprecated This override, which is implementation-specific, will be removed for PFD. */
- public final int hashCode() { return hashCode; }
- private final int hashCode = HASH_CODES.getAndAdd(0x61c88647);
- private static final AtomicInteger HASH_CODES = new AtomicInteger();
-
- private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
-
- /** Slow path for {@link #get}. */
- private T setComputedValue(Class<?> type) {
- ClassValueMap map = getMap(type);
- if (map == null) {
- map = initializeMap(type);
- }
- T value = computeValue(type);
- STORE_BARRIER.lazySet(0);
- // All stores pending from computeValue are completed.
- synchronized (map) {
- // Warm up the table with a null entry.
- map.preInitializeEntry(this);
- }
- STORE_BARRIER.lazySet(0);
- // All stores pending from table expansion are completed.
- synchronized (map) {
- value = (T) map.initializeEntry(this, value);
- // One might fear a possible race condition here
- // if the code for map.put has flushed the write
- // to map.table[*] before the writes to the Map.Entry
- // are done. This is not possible, since we have
- // warmed up the table with an empty entry.
- }
- return value;
- }
-
- // Replace this map by a per-class slot.
- private static final WeakHashMap<Class<?>, ClassValueMap> ROOT
- = new WeakHashMap<Class<?>, ClassValueMap>();
-
- private static ClassValueMap getMap(Class<?> type) {
- return ROOT.get(type);
- }
-
- private static ClassValueMap initializeMap(Class<?> type) {
- synchronized (ClassValue.class) {
- ClassValueMap map = ROOT.get(type);
- if (map == null)
- ROOT.put(type, map = new ClassValueMap());
- return map;
- }
- }
-
- static class ClassValueMap extends WeakHashMap<ClassValue, Object> {
- /** Make sure this table contains an Entry for the given key, even if it is empty. */
- void preInitializeEntry(ClassValue key) {
- if (!this.containsKey(key))
- this.put(key, null);
- }
- /** Make sure this table contains a non-empty Entry for the given key. */
- Object initializeEntry(ClassValue key, Object value) {
- Object prior = this.get(key);
- if (prior != null) {
- return unmaskNull(prior);
- }
- this.put(key, maskNull(value));
- return value;
- }
-
- Object maskNull(Object x) {
- return x == null ? this : x;
- }
- Object unmaskNull(Object x) {
- return x == this ? null : x;
- }
- }
-}
--- a/jdk/src/share/classes/java/dyn/ConstantCallSite.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
- * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
- * bound to the call site's target.
- * @author John Rose, JSR 292 EG
- */
-public class ConstantCallSite extends CallSite {
- /**
- * Creates a call site with a permanent target.
- * @param target the target to be permanently associated with this call site
- * @throws NullPointerException if the proposed target is null
- */
- public ConstantCallSite(MethodHandle target) {
- super(target);
- }
-
- /**
- * Returns the target method of the call site, which behaves
- * like a {@code final} field of the {@code ConstantCallSite}.
- * That is, the the target is always the original value passed
- * to the constructor call which created this instance.
- *
- * @return the immutable linkage state of this call site, a constant method handle
- * @throws UnsupportedOperationException because this kind of call site cannot change its target
- */
- @Override public final MethodHandle getTarget() {
- return target;
- }
-
- /**
- * Always throws an {@link UnsupportedOperationException}.
- * This kind of call site cannot change its target.
- * @param ignore a new target proposed for the call site, which is ignored
- * @throws UnsupportedOperationException because this kind of call site cannot change its target
- */
- @Override public final void setTarget(MethodHandle ignore) {
- throw new UnsupportedOperationException("ConstantCallSite");
- }
-
- /**
- * Returns this call site's permanent target.
- * Since that target will never change, this is a correct implementation
- * of {@link CallSite#dynamicInvoker CallSite.dynamicInvoker}.
- * @return the immutable linkage state of this call site, a constant method handle
- */
- @Override
- public final MethodHandle dynamicInvoker() {
- return getTarget();
- }
-}
--- a/jdk/src/share/classes/java/dyn/DirectMethodHandle.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import static java.dyn.MethodHandleNatives.Constants.*;
-
-/**
- * The flavor of method handle which emulates invokespecial or invokestatic.
- * @author jrose
- */
-class DirectMethodHandle extends MethodHandle {
- //inherited oop vmtarget; // methodOop or virtual class/interface oop
- private final int vmindex; // method index within class or interface
- { vmindex = VM_INDEX_UNINITIALIZED; } // JVM may change this
-
- // Constructors in this class *must* be package scoped or private.
- DirectMethodHandle(MethodType mtype, MemberName m, boolean doDispatch, Class<?> lookupClass) {
- super(mtype);
-
- assert(m.isMethod() || !doDispatch && m.isConstructor());
- if (!m.isResolved())
- throw new InternalError();
-
- MethodHandleNatives.init(this, (Object) m, doDispatch, lookupClass);
- }
-
- boolean isValid() {
- return (vmindex != VM_INDEX_UNINITIALIZED);
- }
-}
--- a/jdk/src/share/classes/java/dyn/FilterGeneric.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4496 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.lang.reflect.*;
-import static java.dyn.MethodHandleStatics.*;
-import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
-
-/**
- * These adapters apply arbitrary conversions to arguments
- * on the way to a ultimate target.
- * For simplicity, these are all generically typed.
- * @author jrose
- */
-class FilterGeneric {
- // type for the incoming call (will be generic)
- private final MethodType entryType;
- // prototype adapters (clone and customize for each new target & conversion!)
- private final Adapter[] adapters;
-
- /** Compute and cache information common to all filtering adapters
- * with the given generic type
- */
- FilterGeneric(MethodType entryType) {
- this.entryType = entryType;
- int tableSize = Kind.LIMIT.invokerIndex(1 + entryType.parameterCount());
- this.adapters = new Adapter[tableSize];
- }
-
- Adapter getAdapter(Kind kind, int pos) {
- int index = kind.invokerIndex(pos);
- Adapter ad = adapters[index];
- if (ad != null) return ad;
- ad = findAdapter(entryType, kind, pos);
- if (ad == null)
- ad = buildAdapterFromBytecodes(entryType, kind, pos);
- adapters[index] = ad;
- return ad;
- }
-
- Adapter makeInstance(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
- Adapter ad = getAdapter(kind, pos);
- return ad.makeInstance(ad.prototypeEntryPoint(), filter, target);
- }
-
- /** Build an adapter of the given generic type, which invokes filter
- * on the selected incoming argument before passing it to the target.
- * @param pos the argument to filter
- * @param filter the function to call on the argument
- * @param target the target to call with the modified argument list
- * @return an adapter method handle
- */
- public static MethodHandle makeArgumentFilter(int pos, MethodHandle filter, MethodHandle target) {
- return make(Kind.value, pos, filter, target);
- }
-
- /** Build an adapter of the given generic type, which invokes a combiner
- * on a selected group of leading arguments.
- * The result of the combiner is prepended before all those arguments.
- * @param combiner the function to call on the selected leading arguments
- * @param target the target to call with the modified argument list
- * @return an adapter method handle
- */
- public static MethodHandle makeArgumentFolder(MethodHandle combiner, MethodHandle target) {
- int num = combiner.type().parameterCount();
- return make(Kind.fold, num, combiner, target);
- }
-
- /** Build an adapter of the given generic type, which invokes a filter
- * on the incoming arguments, reified as a group.
- * The argument may be modified (by side effects in the filter).
- * The arguments, possibly modified, are passed on to the target.
- * @param filter the function to call on the arguments
- * @param target the target to call with the possibly-modified argument list
- * @return an adapter method handle
- */
- public static MethodHandle makeFlyby(MethodHandle filter, MethodHandle target) {
- return make(Kind.flyby, 0, filter, target);
- }
-
- /** Build an adapter of the given generic type, which invokes a collector
- * on the selected incoming argument and all following arguments.
- * The result of the collector replaces all those arguments.
- * @param collector the function to call on the selected trailing arguments
- * @param target the target to call with the modified argument list
- * @return an adapter method handle
- */
- public static MethodHandle makeArgumentCollector(MethodHandle collector, MethodHandle target) {
- int pos = target.type().parameterCount() - 1;
- return make(Kind.collect, pos, collector, target);
- }
-
- static MethodHandle make(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
- FilterGeneric fgen = of(kind, pos, filter.type(), target.type());
- return fgen.makeInstance(kind, pos, filter, target);
- }
-
- /** Return the adapter information for this target and filter type. */
- static FilterGeneric of(Kind kind, int pos, MethodType filterType, MethodType targetType) {
- MethodType entryType = entryType(kind, pos, filterType, targetType);
- if (entryType.generic() != entryType)
- throw newIllegalArgumentException("must be generic: "+entryType);
- MethodTypeForm form = entryType.form();
- FilterGeneric filterGen = form.filterGeneric;
- if (filterGen == null)
- form.filterGeneric = filterGen = new FilterGeneric(entryType);
- return filterGen;
- }
-
- public String toString() {
- return "FilterGeneric/"+entryType;
- }
-
- static MethodType targetType(MethodType entryType, Kind kind, int pos, MethodType filterType) {
- MethodType type = entryType;
- switch (kind) {
- case value:
- case flyby:
- break; // no change
- case fold:
- type = type.insertParameterTypes(0, filterType.returnType());
- break;
- case collect:
- type = type.dropParameterTypes(pos, type.parameterCount());
- type = type.insertParameterTypes(pos, filterType.returnType());
- break;
- default:
- throw new InternalError();
- }
- return type;
- }
-
- static MethodType entryType(Kind kind, int pos, MethodType filterType, MethodType targetType) {
- MethodType type = targetType;
- switch (kind) {
- case value:
- case flyby:
- break; // no change
- case fold:
- type = type.dropParameterTypes(0, 1);
- break;
- case collect:
- type = type.dropParameterTypes(pos, pos+1);
- type = type.insertParameterTypes(pos, filterType.parameterList());
- break;
- default:
- throw new InternalError();
- }
- return type;
- }
-
- /* Create an adapter that handles spreading calls for the given type. */
- static Adapter findAdapter(MethodType entryType, Kind kind, int pos) {
- int argc = entryType.parameterCount();
- String cname0 = "F"+argc;
- String cname1 = "F"+argc+kind.key;
- String[] cnames = { cname0, cname1 };
- String iname = kind.invokerName(pos);
- // e.g., F5; invoke_C3
- for (String cname : cnames) {
- Class<? extends Adapter> acls = Adapter.findSubClass(cname);
- if (acls == null) continue;
- // see if it has the required invoke method
- MethodHandle entryPoint = null;
- try {
- entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
- } catch (ReflectiveOperationException ex) {
- }
- if (entryPoint == null) continue;
- Constructor<? extends Adapter> ctor = null;
- try {
- ctor = acls.getDeclaredConstructor(MethodHandle.class);
- } catch (NoSuchMethodException ex) {
- } catch (SecurityException ex) {
- }
- if (ctor == null) continue;
- try {
- // Produce an instance configured as a prototype.
- return ctor.newInstance(entryPoint);
- } catch (IllegalArgumentException ex) {
- } catch (InvocationTargetException wex) {
- Throwable ex = wex.getTargetException();
- if (ex instanceof Error) throw (Error)ex;
- if (ex instanceof RuntimeException) throw (RuntimeException)ex;
- } catch (InstantiationException ex) {
- } catch (IllegalAccessException ex) {
- }
- }
- return null;
- }
-
- static Adapter buildAdapterFromBytecodes(MethodType entryType, Kind kind, int pos) {
- throw new UnsupportedOperationException("NYI");
- }
-
- /**
- * This adapter takes some untyped arguments, and returns an untyped result.
- * Internally, it applies the invoker to the target, which causes the
- * objects to be unboxed; the result is a raw type in L/I/J/F/D.
- * This result is passed to convert, which is responsible for
- * converting the raw result into a boxed object.
- * The invoker is kept separate from the target because it can be
- * generated once per type erasure family, and reused across adapters.
- */
- static abstract class Adapter extends BoundMethodHandle {
- protected final MethodHandle filter; // transforms one or more arguments
- protected final MethodHandle target; // ultimate target
-
- @Override
- public String toString() {
- return addTypeString(target, this);
- }
-
- protected boolean isPrototype() { return target == null; }
- protected Adapter(MethodHandle entryPoint) {
- this(entryPoint, entryPoint, null);
- assert(isPrototype());
- }
- protected MethodHandle prototypeEntryPoint() {
- if (!isPrototype()) throw new InternalError();
- return filter;
- }
-
- protected Adapter(MethodHandle entryPoint,
- MethodHandle filter, MethodHandle target) {
- super(entryPoint);
- this.filter = filter;
- this.target = target;
- }
-
- /** Make a copy of self, with new fields. */
- protected abstract Adapter makeInstance(MethodHandle entryPoint,
- MethodHandle filter, MethodHandle target);
- // { return new ThisType(entryPoint, filter, target); }
-
- static private final String CLASS_PREFIX; // "java.dyn.FilterGeneric$"
- static {
- String aname = Adapter.class.getName();
- String sname = Adapter.class.getSimpleName();
- if (!aname.endsWith(sname)) throw new InternalError();
- CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
- }
- /** Find a sibing class of Adapter. */
- static Class<? extends Adapter> findSubClass(String name) {
- String cname = Adapter.CLASS_PREFIX + name;
- try {
- return Class.forName(cname).asSubclass(Adapter.class);
- } catch (ClassNotFoundException ex) {
- return null;
- } catch (ClassCastException ex) {
- return null;
- }
- }
- }
-
- static enum Kind {
- value('V'), // filter and replace Nth argument value
- fold('F'), // fold first N arguments, prepend result
- collect('C'), // collect last N arguments, replace with result
- flyby('Y'), // reify entire argument list, filter, pass to target
- LIMIT('?');
- static final int COUNT = LIMIT.ordinal();
-
- final char key;
- Kind(char key) { this.key = key; }
- String invokerName(int pos) { return "invoke_"+key+""+pos; }
- int invokerIndex(int pos) { return pos * COUNT + ordinal(); }
- }
-
- /* generated classes follow this pattern:
- static class F1X extends Adapter {
- protected F1X(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F1X(MethodHandle e, MethodHandle f, MethodHandle t)
- { super(e, f, t); }
- protected F1X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
- { return new F1X(e, f, t); }
- protected Object invoke_V0(Object a0) { return target.invokeExact(filter.invokeExact(a0)); }
- protected Object invoke_F0(Object a0) { return target.invokeExact(filter.invokeExact(), a0); }
- protected Object invoke_F1(Object a0) { return target.invokeExact(filter.invokeExact(a0), a0); }
- protected Object invoke_C0(Object a0) { return target.invokeExact(filter.invokeExact(a0)); }
- protected Object invoke_C1(Object a0) { return target.invokeExact(a0, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0) { Object[] av = { a0 };
- filter.invokeExact(av); return target.invokeExact(av[0]); }
- }
- static class F2X extends Adapter {
- protected F2X(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F2X(MethodHandle e, MethodHandle f, MethodHandle t)
- { super(e, f, t); }
- protected F2X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
- { return new F2X(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0), a1); }
- protected Object invoke_V1(Object a0, Object a1) { return target.invokeExact(a0, filter.invokeExact(a1)); }
- protected Object invoke_F0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(), a0, a1); }
- protected Object invoke_F1(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0), a0, a1); }
- protected Object invoke_F2(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0, a1), a0, a1); }
- protected Object invoke_C0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0, a1)); }
- protected Object invoke_C1(Object a0, Object a1) { return target.invokeExact(a0, filter.invokeExact(a1)); }
- protected Object invoke_C2(Object a0, Object a1) { return target.invokeExact(a0, a1, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1) { Object[] av = { a0, a1 };
- filter.invokeExact(av); return target.invokeExact(av[0], av[1]); }
- }
- // */
-
- // This one is written by hand:
- static class F0 extends Adapter {
- protected F0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F0(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F0 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F0(e, f, t); }
- protected Object invoke_F0() throws Throwable {
- return target.invokeExact(filter.invokeExact()); }
- protected Object invoke_C0() throws Throwable {
- return target.invokeExact(filter.invokeExact()); }
- static final Object[] NO_ARGS = { };
- protected Object invoke_Y0() throws Throwable {
- filter.invokeExact(NO_ARGS); // make the flyby
- return target.invokeExact(); }
- }
-
-/*
- : SHELL; n=FilterGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -ea -cp . genclasses | sed 's| *[/]/ *$||') >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
-//{{{
-import java.util.*;
-class genclasses {
- static String[][] TEMPLATES = { {
- "@for@ N=1..20",
- " //@each-cat@",
- " static class @cat@ extends Adapter {",
- " protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
- " protected @cat@(MethodHandle e, MethodHandle f, MethodHandle t) {",
- " super(e, f, t); }",
- " protected @cat@ makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {",
- " return new @cat@(e, f, t); }",
- " //@each-P@",
- " protected Object invoke_V@P@(@Tvav@) throws Throwable {",
- " return target.invokeExact(@a0_@@Psp@filter.invokeExact(a@P@)@_aN@); }",
- " //@end-P@",
- " //@each-P@",
- " protected Object invoke_F@P@(@Tvav@) throws Throwable {",
- " return target.invokeExact(filter.invokeExact(@a0@),",
- " @av@); }",
- " //@end-P@",
- " protected Object invoke_F@N@(@Tvav@) throws Throwable {",
- " return target.invokeExact(filter.invokeExact(@av@),",
- " @av@); }",
- " //@each-P@",
- " protected Object invoke_C@P@(@Tvav@) throws Throwable {",
- " return target.invokeExact(@a0_@filter.invokeExact(a@P@@_aN@)); }",
- " //@end-P@",
- " protected Object invoke_C@N@(@Tvav@) throws Throwable {",
- " return target.invokeExact(@av@, filter.invokeExact()); }",
- " protected Object invoke_Y0(@Tvav@) throws Throwable {",
- " Object[] av = { @av@ };",
- " filter.invokeExact(av); // make the flyby",
- " return target.invokeExact(@av[i]@); }",
- " }",
- } };
- static final String NEWLINE_INDENT = " //\n ";
- enum VAR {
- cat, N, P, Tvav, av, a0, a0_, _aN, Psp, av_i_;
- public final String pattern = "@"+toString().replace('_','.')+"@";
- public String binding = toString();
- static void makeBindings(boolean topLevel, int inargs, int pos) {
- assert(-1 <= pos && pos < inargs);
- VAR.cat.binding = "F"+inargs;
- VAR.N.binding = String.valueOf(inargs); // incoming arg count
- VAR.P.binding = String.valueOf(pos); // selected arg position
- String[] av = new String[inargs];
- String[] Tvav = new String[inargs];
- String[] av_i_ = new String[inargs];
- for (int i = 0; i < inargs; i++) {
- av[i] = arg(i);
- av_i_[i] = "av["+i+"]";
- String spc = "";
- if (i > 0 && i % 4 == 0) spc = NEWLINE_INDENT+(pos>9?" ":"")+" ";
- Tvav[i] = spc+param("Object", av[i]);
- }
- VAR.av.binding = comma(av);
- VAR.av_i_.binding = comma(av_i_);
- VAR.Tvav.binding = comma(Tvav);
- if (pos >= 0) {
- VAR.Psp.binding = (pos > 0 && pos % 10 == 0) ? NEWLINE_INDENT : "";
- String[] a0 = new String[pos];
- String[] aN = new String[inargs - (pos+1)];
- for (int i = 0; i < pos; i++) {
- String spc = "";
- if (i > 0 && i % 10 == 0) spc = NEWLINE_INDENT;
- a0[i] = spc+av[i];
- }
- VAR.a0.binding = comma(a0);
- VAR.a0_.binding = comma(a0, ", ");
- for (int i = pos+1; i < inargs; i++) {
- String spc = "";
- if (i > 0 && i % 10 == 0) spc = NEWLINE_INDENT;
- aN[i - (pos+1)] = spc+av[i];
- }
- VAR._aN.binding = comma(", ", aN);
- }
- }
- static String arg(int i) { return "a"+i; }
- static String param(String t, String a) { return t+" "+a; }
- static String comma(String[] v) { return comma(v, ""); }
- static String comma(String[] v, String sep) { return comma("", v, sep); }
- static String comma(String sep, String[] v) { return comma(sep, v, ""); }
- static String comma(String sep1, String[] v, String sep2) {
- if (v.length == 0) return "";
- String res = v[0];
- for (int i = 1; i < v.length; i++) res += ", "+v[i];
- return sep1 + res + sep2;
- }
- static String transform(String string) {
- for (VAR var : values())
- string = string.replaceAll(var.pattern, var.binding);
- return string;
- }
- }
- static String[] stringsIn(String[] strings, int beg, int end) {
- return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
- }
- static String[] stringsBefore(String[] strings, int pos) {
- return stringsIn(strings, 0, pos);
- }
- static String[] stringsAfter(String[] strings, int pos) {
- return stringsIn(strings, pos, strings.length);
- }
- static int indexAfter(String[] strings, int pos, String tag) {
- return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
- }
- static int indexBefore(String[] strings, int pos, String tag) {
- for (int i = pos, end = strings.length; ; i++) {
- if (i == end || strings[i].endsWith(tag)) return i;
- }
- }
- static int MIN_ARITY, MAX_ARITY;
- public static void main(String... av) {
- for (String[] template : TEMPLATES) {
- int forLinesLimit = indexBefore(template, 0, "@each-cat@");
- String[] forLines = stringsBefore(template, forLinesLimit);
- template = stringsAfter(template, forLinesLimit);
- for (String forLine : forLines)
- expandTemplate(forLine, template);
- }
- }
- static void expandTemplate(String forLine, String[] template) {
- String[] params = forLine.split("[^0-9]+");
- if (params[0].length() == 0) params = stringsAfter(params, 1);
- System.out.println("//params="+Arrays.asList(params));
- int pcur = 0;
- MIN_ARITY = Integer.valueOf(params[pcur++]);
- MAX_ARITY = Integer.valueOf(params[pcur++]);
- if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
- for (int inargs = MIN_ARITY; inargs <= MAX_ARITY; inargs++) {
- expandTemplate(template, true, inargs, -1);
- }
- }
- static void expandTemplate(String[] template, boolean topLevel, int inargs, int pos) {
- VAR.makeBindings(topLevel, inargs, pos);
- for (int i = 0; i < template.length; i++) {
- String line = template[i];
- if (line.endsWith("@each-cat@")) {
- // ignore
- } else if (line.endsWith("@each-P@")) {
- int blockEnd = indexAfter(template, i, "@end-P@");
- String[] block = stringsIn(template, i+1, blockEnd-1);
- for (int pos1 = Math.max(0,pos); pos1 < inargs; pos1++)
- expandTemplate(block, false, inargs, pos1);
- VAR.makeBindings(topLevel, inargs, pos);
- i = blockEnd-1; continue;
- } else {
- System.out.println(VAR.transform(line));
- }
- }
- }
-}
-//}}} */
-//params=[1, 20]
- static class F1 extends Adapter {
- protected F1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F1(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F1 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F1(e, f, t); }
- protected Object invoke_V0(Object a0) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0)); }
- protected Object invoke_F0(Object a0) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0); }
- protected Object invoke_F1(Object a0) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0); }
- protected Object invoke_C0(Object a0) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0)); }
- protected Object invoke_C1(Object a0) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0) throws Throwable {
- Object[] av = { a0 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0]); }
- }
- static class F2 extends Adapter {
- protected F2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F2(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F2 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F2(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1); }
- protected Object invoke_V1(Object a0, Object a1) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1)); }
- protected Object invoke_F0(Object a0, Object a1) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1); }
- protected Object invoke_F1(Object a0, Object a1) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1); }
- protected Object invoke_F2(Object a0, Object a1) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1); }
- protected Object invoke_C0(Object a0, Object a1) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1)); }
- protected Object invoke_C1(Object a0, Object a1) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1)); }
- protected Object invoke_C2(Object a0, Object a1) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1) throws Throwable {
- Object[] av = { a0, a1 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1]); }
- }
- static class F3 extends Adapter {
- protected F3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F3(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F3 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F3(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2); }
- protected Object invoke_V1(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2); }
- protected Object invoke_V2(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2); }
- protected Object invoke_F1(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2); }
- protected Object invoke_F2(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2); }
- protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2); }
- protected Object invoke_C0(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2) throws Throwable {
- Object[] av = { a0, a1, a2 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2]); }
- }
- static class F4 extends Adapter {
- protected F4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F4(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F4 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F4(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- Object[] av = { a0, a1, a2, a3 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3]); }
- }
- static class F5 extends Adapter {
- protected F5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F5(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F5 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F5(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4]); }
- }
- static class F6 extends Adapter {
- protected F6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F6(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F6 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F6(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5]); }
- }
- static class F7 extends Adapter {
- protected F7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F7(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F7 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F7(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6]); }
- }
- static class F8 extends Adapter {
- protected F8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F8(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F8 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F8(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7]); }
- }
- static class F9 extends Adapter {
- protected F9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F9(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F9 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F9(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8]); }
- }
- static class F10 extends Adapter {
- protected F10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F10(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F10 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F10(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9]); }
- }
- static class F11 extends Adapter {
- protected F11(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F11(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F11 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F11(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
- a10); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
- a10); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
- a10); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
- a10); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
- a10); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
- a10); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
- a10); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
- a10); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
- a10); }
- protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- filter.invokeExact(a10)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
- a10)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
- a10)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
- a10)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
- a10)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
- a10)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
- a10)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
- a10)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
- a10)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10)); }
- protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10]); }
- }
- static class F12 extends Adapter {
- protected F12(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F12(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F12 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F12(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
- a10, a11); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
- a10, a11); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
- a10, a11); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
- a10, a11); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
- a10, a11); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
- a10, a11); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
- a10, a11); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
- a10, a11); }
- protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- filter.invokeExact(a10), a11); }
- protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
- a10, a11)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
- a10, a11)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
- a10, a11)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
- a10, a11)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
- a10, a11)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
- a10, a11)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
- a10, a11)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11)); }
- protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11)); }
- protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11]); }
- }
- static class F13 extends Adapter {
- protected F13(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F13(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F13 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F13(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
- a10, a11, a12); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
- a10, a11, a12); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
- a10, a11, a12); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
- a10, a11, a12); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
- a10, a11, a12); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
- a10, a11, a12); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
- a10, a11, a12); }
- protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- filter.invokeExact(a10), a11, a12); }
- protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11), a12); }
- protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
- a10, a11, a12)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
- a10, a11, a12)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
- a10, a11, a12)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
- a10, a11, a12)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
- a10, a11, a12)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
- a10, a11, a12)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12)); }
- protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11, a12)); }
- protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12)); }
- protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12]); }
- }
- static class F14 extends Adapter {
- protected F14(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F14(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F14 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F14(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
- a10, a11, a12, a13); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
- a10, a11, a12, a13); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
- a10, a11, a12, a13); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
- a10, a11, a12, a13); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
- a10, a11, a12, a13); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
- a10, a11, a12, a13); }
- protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- filter.invokeExact(a10), a11, a12, a13); }
- protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11), a12, a13); }
- protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12), a13); }
- protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
- a10, a11, a12, a13)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
- a10, a11, a12, a13)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
- a10, a11, a12, a13)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
- a10, a11, a12, a13)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
- a10, a11, a12, a13)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13)); }
- protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11, a12, a13)); }
- protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12, a13)); }
- protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13)); }
- protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13]); }
- }
- static class F15 extends Adapter {
- protected F15(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F15(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F15 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F15(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
- a10, a11, a12, a13, a14); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
- a10, a11, a12, a13, a14); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
- a10, a11, a12, a13, a14); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
- a10, a11, a12, a13, a14); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
- a10, a11, a12, a13, a14); }
- protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- filter.invokeExact(a10), a11, a12, a13, a14); }
- protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11), a12, a13, a14); }
- protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12), a13, a14); }
- protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13), a14); }
- protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
- a10, a11, a12, a13, a14)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
- a10, a11, a12, a13, a14)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
- a10, a11, a12, a13, a14)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
- a10, a11, a12, a13, a14)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14)); }
- protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11, a12, a13, a14)); }
- protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12, a13, a14)); }
- protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13, a14)); }
- protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14)); }
- protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14]); }
- }
- static class F16 extends Adapter {
- protected F16(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F16(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F16 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F16(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
- a10, a11, a12, a13, a14, a15); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
- a10, a11, a12, a13, a14, a15); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
- a10, a11, a12, a13, a14, a15); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
- a10, a11, a12, a13, a14, a15); }
- protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- filter.invokeExact(a10), a11, a12, a13, a14, a15); }
- protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11), a12, a13, a14, a15); }
- protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12), a13, a14, a15); }
- protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13), a14, a15); }
- protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14), a15); }
- protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, filter.invokeExact(a15)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
- a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
- a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
- a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14, a15)); }
- protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11, a12, a13, a14, a15)); }
- protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12, a13, a14, a15)); }
- protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13, a14, a15)); }
- protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14, a15)); }
- protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, filter.invokeExact(a15)); }
- protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15]); }
- }
- static class F17 extends Adapter {
- protected F17(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F17(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F17 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F17(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
- a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
- a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
- a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- filter.invokeExact(a10), a11, a12, a13, a14, a15, a16); }
- protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11), a12, a13, a14, a15, a16); }
- protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12), a13, a14, a15, a16); }
- protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13), a14, a15, a16); }
- protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14), a15, a16); }
- protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, filter.invokeExact(a15), a16); }
- protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, filter.invokeExact(a16)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
- a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
- a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11, a12, a13, a14, a15, a16)); }
- protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12, a13, a14, a15, a16)); }
- protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13, a14, a15, a16)); }
- protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14, a15, a16)); }
- protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, filter.invokeExact(a15, a16)); }
- protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, filter.invokeExact(a16)); }
- protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16]); }
- }
- static class F18 extends Adapter {
- protected F18(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F18(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F18 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F18(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
- a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
- a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- filter.invokeExact(a10), a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11), a12, a13, a14, a15, a16, a17); }
- protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12), a13, a14, a15, a16, a17); }
- protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13), a14, a15, a16, a17); }
- protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14), a15, a16, a17); }
- protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, filter.invokeExact(a15), a16, a17); }
- protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, filter.invokeExact(a16), a17); }
- protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
- a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11, a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12, a13, a14, a15, a16, a17)); }
- protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13, a14, a15, a16, a17)); }
- protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14, a15, a16, a17)); }
- protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, filter.invokeExact(a15, a16, a17)); }
- protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, filter.invokeExact(a16, a17)); }
- protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17)); }
- protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17]); }
- }
- static class F19 extends Adapter {
- protected F19(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F19(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F19 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F19(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
- a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- filter.invokeExact(a10), a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11), a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12), a13, a14, a15, a16, a17, a18); }
- protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13), a14, a15, a16, a17, a18); }
- protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14), a15, a16, a17, a18); }
- protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, filter.invokeExact(a15), a16, a17, a18); }
- protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, filter.invokeExact(a16), a17, a18); }
- protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17), a18); }
- protected Object invoke_V18(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(a18)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_F19(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11, a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12, a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13, a14, a15, a16, a17, a18)); }
- protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14, a15, a16, a17, a18)); }
- protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, filter.invokeExact(a15, a16, a17, a18)); }
- protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, filter.invokeExact(a16, a17, a18)); }
- protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17, a18)); }
- protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(a18)); }
- protected Object invoke_C19(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18]); }
- }
- static class F20 extends Adapter {
- protected F20(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected F20(MethodHandle e, MethodHandle f, MethodHandle t) {
- super(e, f, t); }
- protected F20 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
- return new F20(e, f, t); }
- protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- filter.invokeExact(a10), a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11), a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12), a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13), a14, a15, a16, a17, a18, a19); }
- protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14), a15, a16, a17, a18, a19); }
- protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, filter.invokeExact(a15), a16, a17, a18, a19); }
- protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, filter.invokeExact(a16), a17, a18, a19); }
- protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17), a18, a19); }
- protected Object invoke_V18(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(a18), a19); }
- protected Object invoke_V19(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact(a19)); }
- protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F19(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_F20(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19),
- a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
- protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, filter.invokeExact(a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, filter.invokeExact(a12, a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, filter.invokeExact(a13, a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, filter.invokeExact(a14, a15, a16, a17, a18, a19)); }
- protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, filter.invokeExact(a15, a16, a17, a18, a19)); }
- protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, filter.invokeExact(a16, a17, a18, a19)); }
- protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17, a18, a19)); }
- protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(a18, a19)); }
- protected Object invoke_C19(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
- a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact(a19)); }
- protected Object invoke_C20(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, filter.invokeExact()); }
- protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9, Object a10, Object a11,
- Object a12, Object a13, Object a14, Object a15,
- Object a16, Object a17, Object a18, Object a19) throws Throwable {
- Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19 };
- filter.invokeExact(av); // make the flyby
- return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18], av[19]); }
- }
-}
--- a/jdk/src/share/classes/java/dyn/FilterOneArgument.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import static java.dyn.MethodHandleStatics.*;
-import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
-
-/**
- * Unary function composition, useful for many small plumbing jobs.
- * The invoke method takes a single reference argument, and returns a reference
- * Internally, it first calls the {@code filter} method on the argument,
- * Making up the difference between the raw method type and the
- * final method type is the responsibility of a JVM-level adapter.
- * @author jrose
- */
-class FilterOneArgument extends BoundMethodHandle {
- protected final MethodHandle filter; // Object -> Object
- protected final MethodHandle target; // Object -> Object
-
- @Override
- public String toString() {
- return target.toString();
- }
-
- protected Object invoke(Object argument) throws Throwable {
- Object filteredArgument = filter.invokeExact(argument);
- return target.invokeExact(filteredArgument);
- }
-
- private static final MethodHandle INVOKE;
- static {
- try {
- INVOKE =
- IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke",
- MethodType.genericMethodType(1));
- } catch (ReflectiveOperationException ex) {
- throw uncaughtException(ex);
- }
- }
-
- protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
- super(INVOKE);
- this.filter = filter;
- this.target = target;
- }
-
- public static MethodHandle make(MethodHandle filter, MethodHandle target) {
- if (filter == null) return target;
- if (target == null) return filter;
- return new FilterOneArgument(filter, target);
- }
-
-// MethodHandle make(MethodHandle filter1, MethodHandle filter2, MethodHandle target) {
-// MethodHandle filter = make(filter1, filter2);
-// return make(filter, target);
-// }
-}
--- a/jdk/src/share/classes/java/dyn/FromGeneric.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,630 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.Wrapper;
-import java.lang.reflect.*;
-import static java.dyn.MethodHandleStatics.*;
-import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
-
-/**
- * Adapters which mediate between incoming calls which are generic
- * and outgoing calls which are not. Any call can be represented generically
- * boxing up its arguments, and (on return) unboxing the return value.
- * <p>
- * A call is "generic" (in MethodHandle terms) if its MethodType features
- * only Object arguments. A non-generic call therefore features
- * primitives and/or reference types other than Object.
- * An adapter has types for its incoming and outgoing calls.
- * The incoming call type is simply determined by the adapter's type
- * (the MethodType it presents to callers). The outgoing call type
- * is determined by the adapter's target (a MethodHandle that the adapter
- * either binds internally or else takes as a leading argument).
- * (To stretch the term, adapter-like method handles may have multiple
- * targets or be polymorphic across multiple call types.)
- * @author jrose
- */
-class FromGeneric {
- // type for the outgoing call (may have primitives, etc.)
- private final MethodType targetType;
- // type of the outgoing call internal to the adapter
- private final MethodType internalType;
- // prototype adapter (clone and customize for each new target!)
- private final Adapter adapter;
- // entry point for adapter (Adapter mh, a...) => ...
- private final MethodHandle entryPoint;
- // unboxing invoker of type (MH, Object**N) => raw return value
- // it makes up the difference of internalType => targetType
- private final MethodHandle unboxingInvoker;
- // conversion which boxes a the target's raw return value
- private final MethodHandle returnConversion;
-
- /** Compute and cache information common to all unboxing adapters
- * that can call out to targets of the erasure-family of the given erased type.
- */
- private FromGeneric(MethodType targetType) {
- this.targetType = targetType;
- MethodType internalType0;
- // the target invoker will generally need casts on reference arguments
- Adapter ad = findAdapter(internalType0 = targetType.erase());
- if (ad != null) {
- // Immediate hit to exactly the adapter we want,
- // with no monkeying around with primitive types.
- this.internalType = internalType0;
- this.adapter = ad;
- this.entryPoint = ad.prototypeEntryPoint();
- this.returnConversion = computeReturnConversion(targetType, internalType0);
- this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
- return;
- }
-
- // outgoing primitive arguments will be wrapped; unwrap them
- MethodType primsAsObj = targetType.form().primArgsAsBoxes();
- MethodType objArgsRawRet = primsAsObj.form().primsAsInts();
- if (objArgsRawRet != targetType)
- ad = findAdapter(internalType0 = objArgsRawRet);
- if (ad == null) {
- ad = buildAdapterFromBytecodes(internalType0 = targetType);
- }
- this.internalType = internalType0;
- this.adapter = ad;
- MethodType tepType = targetType.insertParameterTypes(0, adapter.getClass());
- this.entryPoint = ad.prototypeEntryPoint();
- this.returnConversion = computeReturnConversion(targetType, internalType0);
- this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
- }
-
- /**
- * The typed target will be called according to targetType.
- * The adapter code will in fact see the raw result from internalType,
- * and must box it into an object. Produce a converter for this.
- */
- private static MethodHandle computeReturnConversion(
- MethodType targetType, MethodType internalType) {
- Class<?> tret = targetType.returnType();
- Class<?> iret = internalType.returnType();
- Wrapper wrap = Wrapper.forBasicType(tret);
- if (!iret.isPrimitive()) {
- assert(iret == Object.class);
- return ValueConversions.identity();
- } else if (wrap.primitiveType() == iret) {
- return ValueConversions.box(wrap, false);
- } else {
- assert(tret == double.class ? iret == long.class : iret == int.class);
- return ValueConversions.boxRaw(wrap, false);
- }
- }
-
- /**
- * The typed target will need an exact invocation point; provide it here.
- * The adapter will possibly need to make a slightly different call,
- * so adapt the invoker. This way, the logic for making up the
- * difference between what the adapter can call and what the target
- * needs can be cached once per type.
- */
- private static MethodHandle computeUnboxingInvoker(
- MethodType targetType, MethodType internalType) {
- // All the adapters we have here have reference-untyped internal calls.
- assert(internalType == internalType.erase());
- MethodHandle invoker = targetType.invokers().exactInvoker();
- // cast all narrow reference types, unbox all primitive arguments:
- MethodType fixArgsType = internalType.changeReturnType(targetType.returnType());
- MethodHandle fixArgs = MethodHandleImpl.convertArguments(
- invoker, Invokers.invokerType(fixArgsType),
- invoker.type(), null);
- if (fixArgs == null)
- throw new InternalError("bad fixArgs");
- // reinterpret the calling sequence as raw:
- MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(
- Invokers.invokerType(internalType), fixArgs);
- if (retyper == null)
- throw new InternalError("bad retyper");
- return retyper;
- }
-
- Adapter makeInstance(MethodHandle typedTarget) {
- MethodType type = typedTarget.type();
- if (type == targetType) {
- return adapter.makeInstance(entryPoint, unboxingInvoker, returnConversion, typedTarget);
- }
- // my erased-type is not exactly the same as the desired type
- assert(type.erase() == targetType); // else we are busted
- MethodHandle invoker = computeUnboxingInvoker(type, internalType);
- return adapter.makeInstance(entryPoint, invoker, returnConversion, typedTarget);
- }
-
- /** Build an adapter of the given generic type, which invokes typedTarget
- * on the incoming arguments, after unboxing as necessary.
- * The return value is boxed if necessary.
- * @param genericType the required type of the result
- * @param typedTarget the target
- * @return an adapter method handle
- */
- public static MethodHandle make(MethodHandle typedTarget) {
- MethodType type = typedTarget.type();
- if (type == type.generic()) return typedTarget;
- return FromGeneric.of(type).makeInstance(typedTarget);
- }
-
- /** Return the adapter information for this type's erasure. */
- static FromGeneric of(MethodType type) {
- MethodTypeForm form = type.form();
- FromGeneric fromGen = form.fromGeneric;
- if (fromGen == null)
- form.fromGeneric = fromGen = new FromGeneric(form.erasedType());
- return fromGen;
- }
-
- public String toString() {
- return "FromGeneric"+targetType;
- }
-
- /* Create an adapter that handles spreading calls for the given type. */
- static Adapter findAdapter(MethodType internalType) {
- MethodType entryType = internalType.generic();
- MethodTypeForm form = internalType.form();
- Class<?> rtype = internalType.returnType();
- int argc = form.parameterCount();
- int lac = form.longPrimitiveParameterCount();
- int iac = form.primitiveParameterCount() - lac;
- String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
- String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
- String cname0 = rawReturn + argc;
- String cname1 = "A" + argc;
- String[] cnames = { cname0+intsAndLongs, cname0, cname1+intsAndLongs, cname1 };
- String iname = "invoke_"+cname0+intsAndLongs;
- // e.g., D5I2, D5, L5I2, L5; invoke_D5
- for (String cname : cnames) {
- Class<? extends Adapter> acls = Adapter.findSubClass(cname);
- if (acls == null) continue;
- // see if it has the required invoke method
- MethodHandle entryPoint = null;
- try {
- entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
- } catch (ReflectiveOperationException ex) {
- }
- if (entryPoint == null) continue;
- Constructor<? extends Adapter> ctor = null;
- try {
- ctor = acls.getDeclaredConstructor(MethodHandle.class);
- } catch (NoSuchMethodException ex) {
- } catch (SecurityException ex) {
- }
- if (ctor == null) continue;
- try {
- // Produce an instance configured as a prototype.
- return ctor.newInstance(entryPoint);
- } catch (IllegalArgumentException ex) {
- } catch (InvocationTargetException wex) {
- Throwable ex = wex.getTargetException();
- if (ex instanceof Error) throw (Error)ex;
- if (ex instanceof RuntimeException) throw (RuntimeException)ex;
- } catch (InstantiationException ex) {
- } catch (IllegalAccessException ex) {
- }
- }
- return null;
- }
-
- static Adapter buildAdapterFromBytecodes(MethodType internalType) {
- throw new UnsupportedOperationException("NYI");
- }
-
- /**
- * This adapter takes some untyped arguments, and returns an untyped result.
- * Internally, it applies the invoker to the target, which causes the
- * objects to be unboxed; the result is a raw type in L/I/J/F/D.
- * This result is passed to convert, which is responsible for
- * converting the raw result into a boxed object.
- * The invoker is kept separate from the target because it can be
- * generated once per type erasure family, and reused across adapters.
- */
- static abstract class Adapter extends BoundMethodHandle {
- /*
- * class X<<R,int N>> extends Adapter {
- * (MH, Object**N)=>raw(R) invoker;
- * (any**N)=>R target;
- * raw(R)=>Object convert;
- * Object invoke(Object**N a) = convert(invoker(target, a...))
- * }
- */
- protected final MethodHandle invoker; // (MH, Object**N) => raw(R)
- protected final MethodHandle convert; // raw(R) => Object
- protected final MethodHandle target; // (any**N) => R
-
- @Override
- public String toString() {
- return addTypeString(target, this);
- }
-
- protected boolean isPrototype() { return target == null; }
- protected Adapter(MethodHandle entryPoint) {
- this(entryPoint, null, entryPoint, null);
- assert(isPrototype());
- }
- protected MethodHandle prototypeEntryPoint() {
- if (!isPrototype()) throw new InternalError();
- return convert;
- }
-
- protected Adapter(MethodHandle entryPoint,
- MethodHandle invoker, MethodHandle convert, MethodHandle target) {
- super(entryPoint);
- this.invoker = invoker;
- this.convert = convert;
- this.target = target;
- }
-
- /** Make a copy of self, with new fields. */
- protected abstract Adapter makeInstance(MethodHandle entryPoint,
- MethodHandle invoker, MethodHandle convert, MethodHandle target);
- // { return new ThisType(entryPoint, convert, target); }
-
- /// Conversions on the value returned from the target.
- protected Object convert_L(Object result) throws Throwable { return convert.invokeExact(result); }
- protected Object convert_I(int result) throws Throwable { return convert.invokeExact(result); }
- protected Object convert_J(long result) throws Throwable { return convert.invokeExact(result); }
- protected Object convert_F(float result) throws Throwable { return convert.invokeExact(result); }
- protected Object convert_D(double result) throws Throwable { return convert.invokeExact(result); }
-
- static private final String CLASS_PREFIX; // "java.dyn.FromGeneric$"
- static {
- String aname = Adapter.class.getName();
- String sname = Adapter.class.getSimpleName();
- if (!aname.endsWith(sname)) throw new InternalError();
- CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
- }
- /** Find a sibing class of Adapter. */
- static Class<? extends Adapter> findSubClass(String name) {
- String cname = Adapter.CLASS_PREFIX + name;
- try {
- return Class.forName(cname).asSubclass(Adapter.class);
- } catch (ClassNotFoundException ex) {
- return null;
- } catch (ClassCastException ex) {
- return null;
- }
- }
- }
-
- /* generated classes follow this pattern:
- static class xA2 extends Adapter {
- protected xA2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected xA2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new xA2(e, i, c, t); }
- protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
- protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1)); }
- protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1)); }
- protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
- protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
- }
- // */
-
-/*
-: SHELL; n=FromGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
-//{{{
-import java.util.*;
-class genclasses {
- static String[] TYPES = { "Object", "int ", "long ", "float ", "double" };
- static String[] WRAPS = { " ", "(Integer)", "(Long) ", "(Float) ", "(Double) " };
- static String[] TCHARS = { "L", "I", "J", "F", "D", "A" };
- static String[][] TEMPLATES = { {
- "@for@ arity=0..10 rcat<=4 nrefs<=99 nints=0 nlongs=0",
- " //@each-cat@",
- " static class @cat@ extends Adapter {",
- " protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
- " protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
- " { super(e, i, c, t); }",
- " protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
- " { return new @cat@(e, i, c, t); }",
- " //@each-R@",
- " protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@((@R@)@W@invoker.invokeExact(target@av@)); }",
- " //@end-R@",
- " }",
- } };
- static final String NEWLINE_INDENT = "\n ";
- enum VAR {
- cat, catN, R, Rc, W, av, Tvav, Ovav;
- public final String pattern = "@"+toString().replace('_','.')+"@";
- public String binding;
- static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
- int nargs = nrefs + nints + nlongs;
- if (topLevel)
- VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
- VAR.catN.binding = catstr(rcat, nrefs, nints, nlongs);
- VAR.R.binding = TYPES[rcat];
- VAR.Rc.binding = TCHARS[rcat];
- VAR.W.binding = WRAPS[rcat];
- String[] Tv = new String[nargs];
- String[] av = new String[nargs];
- String[] Tvav = new String[nargs];
- String[] Ovav = new String[nargs];
- for (int i = 0; i < nargs; i++) {
- int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
- Tv[i] = TYPES[tcat];
- av[i] = arg(i);
- Tvav[i] = param(Tv[i], av[i]);
- Ovav[i] = param("Object", av[i]);
- }
- VAR.av.binding = comma(", ", av);
- VAR.Tvav.binding = comma(Tvav);
- VAR.Ovav.binding = comma(Ovav);
- }
- static String arg(int i) { return "a"+i; }
- static String param(String t, String a) { return t+" "+a; }
- static String comma(String[] v) { return comma("", v); }
- static String comma(String sep, String[] v) {
- if (v.length == 0) return "";
- String res = sep+v[0];
- for (int i = 1; i < v.length; i++) res += ", "+v[i];
- return res;
- }
- static String transform(String string) {
- for (VAR var : values())
- string = string.replaceAll(var.pattern, var.binding);
- return string;
- }
- }
- static String[] stringsIn(String[] strings, int beg, int end) {
- return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
- }
- static String[] stringsBefore(String[] strings, int pos) {
- return stringsIn(strings, 0, pos);
- }
- static String[] stringsAfter(String[] strings, int pos) {
- return stringsIn(strings, pos, strings.length);
- }
- static int indexAfter(String[] strings, int pos, String tag) {
- return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
- }
- static int indexBefore(String[] strings, int pos, String tag) {
- for (int i = pos, end = strings.length; ; i++) {
- if (i == end || strings[i].endsWith(tag)) return i;
- }
- }
- static int MIN_ARITY, MAX_ARITY, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
- static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
- static HashSet<String> done = new HashSet<String>();
- public static void main(String... av) {
- for (String[] template : TEMPLATES) {
- int forLinesLimit = indexBefore(template, 0, "@each-cat@");
- String[] forLines = stringsBefore(template, forLinesLimit);
- template = stringsAfter(template, forLinesLimit);
- for (String forLine : forLines)
- expandTemplate(forLine, template);
- }
- }
- static void expandTemplate(String forLine, String[] template) {
- String[] params = forLine.split("[^0-9]+");
- if (params[0].length() == 0) params = stringsAfter(params, 1);
- System.out.println("//params="+Arrays.asList(params));
- int pcur = 0;
- MIN_ARITY = Integer.valueOf(params[pcur++]);
- MAX_ARITY = Integer.valueOf(params[pcur++]);
- MAX_RCAT = Integer.valueOf(params[pcur++]);
- MAX_REFS = Integer.valueOf(params[pcur++]);
- MAX_INTS = Integer.valueOf(params[pcur++]);
- MAX_LONGS = Integer.valueOf(params[pcur++]);
- if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
- if (MAX_RCAT >= TYPES.length) MAX_RCAT = TYPES.length - 1;
- ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
- ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
- for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
- for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
- expandTemplate(template, true, rcat, nargs, 0, 0);
- if (ALL_ARG_TYPES) break;
- expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
- if (ALL_RETURN_TYPES) break;
- }
- }
- }
- static String catstr(int rcat, int nrefs, int nints, int nlongs) {
- int nargs = nrefs + nints + nlongs;
- String cat = TCHARS[rcat] + nargs;
- if (!ALL_ARG_TYPES) cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
- return cat;
- }
- static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
- for (int isLong = 0; isLong <= 1; isLong++) {
- for (int nprims = 1; nprims <= nargs; nprims++) {
- int nrefs = nargs - nprims;
- int nints = ((1-isLong) * nprims);
- int nlongs = (isLong * nprims);
- expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
- }
- }
- }
- static void expandTemplate(String[] template, boolean topLevel,
- int rcat, int nrefs, int nints, int nlongs) {
- int nargs = nrefs + nints + nlongs;
- if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS) return;
- VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
- if (topLevel && !done.add(VAR.cat.binding)) {
- System.out.println(" //repeat "+VAR.cat.binding);
- return;
- }
- for (int i = 0; i < template.length; i++) {
- String line = template[i];
- if (line.endsWith("@each-cat@")) {
- // ignore
- } else if (line.endsWith("@each-R@")) {
- int blockEnd = indexAfter(template, i, "@end-R@");
- String[] block = stringsIn(template, i+1, blockEnd-1);
- for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
- expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
- VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
- i = blockEnd-1; continue;
- } else if (line.endsWith("@each-Tv@")) {
- int blockEnd = indexAfter(template, i, "@end-Tv@");
- String[] block = stringsIn(template, i+1, blockEnd-1);
- expandTemplate(block, false, rcat, nrefs, nints, nlongs);
- expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
- VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
- i = blockEnd-1; continue;
- } else {
- System.out.println(VAR.transform(line));
- }
- }
- }
-}
-//}}} */
-//params=[0, 10, 4, 99, 0, 0]
- static class A0 extends Adapter {
- protected A0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A0(e, i, c, t); }
- protected Object invoke_L0() throws Throwable { return convert_L((Object)invoker.invokeExact(target)); }
- protected Object invoke_I0() throws Throwable { return convert_I((int) invoker.invokeExact(target)); }
- protected Object invoke_J0() throws Throwable { return convert_J((long) invoker.invokeExact(target)); }
- protected Object invoke_F0() throws Throwable { return convert_F((float) invoker.invokeExact(target)); }
- protected Object invoke_D0() throws Throwable { return convert_D((double)invoker.invokeExact(target)); }
- }
- static class A1 extends Adapter {
- protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A1(e, i, c, t); }
- protected Object invoke_L1(Object a0) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0)); }
- protected Object invoke_I1(Object a0) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0)); }
- protected Object invoke_J1(Object a0) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0)); }
- protected Object invoke_F1(Object a0) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0)); }
- protected Object invoke_D1(Object a0) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0)); }
- }
- static class A2 extends Adapter {
- protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A2(e, i, c, t); }
- protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
- protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1)); }
- protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1)); }
- protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
- protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
- }
- static class A3 extends Adapter {
- protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A3(e, i, c, t); }
- protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2)); }
- protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2)); }
- protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2)); }
- protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2)); }
- protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2)); }
- }
- static class A4 extends Adapter {
- protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A4(e, i, c, t); }
- protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3)); }
- protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3)); }
- protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3)); }
- protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3)); }
- protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3)); }
- }
- static class A5 extends Adapter {
- protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A5(e, i, c, t); }
- protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
- protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
- protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
- protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
- protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
- }
- static class A6 extends Adapter {
- protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A6(e, i, c, t); }
- protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
- }
- static class A7 extends Adapter {
- protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A7(e, i, c, t); }
- protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
- }
- static class A8 extends Adapter {
- protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A8(e, i, c, t); }
- protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
- }
- static class A9 extends Adapter {
- protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A9(e, i, c, t); }
- protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- }
- static class A10 extends Adapter {
- protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { super(e, i, c, t); }
- protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
- { return new A10(e, i, c, t); }
- protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- }
-}
--- a/jdk/src/share/classes/java/dyn/InvokeDynamic.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * This is a place-holder class. Some HotSpot implementations need to see it.
- */
-final class InvokeDynamic {
- private InvokeDynamic() { throw new InternalError(); } // do not instantiate
-}
--- a/jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * Thrown to indicate that an {@code invokedynamic} instruction has
- * failed to find its
- * {@linkplain BootstrapMethod bootstrap method},
- * or the bootstrap method has
- * failed to provide a
- * {@linkplain CallSite call site} with a {@linkplain CallSite#getTarget target}
- * of the correct {@linkplain MethodHandle#type method type}.
- *
- * @author John Rose, JSR 292 EG
- * @since 1.7
- */
-public class InvokeDynamicBootstrapError extends LinkageError {
- private static final long serialVersionUID = 292L;
-
- /**
- * Constructs an {@code InvokeDynamicBootstrapError} with no detail message.
- */
- public InvokeDynamicBootstrapError() {
- super();
- }
-
- /**
- * Constructs an {@code InvokeDynamicBootstrapError} with the specified
- * detail message.
- *
- * @param s the detail message.
- */
- public InvokeDynamicBootstrapError(String s) {
- super(s);
- }
-
- /**
- * Constructs a {@code InvokeDynamicBootstrapError} with the specified
- * detail message and cause.
- *
- * @param s the detail message.
- * @param cause the cause, may be {@code null}.
- */
- public InvokeDynamicBootstrapError(String s, Throwable cause) {
- super(s, cause);
- }
-
- /**
- * Constructs a {@code InvokeDynamicBootstrapError} with the specified
- * cause.
- *
- * @param cause the cause, may be {@code null}.
- */
- public InvokeDynamicBootstrapError(Throwable cause) {
- // cf. Throwable(Throwable cause) constructor.
- super(cause == null ? null : cause.toString());
- initCause(cause);
- }
-}
--- a/jdk/src/share/classes/java/dyn/InvokeGeneric.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.util.*;
-import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
-
-/**
- * Adapters which manage MethodHandle.invokeGeneric calls.
- * The JVM calls one of these when the exact type match fails.
- * @author jrose
- */
-class InvokeGeneric {
- // erased type for the call, which originates from an invokeGeneric site
- private final MethodType erasedCallerType;
- // an invoker of type (MT, MH; A...) -> R
- private final MethodHandle initialInvoker;
-
- /** Compute and cache information for this adapter, so that it can
- * call out to targets of the erasure-family of the given erased type.
- */
- /*non-public*/ InvokeGeneric(MethodType erasedCallerType) throws ReflectiveOperationException {
- assert(erasedCallerType.equals(erasedCallerType.erase()));
- this.erasedCallerType = erasedCallerType;
- this.initialInvoker = makeInitialInvoker();
- assert initialInvoker.type().equals(erasedCallerType
- .insertParameterTypes(0, MethodType.class, MethodHandle.class))
- : initialInvoker.type();
- }
-
- private static MethodHandles.Lookup lookup() {
- return IMPL_LOOKUP;
- }
-
- /** Return the adapter information for this type's erasure. */
- /*non-public*/ static MethodHandle genericInvokerOf(MethodType erasedCallerType) throws ReflectiveOperationException {
- InvokeGeneric gen = new InvokeGeneric(erasedCallerType);
- return gen.initialInvoker;
- }
-
- private MethodHandle makeInitialInvoker() throws ReflectiveOperationException {
- // postDispatch = #(MH'; MT, MH; A...){MH'(MT, MH; A)}
- MethodHandle postDispatch = makePostDispatchInvoker();
- MethodHandle invoker;
- if (returnConversionPossible()) {
- invoker = MethodHandles.foldArguments(postDispatch,
- dispatcher("dispatchWithConversion"));
- } else {
- invoker = MethodHandles.foldArguments(postDispatch, dispatcher("dispatch"));
- }
- return invoker;
- }
-
- private static final Class<?>[] EXTRA_ARGS = { MethodType.class, MethodHandle.class };
- private MethodHandle makePostDispatchInvoker() {
- // Take (MH'; MT, MH; A...) and run MH'(MT, MH; A...).
- MethodType invokerType = erasedCallerType.insertParameterTypes(0, EXTRA_ARGS);
- return invokerType.invokers().exactInvoker();
- }
- private MethodHandle dropDispatchArguments(MethodHandle targetInvoker) {
- assert(targetInvoker.type().parameterType(0) == MethodHandle.class);
- return MethodHandles.dropArguments(targetInvoker, 1, EXTRA_ARGS);
- }
-
- private MethodHandle dispatcher(String dispatchName) throws ReflectiveOperationException {
- return lookup().bind(this, dispatchName,
- MethodType.methodType(MethodHandle.class,
- MethodType.class, MethodHandle.class));
- }
-
- static final boolean USE_AS_TYPE_PATH = true;
-
- /** Return a method handle to invoke on the callerType, target, and remaining arguments.
- * The method handle must finish the call.
- * This is the first look at the caller type and target.
- */
- private MethodHandle dispatch(MethodType callerType, MethodHandle target) {
- MethodType targetType = target.type();
- if (USE_AS_TYPE_PATH || target.isVarargsCollector()) {
- MethodHandle newTarget = target.asType(callerType);
- targetType = callerType;
- Invokers invokers = targetType.invokers();
- MethodHandle invoker = invokers.erasedInvokerWithDrops;
- if (invoker == null) {
- invokers.erasedInvokerWithDrops = invoker =
- dropDispatchArguments(invokers.erasedInvoker());
- }
- return invoker.bindTo(newTarget);
- }
- throw new RuntimeException("NYI");
- }
-
- private MethodHandle dispatchWithConversion(MethodType callerType, MethodHandle target) {
- MethodHandle finisher = dispatch(callerType, target);
- if (returnConversionNeeded(callerType, target))
- finisher = addReturnConversion(finisher, callerType.returnType()); //FIXME: slow
- return finisher;
- }
-
- private boolean returnConversionPossible() {
- Class<?> needType = erasedCallerType.returnType();
- return !needType.isPrimitive();
- }
- private boolean returnConversionNeeded(MethodType callerType, MethodHandle target) {
- Class<?> needType = callerType.returnType();
- if (needType == erasedCallerType.returnType())
- return false; // no conversions possible, since must be primitive or Object
- Class<?> haveType = target.type().returnType();
- if (VerifyType.isNullConversion(haveType, needType))
- return false;
- return true;
- }
- private MethodHandle addReturnConversion(MethodHandle target, Class<?> type) {
- if (true) throw new RuntimeException("NYI");
- // FIXME: This is slow because it creates a closure node on every call that requires a return cast.
- MethodType targetType = target.type();
- MethodHandle caster = ValueConversions.identity(type);
- caster = caster.asType(MethodType.methodType(type, targetType.returnType()));
- // Drop irrelevant arguments, because we only care about the return value:
- caster = MethodHandles.dropArguments(caster, 1, targetType.parameterList());
- MethodHandle result = MethodHandles.foldArguments(caster, target);
- return result.asType(target.type());
- }
-
- public String toString() {
- return "InvokeGeneric"+erasedCallerType;
- }
-}
--- a/jdk/src/share/classes/java/dyn/Invokers.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.empty.Empty;
-import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
-
-/**
- * Construction and caching of often-used invokers.
- * @author jrose
- */
-class Invokers {
- // exact type (sans leading taget MH) for the outgoing call
- private final MethodType targetType;
-
- // exact invoker for the outgoing call
- private /*lazy*/ MethodHandle exactInvoker;
-
- // erased (partially untyped but with primitives) invoker for the outgoing call
- private /*lazy*/ MethodHandle erasedInvoker;
- /*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric
-
- // generic (untyped) invoker for the outgoing call
- private /*lazy*/ MethodHandle genericInvoker;
-
- // generic (untyped) invoker for the outgoing call; accepts a single Object[]
- private final /*lazy*/ MethodHandle[] spreadInvokers;
-
- // invoker for an unbound callsite
- private /*lazy*/ MethodHandle uninitializedCallSite;
-
- /** Compute and cache information common to all collecting adapters
- * that implement members of the erasure-family of the given erased type.
- */
- /*non-public*/ Invokers(MethodType targetType) {
- this.targetType = targetType;
- this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
- }
-
- /*non-public*/ static MethodType invokerType(MethodType targetType) {
- return targetType.insertParameterTypes(0, MethodHandle.class);
- }
-
- /*non-public*/ MethodHandle exactInvoker() {
- MethodHandle invoker = exactInvoker;
- if (invoker != null) return invoker;
- try {
- invoker = IMPL_LOOKUP.findVirtual(MethodHandle.class, "invokeExact", targetType);
- } catch (ReflectiveOperationException ex) {
- throw new InternalError("JVM cannot find invoker for "+targetType);
- }
- assert(invokerType(targetType) == invoker.type());
- exactInvoker = invoker;
- return invoker;
- }
-
- /*non-public*/ MethodHandle genericInvoker() {
- MethodHandle invoker1 = exactInvoker();
- MethodHandle invoker = genericInvoker;
- if (invoker != null) return invoker;
- MethodType genericType = targetType.generic();
- invoker = MethodHandles.convertArguments(invoker1, invokerType(genericType));
- genericInvoker = invoker;
- return invoker;
- }
-
- /*non-public*/ MethodHandle erasedInvoker() {
- MethodHandle invoker1 = exactInvoker();
- MethodHandle invoker = erasedInvoker;
- if (invoker != null) return invoker;
- MethodType erasedType = targetType.erase();
- if (erasedType == targetType.generic())
- invoker = genericInvoker();
- else
- invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType));
- erasedInvoker = invoker;
- return invoker;
- }
-
- /*non-public*/ MethodHandle spreadInvoker(int objectArgCount) {
- MethodHandle vaInvoker = spreadInvokers[objectArgCount];
- if (vaInvoker != null) return vaInvoker;
- MethodHandle gInvoker = genericInvoker();
- vaInvoker = gInvoker.asSpreader(Object[].class, targetType.parameterCount() - objectArgCount);
- spreadInvokers[objectArgCount] = vaInvoker;
- return vaInvoker;
- }
-
- private static MethodHandle THROW_UCS = null;
-
- /*non-public*/ MethodHandle uninitializedCallSite() {
- MethodHandle invoker = uninitializedCallSite;
- if (invoker != null) return invoker;
- if (targetType.parameterCount() > 0) {
- MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
- Invokers invokers0 = type0.invokers();
- invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
- 0, targetType.parameterList());
- assert(invoker.type().equals(targetType));
- uninitializedCallSite = invoker;
- return invoker;
- }
- if (THROW_UCS == null) {
- try {
- THROW_UCS = IMPL_LOOKUP
- .findStatic(CallSite.class, "uninitializedCallSite",
- MethodType.methodType(Empty.class));
- } catch (ReflectiveOperationException ex) {
- throw new RuntimeException(ex);
- }
- }
- invoker = AdapterMethodHandle.makeRetypeRaw(targetType, THROW_UCS);
- assert(invoker.type().equals(targetType));
- uninitializedCallSite = invoker;
- return invoker;
- }
-
- public String toString() {
- return "Invokers"+targetType;
- }
-}
--- a/jdk/src/share/classes/java/dyn/Linkage.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.util.VerifyAccess;
-import java.dyn.MethodHandles.Lookup;
-import sun.reflect.Reflection;
-
-/**
- * <em>CLASS WILL BE REMOVED FOR PFD:</em>
- * Static routines for controlling invokedynamic behavior.
- * Replaced by non-static APIs.
- * @author John Rose, JSR 292 EG
- * @deprecated This class will be removed in the Public Final Draft.
- */
-public class Linkage {
- private Linkage() {} // do not instantiate
-
- /**
- * <em>METHOD WILL BE REMOVED FOR PFD:</em>
- * Register a <em>bootstrap method</em> to use when linking dynamic call sites within
- * a given caller class.
- * @deprecated Use @{@link BootstrapMethod} annotations instead.
- */
- public static
- void registerBootstrapMethod(Class callerClass, MethodHandle bootstrapMethod) {
- Class callc = Reflection.getCallerClass(2);
- if (callc != null && !VerifyAccess.isSamePackage(callerClass, callc))
- throw new IllegalArgumentException("cannot set bootstrap method on "+callerClass);
- MethodHandleImpl.registerBootstrap(callerClass, bootstrapMethod);
- }
-
- /**
- * <em>METHOD WILL BE REMOVED FOR PFD:</em>
- * Simplified version of {@code registerBootstrapMethod} for self-registration,
- * to be called from a static initializer.
- * @deprecated Use @{@link BootstrapMethod} annotations instead.
- */
- public static
- void registerBootstrapMethod(Class<?> runtime, String name) {
- Class callerClass = Reflection.getCallerClass(2);
- registerBootstrapMethodLookup(callerClass, runtime, name);
- }
-
- /**
- * <em>METHOD WILL BE REMOVED FOR PFD:</em>
- * Simplified version of {@code registerBootstrapMethod} for self-registration,
- * @deprecated Use @{@link BootstrapMethod} annotations instead.
- */
- public static
- void registerBootstrapMethod(String name) {
- Class callerClass = Reflection.getCallerClass(2);
- registerBootstrapMethodLookup(callerClass, callerClass, name);
- }
-
- private static
- void registerBootstrapMethodLookup(Class<?> callerClass, Class<?> runtime, String name) {
- Lookup lookup = new Lookup(callerClass);
- MethodHandle bootstrapMethod;
- try {
- bootstrapMethod = lookup.findStatic(runtime, name, BOOTSTRAP_METHOD_TYPE);
- } catch (ReflectiveOperationException ex) {
- throw new IllegalArgumentException("no such bootstrap method in "+runtime+": "+name, ex);
- }
- MethodHandleImpl.registerBootstrap(callerClass, bootstrapMethod);
- }
-
- private static final MethodType BOOTSTRAP_METHOD_TYPE
- = MethodType.methodType(CallSite.class,
- Class.class, String.class, MethodType.class);
-
- /**
- * <em>METHOD WILL BE REMOVED FOR PFD:</em>
- * Invalidate all <code>invokedynamic</code> call sites everywhere.
- * @deprecated Use {@linkplain MutableCallSite#setTarget call site target setting},
- * {@link MutableCallSite#syncAll call site update pushing},
- * and {@link SwitchPoint#guardWithTest target switching} instead.
- */
- public static
- Object invalidateAll() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * <em>METHOD WILL BE REMOVED FOR PFD:</em>
- * Invalidate all {@code invokedynamic} call sites in the bytecodes
- * of any methods of the given class.
- * @deprecated Use {@linkplain MutableCallSite#setTarget call site target setting},
- * {@link MutableCallSite#syncAll call site update pushing},
- * and {@link SwitchPoint#guardWithTest target switching} instead.
- */
- public static
- Object invalidateCallerClass(Class<?> callerClass) {
- throw new UnsupportedOperationException();
- }
-}
--- a/jdk/src/share/classes/java/dyn/MemberName.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,718 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.util.BytecodeDescriptor;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Member;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import static java.dyn.MethodHandleNatives.Constants.*;
-import static java.dyn.MethodHandleStatics.*;
-
-/**
- * A {@code MemberName} is a compact symbolic datum which fully characterizes
- * a method or field reference.
- * A member name refers to a field, method, constructor, or member type.
- * Every member name has a simple name (a string) and a type (either a Class or MethodType).
- * A member name may also have a non-null declaring class, or it may be simply
- * a naked name/type pair.
- * A member name may also have non-zero modifier flags.
- * Finally, a member name may be either resolved or unresolved.
- * If it is resolved, the existence of the named
- * <p>
- * Whether resolved or not, a member name provides no access rights or
- * invocation capability to its possessor. It is merely a compact
- * representation of all symbolic information necessary to link to
- * and properly use the named member.
- * <p>
- * When resolved, a member name's internal implementation may include references to JVM metadata.
- * This representation is stateless and only decriptive.
- * It provides no private information and no capability to use the member.
- * <p>
- * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
- * about the internals of a method (except its bytecodes) and also
- * allows invocation. A MemberName is much lighter than a Method,
- * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
- * and those seven fields omit much of the information in Method.
- * @author jrose
- */
-/*non-public*/ final class MemberName implements Member, Cloneable {
- private Class<?> clazz; // class in which the method is defined
- private String name; // may be null if not yet materialized
- private Object type; // may be null if not yet materialized
- private int flags; // modifier bits; see reflect.Modifier
-
- private Object vmtarget; // VM-specific target value
- private int vmindex; // method index within class or interface
-
- { vmindex = VM_INDEX_UNINITIALIZED; }
-
- /** Return the declaring class of this member.
- * In the case of a bare name and type, the declaring class will be null.
- */
- public Class<?> getDeclaringClass() {
- if (clazz == null && isResolved()) {
- expandFromVM();
- }
- return clazz;
- }
-
- /** Utility method producing the class loader of the declaring class. */
- public ClassLoader getClassLoader() {
- return clazz.getClassLoader();
- }
-
- /** Return the simple name of this member.
- * For a type, it is the same as {@link Class#getSimpleName}.
- * For a method or field, it is the simple name of the member.
- * For a constructor, it is always {@code "<init>"}.
- */
- public String getName() {
- if (name == null) {
- expandFromVM();
- if (name == null) return null;
- }
- return name;
- }
-
- /** Return the declared type of this member, which
- * must be a method or constructor.
- */
- public MethodType getMethodType() {
- if (type == null) {
- expandFromVM();
- if (type == null) return null;
- }
- if (!isInvocable())
- throw newIllegalArgumentException("not invocable, no method type");
- if (type instanceof MethodType) {
- return (MethodType) type;
- }
- if (type instanceof String) {
- String sig = (String) type;
- MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
- this.type = res;
- return res;
- }
- if (type instanceof Object[]) {
- Object[] typeInfo = (Object[]) type;
- Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
- Class<?> rtype = (Class<?>) typeInfo[0];
- MethodType res = MethodType.methodType(rtype, ptypes);
- this.type = res;
- return res;
- }
- throw new InternalError("bad method type "+type);
- }
-
- /** Return the actual type under which this method or constructor must be invoked.
- * For non-static methods or constructors, this is the type with a leading parameter,
- * a reference to declaring class. For static methods, it is the same as the declared type.
- */
- public MethodType getInvocationType() {
- MethodType itype = getMethodType();
- if (!isStatic())
- itype = itype.insertParameterTypes(0, clazz);
- return itype;
- }
-
- /** Utility method producing the parameter types of the method type. */
- public Class<?>[] getParameterTypes() {
- return getMethodType().parameterArray();
- }
-
- /** Utility method producing the return type of the method type. */
- public Class<?> getReturnType() {
- return getMethodType().returnType();
- }
-
- /** Return the declared type of this member, which
- * must be a field or type.
- * If it is a type member, that type itself is returned.
- */
- public Class<?> getFieldType() {
- if (type == null) {
- expandFromVM();
- if (type == null) return null;
- }
- if (isInvocable())
- throw newIllegalArgumentException("not a field or nested class, no simple type");
- if (type instanceof Class<?>) {
- return (Class<?>) type;
- }
- if (type instanceof String) {
- String sig = (String) type;
- MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
- Class<?> res = mtype.returnType();
- this.type = res;
- return res;
- }
- throw new InternalError("bad field type "+type);
- }
-
- /** Utility method to produce either the method type or field type of this member. */
- public Object getType() {
- return (isInvocable() ? getMethodType() : getFieldType());
- }
-
- /** Utility method to produce the signature of this member,
- * used within the class file format to describe its type.
- */
- public String getSignature() {
- if (type == null) {
- expandFromVM();
- if (type == null) return null;
- }
- if (type instanceof String)
- return (String) type;
- if (isInvocable())
- return BytecodeDescriptor.unparse(getMethodType());
- else
- return BytecodeDescriptor.unparse(getFieldType());
- }
-
- /** Return the modifier flags of this member.
- * @see java.lang.reflect.Modifier
- */
- public int getModifiers() {
- return (flags & RECOGNIZED_MODIFIERS);
- }
-
- private void setFlags(int flags) {
- this.flags = flags;
- assert(testAnyFlags(ALL_KINDS));
- }
-
- private boolean testFlags(int mask, int value) {
- return (flags & mask) == value;
- }
- private boolean testAllFlags(int mask) {
- return testFlags(mask, mask);
- }
- private boolean testAnyFlags(int mask) {
- return !testFlags(mask, 0);
- }
-
- /** Utility method to query the modifier flags of this member. */
- public boolean isStatic() {
- return Modifier.isStatic(flags);
- }
- /** Utility method to query the modifier flags of this member. */
- public boolean isPublic() {
- return Modifier.isPublic(flags);
- }
- /** Utility method to query the modifier flags of this member. */
- public boolean isPrivate() {
- return Modifier.isPrivate(flags);
- }
- /** Utility method to query the modifier flags of this member. */
- public boolean isProtected() {
- return Modifier.isProtected(flags);
- }
- /** Utility method to query the modifier flags of this member. */
- public boolean isFinal() {
- return Modifier.isFinal(flags);
- }
- /** Utility method to query the modifier flags of this member. */
- public boolean isAbstract() {
- return Modifier.isAbstract(flags);
- }
- // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
-
- // unofficial modifier flags, used by HotSpot:
- static final int BRIDGE = 0x00000040;
- static final int VARARGS = 0x00000080;
- static final int SYNTHETIC = 0x00001000;
- static final int ANNOTATION= 0x00002000;
- static final int ENUM = 0x00004000;
- /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
- public boolean isBridge() {
- return testAllFlags(IS_METHOD | BRIDGE);
- }
- /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
- public boolean isVarargs() {
- return testAllFlags(VARARGS) && isInvocable();
- }
- /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
- public boolean isSynthetic() {
- return testAllFlags(SYNTHETIC);
- }
-
- static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
-
- // modifiers exported by the JVM:
- static final int RECOGNIZED_MODIFIERS = 0xFFFF;
-
- // private flags, not part of RECOGNIZED_MODIFIERS:
- static final int
- IS_METHOD = MN_IS_METHOD, // method (not constructor)
- IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
- IS_FIELD = MN_IS_FIELD, // field
- IS_TYPE = MN_IS_TYPE; // nested type
- static final int // for MethodHandleNatives.getMembers
- SEARCH_SUPERCLASSES = MN_SEARCH_SUPERCLASSES,
- SEARCH_INTERFACES = MN_SEARCH_INTERFACES;
-
- static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
- static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
- static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
- static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
- static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES;
-
- /** Utility method to query whether this member is a method or constructor. */
- public boolean isInvocable() {
- return testAnyFlags(IS_INVOCABLE);
- }
- /** Utility method to query whether this member is a method, constructor, or field. */
- public boolean isFieldOrMethod() {
- return testAnyFlags(IS_FIELD_OR_METHOD);
- }
- /** Query whether this member is a method. */
- public boolean isMethod() {
- return testAllFlags(IS_METHOD);
- }
- /** Query whether this member is a constructor. */
- public boolean isConstructor() {
- return testAllFlags(IS_CONSTRUCTOR);
- }
- /** Query whether this member is a field. */
- public boolean isField() {
- return testAllFlags(IS_FIELD);
- }
- /** Query whether this member is a type. */
- public boolean isType() {
- return testAllFlags(IS_TYPE);
- }
- /** Utility method to query whether this member is neither public, private, nor protected. */
- public boolean isPackage() {
- return !testAnyFlags(ALL_ACCESS);
- }
-
- /** Initialize a query. It is not resolved. */
- private void init(Class<?> defClass, String name, Object type, int flags) {
- // defining class is allowed to be null (for a naked name/type pair)
- //name.toString(); // null check
- //type.equals(type); // null check
- // fill in fields:
- this.clazz = defClass;
- this.name = name;
- this.type = type;
- setFlags(flags);
- assert(!isResolved());
- }
-
- private void expandFromVM() {
- if (!isResolved()) return;
- if (type instanceof Object[])
- type = null; // don't saddle JVM w/ typeInfo
- MethodHandleNatives.expand(this);
- }
-
- // Capturing information from the Core Reflection API:
- private static int flagsMods(int flags, int mods) {
- assert((flags & RECOGNIZED_MODIFIERS) == 0);
- assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
- return flags | mods;
- }
- /** Create a name for the given reflected method. The resulting name will be in a resolved state. */
- public MemberName(Method m) {
- Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() };
- init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers()));
- // fill in vmtarget, vmindex while we have m in hand:
- MethodHandleNatives.init(this, m);
- assert(isResolved());
- }
- /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */
- public MemberName(Constructor ctor) {
- Object[] typeInfo = { void.class, ctor.getParameterTypes() };
- init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers()));
- // fill in vmtarget, vmindex while we have ctor in hand:
- MethodHandleNatives.init(this, ctor);
- assert(isResolved());
- }
- /** Create a name for the given reflected field. The resulting name will be in a resolved state. */
- public MemberName(Field fld) {
- init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers()));
- // fill in vmtarget, vmindex while we have fld in hand:
- MethodHandleNatives.init(this, fld);
- assert(isResolved());
- }
- /** Create a name for the given class. The resulting name will be in a resolved state. */
- public MemberName(Class<?> type) {
- init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers()));
- vmindex = 0; // isResolved
- assert(isResolved());
- }
-
- // bare-bones constructor; the JVM will fill it in
- MemberName() { }
-
- // locally useful cloner
- @Override protected MemberName clone() {
- try {
- return (MemberName) super.clone();
- } catch (CloneNotSupportedException ex) {
- throw new InternalError();
- }
- }
-
- // %%% define equals/hashcode?
-
- // Construction from symbolic parts, for queries:
- /** Create a field or type name from the given components: Declaring class, name, type, modifiers.
- * The declaring class may be supplied as null if this is to be a bare name and type.
- * The resulting name will in an unresolved state.
- */
- public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) {
- init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS));
- }
- /** Create a field or type name from the given components: Declaring class, name, type.
- * The declaring class may be supplied as null if this is to be a bare name and type.
- * The modifier flags default to zero.
- * The resulting name will in an unresolved state.
- */
- public MemberName(Class<?> defClass, String name, Class<?> type) {
- this(defClass, name, type, 0);
- }
- /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers.
- * It will be a constructor if and only if the name is {@code "<init>"}.
- * The declaring class may be supplied as null if this is to be a bare name and type.
- * The resulting name will in an unresolved state.
- */
- public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) {
- int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
- init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS));
- }
- /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers.
- * It will be a constructor if and only if the name is {@code "<init>"}.
- * The declaring class may be supplied as null if this is to be a bare name and type.
- * The modifier flags default to zero.
- * The resulting name will in an unresolved state.
- */
- public MemberName(Class<?> defClass, String name, MethodType type) {
- this(defClass, name, type, 0);
- }
-
- /** Query whether this member name is resolved.
- * A resolved member name is one for which the JVM has found
- * a method, constructor, field, or type binding corresponding exactly to the name.
- * (Document?)
- */
- public boolean isResolved() {
- return (vmindex != VM_INDEX_UNINITIALIZED);
- }
-
- /** Query whether this member name is resolved to a non-static, non-final method.
- */
- public boolean hasReceiverTypeDispatch() {
- return (isMethod() && getVMIndex() >= 0);
- }
-
- /** Produce a string form of this member name.
- * For types, it is simply the type's own string (as reported by {@code toString}).
- * For fields, it is {@code "DeclaringClass.name/type"}.
- * For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}.
- * If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted.
- * If the member is unresolved, a prefix {@code "*."} is prepended.
- */
- @Override
- public String toString() {
- if (isType())
- return type.toString(); // class java.lang.String
- // else it is a field, method, or constructor
- StringBuilder buf = new StringBuilder();
- if (getDeclaringClass() != null) {
- buf.append(getName(clazz));
- buf.append('.');
- }
- String name = getName();
- buf.append(name == null ? "*" : name);
- Object type = getType();
- if (!isInvocable()) {
- buf.append('/');
- buf.append(type == null ? "*" : getName(type));
- } else {
- buf.append(type == null ? "(*)*" : getName(type));
- }
- /*
- buf.append('/');
- // key: Public, private, pRotected, sTatic, Final, sYnchronized,
- // transient/Varargs, native, (interface), abstract, sTrict, sYnthetic,
- // (annotation), Enum, (unused)
- final String FIELD_MOD_CHARS = "PprTF?vt????Y?E?";
- final String METHOD_MOD_CHARS = "PprTFybVn?atY???";
- String modChars = (isInvocable() ? METHOD_MOD_CHARS : FIELD_MOD_CHARS);
- for (int i = 0; i < modChars.length(); i++) {
- if ((flags & (1 << i)) != 0) {
- char mc = modChars.charAt(i);
- if (mc != '?')
- buf.append(mc);
- }
- }
- */
- return buf.toString();
- }
- private static String getName(Object obj) {
- if (obj instanceof Class<?>)
- return ((Class<?>)obj).getName();
- return String.valueOf(obj);
- }
-
- // Queries to the JVM:
- /** Document? */
- /*non-public*/ int getVMIndex() {
- if (!isResolved())
- throw newIllegalStateException("not resolved", this);
- return vmindex;
- }
-// /*non-public*/ Object getVMTarget() {
-// if (!isResolved())
-// throw newIllegalStateException("not resolved", this);
-// return vmtarget;
-// }
-
- public IllegalAccessException makeAccessException(String message, Object from) {
- message = message + ": "+ toString();
- if (from != null) message += ", from " + from;
- return new IllegalAccessException(message);
- }
- public ReflectiveOperationException makeAccessException(String message) {
- message = message + ": "+ toString();
- if (isResolved())
- return new IllegalAccessException(message);
- else if (isConstructor())
- return new NoSuchMethodException(message);
- else if (isMethod())
- return new NoSuchMethodException(message);
- else
- return new NoSuchFieldException(message);
- }
-
- /** Actually making a query requires an access check. */
- /*non-public*/ static Factory getFactory() {
- return Factory.INSTANCE;
- }
- /** A factory type for resolving member names with the help of the VM.
- * TBD: Define access-safe public constructors for this factory.
- */
- public static class Factory {
- private Factory() { } // singleton pattern
- static Factory INSTANCE = new Factory();
-
- private static int ALLOWED_FLAGS = SEARCH_ALL_SUPERS | ALL_KINDS;
-
- /// Queries
- List<MemberName> getMembers(Class<?> defc,
- String matchName, Object matchType,
- int matchFlags, Class<?> lookupClass) {
- matchFlags &= ALLOWED_FLAGS;
- String matchSig = null;
- if (matchType != null) {
- matchSig = BytecodeDescriptor.unparse(matchType);
- if (matchSig.startsWith("("))
- matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
- else
- matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
- }
- final int BUF_MAX = 0x2000;
- int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
- MemberName[] buf = newMemberBuffer(len1);
- int totalCount = 0;
- ArrayList<MemberName[]> bufs = null;
- int bufCount = 0;
- for (;;) {
- bufCount = MethodHandleNatives.getMembers(defc,
- matchName, matchSig, matchFlags,
- lookupClass,
- totalCount, buf);
- if (bufCount <= buf.length) {
- if (bufCount < 0) bufCount = 0;
- totalCount += bufCount;
- break;
- }
- // JVM returned to us with an intentional overflow!
- totalCount += buf.length;
- int excess = bufCount - buf.length;
- if (bufs == null) bufs = new ArrayList<MemberName[]>(1);
- bufs.add(buf);
- int len2 = buf.length;
- len2 = Math.max(len2, excess);
- len2 = Math.max(len2, totalCount / 4);
- buf = newMemberBuffer(Math.min(BUF_MAX, len2));
- }
- ArrayList<MemberName> result = new ArrayList<MemberName>(totalCount);
- if (bufs != null) {
- for (MemberName[] buf0 : bufs) {
- Collections.addAll(result, buf0);
- }
- }
- result.addAll(Arrays.asList(buf).subList(0, bufCount));
- // Signature matching is not the same as type matching, since
- // one signature might correspond to several types.
- // So if matchType is a Class or MethodType, refilter the results.
- if (matchType != null && matchType != matchSig) {
- for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
- MemberName m = it.next();
- if (!matchType.equals(m.getType()))
- it.remove();
- }
- }
- return result;
- }
- boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
- if (m.name == null || m.type == null) { // find unique non-overloaded name
- Class<?> defc = m.getDeclaringClass();
- List<MemberName> choices = null;
- if (m.isMethod())
- choices = getMethods(defc, searchSupers, m.name, (MethodType) m.type, lookupClass);
- else if (m.isConstructor())
- choices = getConstructors(defc, lookupClass);
- else if (m.isField())
- choices = getFields(defc, searchSupers, m.name, (Class<?>) m.type, lookupClass);
- //System.out.println("resolving "+m+" to "+choices);
- if (choices == null || choices.size() != 1)
- return false;
- if (m.name == null) m.name = choices.get(0).name;
- if (m.type == null) m.type = choices.get(0).type;
- }
- MethodHandleNatives.resolve(m, lookupClass);
- if (m.isResolved()) return true;
- int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
- String matchSig = m.getSignature();
- MemberName[] buf = { m };
- int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
- m.getName(), matchSig, matchFlags, lookupClass, 0, buf);
- if (n != 1) return false;
- return m.isResolved();
- }
- /** Produce a resolved version of the given member.
- * Super types are searched (for inherited members) if {@code searchSupers} is true.
- * Access checking is performed on behalf of the given {@code lookupClass}.
- * If lookup fails or access is not permitted, null is returned.
- * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
- */
- public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> lookupClass) {
- MemberName result = m.clone();
- if (resolveInPlace(result, searchSupers, lookupClass))
- return result;
- return null;
- }
- /** Produce a resolved version of the given member.
- * Super types are searched (for inherited members) if {@code searchSupers} is true.
- * Access checking is performed on behalf of the given {@code lookupClass}.
- * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
- * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
- */
- public
- <NoSuchMemberException extends ReflectiveOperationException>
- MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass,
- Class<NoSuchMemberException> nsmClass)
- throws IllegalAccessException, NoSuchMemberException {
- MemberName result = resolveOrNull(m, searchSupers, lookupClass);
- if (result != null)
- return result;
- ReflectiveOperationException ex = m.makeAccessException("no access");
- if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex;
- throw nsmClass.cast(ex);
- }
- /** Return a list of all methods defined by the given class.
- * Super types are searched (for inherited members) if {@code searchSupers} is true.
- * Access checking is performed on behalf of the given {@code lookupClass}.
- * Inaccessible members are not added to the last.
- */
- public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
- Class<?> lookupClass) {
- return getMethods(defc, searchSupers, null, null, lookupClass);
- }
- /** Return a list of matching methods defined by the given class.
- * Super types are searched (for inherited members) if {@code searchSupers} is true.
- * Returned methods will match the name (if not null) and the type (if not null).
- * Access checking is performed on behalf of the given {@code lookupClass}.
- * Inaccessible members are not added to the last.
- */
- public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
- String name, MethodType type, Class<?> lookupClass) {
- int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
- return getMembers(defc, name, type, matchFlags, lookupClass);
- }
- /** Return a list of all constructors defined by the given class.
- * Access checking is performed on behalf of the given {@code lookupClass}.
- * Inaccessible members are not added to the last.
- */
- public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
- return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
- }
- /** Return a list of all fields defined by the given class.
- * Super types are searched (for inherited members) if {@code searchSupers} is true.
- * Access checking is performed on behalf of the given {@code lookupClass}.
- * Inaccessible members are not added to the last.
- */
- public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
- Class<?> lookupClass) {
- return getFields(defc, searchSupers, null, null, lookupClass);
- }
- /** Return a list of all fields defined by the given class.
- * Super types are searched (for inherited members) if {@code searchSupers} is true.
- * Returned fields will match the name (if not null) and the type (if not null).
- * Access checking is performed on behalf of the given {@code lookupClass}.
- * Inaccessible members are not added to the last.
- */
- public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
- String name, Class<?> type, Class<?> lookupClass) {
- int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
- return getMembers(defc, name, type, matchFlags, lookupClass);
- }
- /** Return a list of all nested types defined by the given class.
- * Super types are searched (for inherited members) if {@code searchSupers} is true.
- * Access checking is performed on behalf of the given {@code lookupClass}.
- * Inaccessible members are not added to the last.
- */
- public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
- Class<?> lookupClass) {
- int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
- return getMembers(defc, null, null, matchFlags, lookupClass);
- }
- private static MemberName[] newMemberBuffer(int length) {
- MemberName[] buf = new MemberName[length];
- // fill the buffer with dummy structs for the JVM to fill in
- for (int i = 0; i < length; i++)
- buf[i] = new MemberName();
- return buf;
- }
- }
-
-// static {
-// System.out.println("Hello world! My methods are:");
-// System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
-// }
-}
--- a/jdk/src/share/classes/java/dyn/MethodHandle.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1006 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-
-import static java.dyn.MethodHandleStatics.*;
-
-/**
- * A method handle is a typed, directly executable reference to an underlying method,
- * constructor, field, or similar low-level operation, with optional
- * transformations of arguments or return values.
- * These transformations are quite general, and include such patterns as
- * {@linkplain #asType conversion},
- * {@linkplain #bindTo insertion},
- * {@linkplain java.dyn.MethodHandles#dropArguments deletion},
- * and {@linkplain java.dyn.MethodHandles#filterArguments substitution}.
- * <p>
- * <em>Note: The super-class of MethodHandle is Object.
- * Any other super-class visible in the Reference Implementation
- * will be removed before the Proposed Final Draft.
- * Also, the final version will not include any public or
- * protected constructors.</em>
- *
- * <h3>Method handle contents</h3>
- * Method handles are dynamically and strongly typed according to type descriptor.
- * They are not distinguished by the name or defining class of their underlying methods.
- * A method handle must be invoked using type descriptor which matches
- * the method handle's own {@linkplain #type method type}.
- * <p>
- * Every method handle reports its type via the {@link #type type} accessor.
- * This type descriptor is a {@link java.dyn.MethodType MethodType} object,
- * whose structure is a series of classes, one of which is
- * the return type of the method (or {@code void.class} if none).
- * <p>
- * A method handle's type controls the types of invocations it accepts,
- * and the kinds of transformations that apply to it.
- * <p>
- * A method handle contains a pair of special invoker methods
- * called {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}.
- * Both invoker methods provide direct access to the method handle's
- * underlying method, constructor, field, or other operation,
- * as modified by transformations of arguments and return values.
- * Both invokers accept calls which exactly match the method handle's own type.
- * The {@code invokeGeneric} invoker also accepts a range of other call types.
- * <p>
- * Method handles are immutable and have no visible state.
- * Of course, they can be bound to underlying methods or data which exhibit state.
- * With respect to the Java Memory Model, any method handle will behave
- * as if all of its (internal) fields are final variables. This means that any method
- * handle made visible to the application will always be fully formed.
- * This is true even if the method handle is published through a shared
- * variable in a data race.
- * <p>
- * Method handles cannot be subclassed by the user.
- * Implementations may (or may not) create internal subclasses of {@code MethodHandle}
- * which may be visible via the {@link java.lang.Object#getClass Object.getClass}
- * operation. The programmer should not draw conclusions about a method handle
- * from its specific class, as the method handle class hierarchy (if any)
- * may change from time to time or across implementations from different vendors.
- *
- * <h3>Method handle compilation</h3>
- * A Java method call expression naming {@code invokeExact} or {@code invokeGeneric}
- * can invoke a method handle from Java source code.
- * From the viewpoint of source code, these methods can take any arguments
- * and their result can be cast to any return type.
- * Formally this is accomplished by giving the invoker methods
- * {@code Object} return types and variable-arity {@code Object} arguments,
- * but they have an additional quality called <em>signature polymorphism</em>
- * which connects this freedom of invocation directly to the JVM execution stack.
- * <p>
- * As is usual with virtual methods, source-level calls to {@code invokeExact}
- * and {@code invokeGeneric} compile to an {@code invokevirtual} instruction.
- * More unusually, the compiler must record the actual argument types,
- * and may not perform method invocation conversions on the arguments.
- * Instead, it must push them on the stack according to their own unconverted types.
- * The method handle object itself is pushed on the stack before the arguments.
- * The compiler then calls the method handle with a type descriptor which
- * describes the argument and return types.
- * <p>
- * To issue a complete type descriptor, the compiler must also determine
- * the return type. This is based on a cast on the method invocation expression,
- * if there is one, or else {@code Object} if the invocation is an expression
- * or else {@code void} if the invocation is a statement.
- * The cast may be to a primitive type (but not {@code void}).
- * <p>
- * As a corner case, an uncasted {@code null} argument is given
- * a type descriptor of {@code java.lang.Void}.
- * The ambiguity with the type {@code Void} is harmless, since there are no references of type
- * {@code Void} except the null reference.
- *
- * <h3>Method handle invocation</h3>
- * The first time a {@code invokevirtual} instruction is executed
- * it is linked, by symbolically resolving the names in the instruction
- * and verifying that the method call is statically legal.
- * This is true of calls to {@code invokeExact} and {@code invokeGeneric}.
- * In this case, the type descriptor emitted by the compiler is checked for
- * correct syntax and names it contains are resolved.
- * Thus, an {@code invokevirtual} instruction which invokes
- * a method handle will always link, as long
- * as the type descriptor is syntactically well-formed
- * and the types exist.
- * <p>
- * When the {@code invokevirtual} is executed after linking,
- * the receiving method handle's type is first checked by the JVM
- * to ensure that it matches the descriptor.
- * If the type match fails, it means that the method which the
- * caller is invoking is not present on the individual
- * method handle being invoked.
- * <p>
- * In the case of {@code invokeExact}, the type descriptor of the invocation
- * (after resolving symbolic type names) must exactly match the method type
- * of the receiving method handle.
- * In the case of {@code invokeGeneric}, the resolved type descriptor
- * must be a valid argument to the receiver's {@link #asType asType} method.
- * Thus, {@code invokeGeneric} is more permissive than {@code invokeExact}.
- * <p>
- * After type matching, a call to {@code invokeExact} directly
- * and immediately invoke the method handle's underlying method
- * (or other behavior, as the case may be).
- * <p>
- * A call to {@code invokeGeneric} works the same as a call to
- * {@code invokeExact}, if the type descriptor specified by the caller
- * exactly matches the method handle's own type.
- * If there is a type mismatch, {@code invokeGeneric} attempts
- * to adjust the type of the receiving method handle,
- * as if by a call to {@link #asType asType},
- * to obtain an exactly invokable method handle {@code M2}.
- * This allows a more powerful negotiation of method type
- * between caller and callee.
- * <p>
- * (Note: The adjusted method handle {@code M2} is not directly observable,
- * and implementations are therefore not required to materialize it.)
- *
- * <h3>Invocation checking</h3>
- * In typical programs, method handle type matching will usually succeed.
- * But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
- * either directly (in the case of {@code invokeExact}) or indirectly as if
- * by a failed call to {@code asType} (in the case of {@code invokeGeneric}).
- * <p>
- * Thus, a method type mismatch which might show up as a linkage error
- * in a statically typed program can show up as
- * a dynamic {@code WrongMethodTypeException}
- * in a program which uses method handles.
- * <p>
- * Because method types contain "live" {@code Class} objects,
- * method type matching takes into account both types names and class loaders.
- * Thus, even if a method handle {@code M} is created in one
- * class loader {@code L1} and used in another {@code L2},
- * method handle calls are type-safe, because the caller's type
- * descriptor, as resolved in {@code L2},
- * is matched against the original callee method's type descriptor,
- * as resolved in {@code L1}.
- * The resolution in {@code L1} happens when {@code M} is created
- * and its type is assigned, while the resolution in {@code L2} happens
- * when the {@code invokevirtual} instruction is linked.
- * <p>
- * Apart from the checking of type descriptors,
- * a method handle's capability to call its underlying method is unrestricted.
- * If a method handle is formed on a non-public method by a class
- * that has access to that method, the resulting handle can be used
- * in any place by any caller who receives a reference to it.
- * <p>
- * Unlike with the Core Reflection API, where access is checked every time
- * a reflective method is invoked,
- * method handle access checking is performed
- * <a href="MethodHandles.Lookup.html#access">when the method handle is created</a>.
- * In the case of {@code ldc} (see below), access checking is performed as part of linking
- * the constant pool entry underlying the constant method handle.
- * <p>
- * Thus, handles to non-public methods, or to methods in non-public classes,
- * should generally be kept secret.
- * They should not be passed to untrusted code unless their use from
- * the untrusted code would be harmless.
- *
- * <h3>Method handle creation</h3>
- * Java code can create a method handle that directly accesses
- * any method, constructor, or field that is accessible to that code.
- * This is done via a reflective, capability-based API called
- * {@link java.dyn.MethodHandles.Lookup MethodHandles.Lookup}
- * For example, a static method handle can be obtained
- * from {@link java.dyn.MethodHandles.Lookup#findStatic Lookup.findStatic}.
- * There are also conversion methods from Core Reflection API objects,
- * such as {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect}.
- * <p>
- * Like classes and strings, method handles that correspond to accessible
- * fields, methods, and constructors can also be represented directly
- * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
- * A new type of constant pool entry, {@code CONSTANT_MethodHandle},
- * refers directly to an associated {@code CONSTANT_Methodref},
- * {@code CONSTANT_InterfaceMethodref}, or {@code CONSTANT_Fieldref}
- * constant pool entry.
- * (For more details on method handle constants,
- * see the <a href="package-summary.html#mhcon">package summary</a>.)
- * <p>
- * Method handles produced by lookups or constant loads from methods or
- * constructors with the variable arity modifier bit ({@code 0x0080})
- * have a corresponding variable arity, as if they were defined with
- * the help of {@link #asVarargsCollector asVarargsCollector}.
- * <p>
- * A method reference may refer either to a static or non-static method.
- * In the non-static case, the method handle type includes an explicit
- * receiver argument, prepended before any other arguments.
- * In the method handle's type, the initial receiver argument is typed
- * according to the class under which the method was initially requested.
- * (E.g., if a non-static method handle is obtained via {@code ldc},
- * the type of the receiver is the class named in the constant pool entry.)
- * <p>
- * When a method handle to a virtual method is invoked, the method is
- * always looked up in the receiver (that is, the first argument).
- * <p>
- * A non-virtual method handle to a specific virtual method implementation
- * can also be created. These do not perform virtual lookup based on
- * receiver type. Such a method handle simulates the effect of
- * an {@code invokespecial} instruction to the same method.
- *
- * <h3>Usage examples</h3>
- * Here are some examples of usage:
- * <p><blockquote><pre>
-Object x, y; String s; int i;
-MethodType mt; MethodHandle mh;
-MethodHandles.Lookup lookup = MethodHandles.lookup();
-// mt is (char,char)String
-mt = MethodType.methodType(String.class, char.class, char.class);
-mh = lookup.findVirtual(String.class, "replace", mt);
-s = (String) mh.invokeExact("daddy",'d','n');
-// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
-assert(s.equals("nanny"));
-// weakly typed invocation (using MHs.invoke)
-s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
-assert(s.equals("savvy"));
-// mt is (Object[])List
-mt = MethodType.methodType(java.util.List.class, Object[].class);
-mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
-assert(mh.isVarargsCollector());
-x = mh.invokeGeneric("one", "two");
-// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
-assert(x.equals(java.util.Arrays.asList("one","two")));
-// mt is (Object,Object,Object)Object
-mt = MethodType.genericMethodType(3);
-mh = mh.asType(mt);
-x = mh.invokeExact((Object)1, (Object)2, (Object)3);
-// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-assert(x.equals(java.util.Arrays.asList(1,2,3)));
-// mt is { => int}
-mt = MethodType.methodType(int.class);
-mh = lookup.findVirtual(java.util.List.class, "size", mt);
-i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
-// invokeExact(Ljava/util/List;)I
-assert(i == 3);
-mt = MethodType.methodType(void.class, String.class);
-mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
-mh.invokeExact(System.out, "Hello, world.");
-// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
- * </pre></blockquote>
- * Each of the above calls to {@code invokeExact} or {@code invokeGeneric}
- * generates a single invokevirtual instruction with
- * the type descriptor indicated in the following comment.
- *
- * <h3>Exceptions</h3>
- * The methods {@code invokeExact} and {@code invokeGeneric} are declared
- * to throw {@link java.lang.Throwable Throwable},
- * which is to say that there is no static restriction on what a method handle
- * can throw. Since the JVM does not distinguish between checked
- * and unchecked exceptions (other than by their class, of course),
- * there is no particular effect on bytecode shape from ascribing
- * checked exceptions to method handle invocations. But in Java source
- * code, methods which perform method handle calls must either explicitly
- * throw {@code java.lang.Throwable Throwable}, or else must catch all
- * throwables locally, rethrowing only those which are legal in the context,
- * and wrapping ones which are illegal.
- *
- * <h3><a name="sigpoly"></a>Signature polymorphism</h3>
- * The unusual compilation and linkage behavior of
- * {@code invokeExact} and {@code invokeGeneric}
- * is referenced by the term <em>signature polymorphism</em>.
- * A signature polymorphic method is one which can operate with
- * any of a wide range of call signatures and return types.
- * In order to make this work, both the Java compiler and the JVM must
- * give special treatment to signature polymorphic methods.
- * <p>
- * In source code, a call to a signature polymorphic method will
- * compile, regardless of the requested type descriptor.
- * As usual, the Java compiler emits an {@code invokevirtual}
- * instruction with the given type descriptor against the named method.
- * The unusual part is that the type descriptor is derived from
- * the actual argument and return types, not from the method declaration.
- * <p>
- * When the JVM processes bytecode containing signature polymorphic calls,
- * it will successfully link any such call, regardless of its type descriptor.
- * (In order to retain type safety, the JVM will guard such calls with suitable
- * dynamic type checks, as described elsewhere.)
- * <p>
- * Bytecode generators, including the compiler back end, are required to emit
- * untransformed type descriptors for these methods.
- * Tools which determine symbolic linkage are required to accept such
- * untransformed descriptors, without reporting linkage errors.
- * <p>
- * For the sake of tools (but not as a programming API), the signature polymorphic
- * methods are marked with a private yet standard annotation,
- * {@code @java.dyn.MethodHandle.PolymorphicSignature}.
- * The annotation's retention is {@code RUNTIME}, so that all tools can see it.
- *
- * <h3>Formal rules for processing signature polymorphic methods</h3>
- * <p>
- * The following methods (and no others) are signature polymorphic:
- * <ul>
- * <li>{@link java.dyn.MethodHandle#invokeExact MethodHandle.invokeExact}
- * <li>{@link java.dyn.MethodHandle#invokeGeneric MethodHandle.invokeGeneric}
- * </ul>
- * <p>
- * A signature polymorphic method will be declared with the following properties:
- * <ul>
- * <li>It must be native.
- * <li>It must take a single varargs parameter of the form {@code Object...}.
- * <li>It must produce a return value of type {@code Object}.
- * <li>It must be contained within the {@code java.dyn} package.
- * </ul>
- * Because of these requirements, a signature polymorphic method is able to accept
- * any number and type of actual arguments, and can, with a cast, produce a value of any type.
- * However, the JVM will treat these declaration features as a documentation convention,
- * rather than a description of the actual structure of the methods as executed.
- * <p>
- * When a call to a signature polymorphic method is compiled, the associated linkage information for
- * its arguments is not array of {@code Object} (as for other similar varargs methods)
- * but rather the erasure of the static types of all the arguments.
- * <p>
- * In an argument position of a method invocation on a signature polymorphic method,
- * a null literal has type {@code java.lang.Void}, unless cast to a reference type.
- * (Note: This typing rule allows the null type to have its own encoding in linkage information
- * distinct from other types.
- * <p>
- * The linkage information for the return type is derived from a context-dependent target typing convention.
- * The return type for a signature polymorphic method invocation is determined as follows:
- * <ul>
- * <li>If the method invocation expression is an expression statement, the method is {@code void}.
- * <li>Otherwise, if the method invocation expression is the immediate operand of a cast,
- * the return type is the erasure of the cast type.
- * <li>Otherwise, the return type is the method's nominal return type, {@code Object}.
- * </ul>
- * (Programmers are encouraged to use explicit casts unless it is clear that a signature polymorphic
- * call will be used as a plain {@code Object} expression.)
- * <p>
- * The linkage information for argument and return types is stored in the descriptor for the
- * compiled (bytecode) call site. As for any invocation instruction, the arguments and return value
- * will be passed directly on the JVM stack, in accordance with the descriptor,
- * and without implicit boxing or unboxing.
- *
- * <h3>Interoperation between method handles and the Core Reflection API</h3>
- * Using factory methods in the {@link java.dyn.MethodHandles.Lookup Lookup} API,
- * any class member represented by a Core Reflection API object
- * can be converted to a behaviorally equivalent method handle.
- * For example, a reflective {@link java.lang.reflect.Method Method} can
- * be converted to a method handle using
- * {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect}.
- * The resulting method handles generally provide more direct and efficient
- * access to the underlying class members.
- * <p>
- * As a special case,
- * when the Core Reflection API is used to view the signature polymorphic
- * methods {@code invokeExact} or {@code invokeGeneric} in this class,
- * they appear as single, non-polymorphic native methods.
- * Calls to these native methods do not result in method handle invocations.
- * Since {@code invokevirtual} instructions can natively
- * invoke method handles under any type descriptor, this reflective view conflicts
- * with the normal presentation via bytecodes.
- * Thus, these two native methods, as viewed by
- * {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod},
- * are placeholders only.
- * If invoked via {@link java.lang.reflect.Method#invoke Method.invoke},
- * they will throw {@code UnsupportedOperationException}.
- * <p>
- * In order to obtain an invoker method for a particular type descriptor,
- * use {@link java.dyn.MethodHandles#exactInvoker MethodHandles.exactInvoker},
- * or {@link java.dyn.MethodHandles#genericInvoker MethodHandles.genericInvoker}.
- * The {@link java.dyn.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
- * API is also able to return a method handle
- * to call {@code invokeExact} or {@code invokeGeneric},
- * for any specified type descriptor .
- *
- * <h3>Interoperation between method handles and Java generics</h3>
- * A method handle can be obtained on a method, constructor, or field
- * which is declared with Java generic types.
- * As with the Core Reflection API, the type of the method handle
- * will constructed from the erasure of the source-level type.
- * When a method handle is invoked, the types of its arguments
- * or the return value cast type may be generic types or type instances.
- * If this occurs, the compiler will replace those
- * types by their erasures when when it constructs the type descriptor
- * for the {@code invokevirtual} instruction.
- * <p>
- * Method handles do not represent
- * their function-like types in terms of Java parameterized (generic) types,
- * because there are three mismatches between function-like types and parameterized
- * Java types.
- * <ul>
- * <li>Method types range over all possible arities,
- * from no arguments to up to 255 of arguments (a limit imposed by the JVM).
- * Generics are not variadic, and so cannot represent this.</li>
- * <li>Method types can specify arguments of primitive types,
- * which Java generic types cannot range over.</li>
- * <li>Higher order functions over method handles (combinators) are
- * often generic across a wide range of function types, including
- * those of multiple arities. It is impossible to represent such
- * genericity with a Java type parameter.</li>
- * </ul>
- *
- * @see MethodType
- * @see MethodHandles
- * @author John Rose, JSR 292 EG
- */
-public abstract class MethodHandle {
- // { JVM internals:
-
- private byte vmentry; // adapter stub or method entry point
- //private int vmslots; // optionally, hoist type.form.vmslots
- /*non-public*/ Object vmtarget; // VM-specific, class-specific target value
-
- // TO DO: vmtarget should be invisible to Java, since the JVM puts internal
- // managed pointers into it. Making it visible exposes it to debuggers,
- // which can cause errors when they treat the pointer as an Object.
-
- // These two dummy fields are present to force 'I' and 'J' signatures
- // into this class's constant pool, so they can be transferred
- // to vmentry when this class is loaded.
- static final int INT_FIELD = 0;
- static final long LONG_FIELD = 0;
-
- // vmentry (a void* field) is used *only* by the JVM.
- // The JVM adjusts its type to int or long depending on system wordsize.
- // Since it is statically typed as neither int nor long, it is impossible
- // to use this field from Java bytecode. (Please don't try to, either.)
-
- // The vmentry is an assembly-language stub which is jumped to
- // immediately after the method type is verified.
- // For a direct MH, this stub loads the vmtarget's entry point
- // and jumps to it.
-
- // } End of JVM internals.
-
- static { MethodHandleImpl.initStatics(); }
-
- // interface MethodHandle<R throws X extends Exception,A...>
- // { MethodType<R throws X,A...> type(); public R invokeExact(A...) throws X; }
-
- /**
- * Internal marker interface which distinguishes (to the Java compiler)
- * those methods which are <a href="MethodHandle.html#sigpoly">signature polymorphic</a>.
- */
- @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
- @interface PolymorphicSignature { }
-
- private MethodType type;
-
- /**
- * Report the type of this method handle.
- * Every invocation of this method handle via {@code invokeExact} must exactly match this type.
- * @return the method handle type
- */
- public MethodType type() {
- return type;
- }
-
- /**
- * Package-private constructor for the method handle implementation hierarchy.
- * Method handle inheritance will be contained completely within
- * the {@code java.dyn} package.
- */
- // @param type type (permanently assigned) of the new method handle
- /*non-public*/ MethodHandle(MethodType type) {
- type.getClass(); // elicit NPE
- this.type = type;
- }
-
- /**
- * Invoke the method handle, allowing any caller type descriptor, but requiring an exact type match.
- * The type descriptor at the call site of {@code invokeExact} must
- * exactly match this method handle's {@link #type type}.
- * No conversions are allowed on arguments or return values.
- * <p>
- * When this method is observed via the Core Reflection API,
- * it will appear as a single native method, taking an object array and returning an object.
- * If this native method is invoked directly via
- * {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
- * or indirectly via {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect},
- * it will throw an {@code UnsupportedOperationException}.
- * @throws WrongMethodTypeException if the target's type is not identical with the caller's type descriptor
- * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
- */
- public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
-
- /**
- * Invoke the method handle, allowing any caller type descriptor,
- * and optionally performing conversions on arguments and return values.
- * <p>
- * If the call site type descriptor exactly matches this method handle's {@link #type type},
- * the call proceeds as if by {@link #invokeExact invokeExact}.
- * <p>
- * Otherwise, the call proceeds as if this method handle were first
- * adjusted by calling {@link #asType asType} to adjust this method handle
- * to the required type, and then the call proceeds as if by
- * {@link #invokeExact invokeExact} on the adjusted method handle.
- * <p>
- * There is no guarantee that the {@code asType} call is actually made.
- * If the JVM can predict the results of making the call, it may perform
- * adaptations directly on the caller's arguments,
- * and call the target method handle according to its own exact type.
- * <p>
- * The type descriptor at the call site of {@code invokeGeneric} must
- * be a valid argument to the receivers {@code asType} method.
- * In particular, the caller must specify the same argument arity
- * as the callee's type,
- * if the callee is not a {@linkplain #asVarargsCollector variable arity collector}.
- * <p>
- * When this method is observed via the Core Reflection API,
- * it will appear as a single native method, taking an object array and returning an object.
- * If this native method is invoked directly via
- * {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
- * or indirectly via {@link java.dyn.MethodHandles.Lookup#unreflect Lookup.unreflect},
- * it will throw an {@code UnsupportedOperationException}.
- * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type descriptor
- * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
- * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
- */
- public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable;
-
- /**
- * Perform a varargs invocation, passing the arguments in the given array
- * to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
- * which mentions only the type {@code Object}, and whose arity is the length
- * of the argument array.
- * <p>
- * Specifically, execution proceeds as if by the following steps,
- * although the methods are not guaranteed to be called if the JVM
- * can predict their effects.
- * <ul>
- * <li>Determine the length of the argument array as {@code N}.
- * For a null reference, {@code N=0}. </li>
- * <li>Determine the generic type {@code TN} of {@code N} arguments as
- * as {@code TN=MethodType.genericMethodType(N)}.</li>
- * <li>Force the original target method handle {@code MH0} to the
- * required type, as {@code MH1 = MH0.asType(TN)}. </li>
- * <li>Spread the array into {@code N} separate arguments {@code A0, ...}. </li>
- * <li>Invoke the type-adjusted method handle on the unpacked arguments:
- * MH1.invokeExact(A0, ...). </li>
- * <li>Take the return value as an {@code Object} reference. </li>
- * </ul>
- * <p>
- * Because of the action of the {@code asType} step, the following argument
- * conversions are applied as necessary:
- * <ul>
- * <li>reference casting
- * <li>unboxing
- * <li>widening primitive conversions
- * </ul>
- * <p>
- * The result returned by the call is boxed if it is a primitive,
- * or forced to null if the return type is void.
- * <p>
- * This call is equivalent to the following code:
- * <p><blockquote><pre>
- * MethodHandle invoker = MethodHandles.spreadInvoker(this.type(), 0);
- * Object result = invoker.invokeExact(this, arguments);
- * </pre></blockquote>
- * <p>
- * Unlike the signature polymorphic methods {@code invokeExact} and {@code invokeGeneric},
- * {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI.
- * It can therefore be used as a bridge between native or reflective code and method handles.
- *
- * @param arguments the arguments to pass to the target
- * @return the result returned by the target
- * @throws ClassCastException if an argument cannot be converted by reference casting
- * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
- * @throws Throwable anything thrown by the target method invocation
- * @see MethodHandles#spreadInvoker
- */
- public Object invokeWithArguments(Object... arguments) throws Throwable {
- int argc = arguments == null ? 0 : arguments.length;
- MethodType type = type();
- if (type.parameterCount() != argc) {
- // simulate invokeGeneric
- return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
- }
- if (argc <= 10) {
- MethodHandle invoker = type.invokers().genericInvoker();
- switch (argc) {
- case 0: return invoker.invokeExact(this);
- case 1: return invoker.invokeExact(this,
- arguments[0]);
- case 2: return invoker.invokeExact(this,
- arguments[0], arguments[1]);
- case 3: return invoker.invokeExact(this,
- arguments[0], arguments[1], arguments[2]);
- case 4: return invoker.invokeExact(this,
- arguments[0], arguments[1], arguments[2],
- arguments[3]);
- case 5: return invoker.invokeExact(this,
- arguments[0], arguments[1], arguments[2],
- arguments[3], arguments[4]);
- case 6: return invoker.invokeExact(this,
- arguments[0], arguments[1], arguments[2],
- arguments[3], arguments[4], arguments[5]);
- case 7: return invoker.invokeExact(this,
- arguments[0], arguments[1], arguments[2],
- arguments[3], arguments[4], arguments[5],
- arguments[6]);
- case 8: return invoker.invokeExact(this,
- arguments[0], arguments[1], arguments[2],
- arguments[3], arguments[4], arguments[5],
- arguments[6], arguments[7]);
- case 9: return invoker.invokeExact(this,
- arguments[0], arguments[1], arguments[2],
- arguments[3], arguments[4], arguments[5],
- arguments[6], arguments[7], arguments[8]);
- case 10: return invoker.invokeExact(this,
- arguments[0], arguments[1], arguments[2],
- arguments[3], arguments[4], arguments[5],
- arguments[6], arguments[7], arguments[8],
- arguments[9]);
- }
- }
-
- // more than ten arguments get boxed in a varargs list:
- MethodHandle invoker = type.invokers().spreadInvoker(0);
- return invoker.invokeExact(this, arguments);
- }
- /** Equivalent to {@code invokeWithArguments(arguments.toArray())}. */
- public Object invokeWithArguments(java.util.List<?> arguments) throws Throwable {
- return invokeWithArguments(arguments.toArray());
- }
-
- /**
- * Produce an adapter method handle which adapts the type of the
- * current method handle to a new type
- * The resulting method handle is guaranteed to report a type
- * which is equal to the desired new type.
- * <p>
- * If the original type and new type are equal, returns {@code this}.
- * <p>
- * This method provides the crucial behavioral difference between
- * {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}. The two methods
- * perform the same steps when the caller's type descriptor is identical
- * with the callee's, but when the types differ, {@link #invokeGeneric invokeGeneric}
- * also calls {@code asType} (or some internal equivalent) in order
- * to match up the caller's and callee's types.
- * <p>
- * This method is equivalent to {@link MethodHandles#convertArguments convertArguments},
- * except for variable arity method handles produced by {@link #asVarargsCollector asVarargsCollector}.
- *
- * @param newType the expected type of the new method handle
- * @return a method handle which delegates to {@code this} after performing
- * any necessary argument conversions, and arranges for any
- * necessary return value conversions
- * @throws WrongMethodTypeException if the conversion cannot be made
- * @see MethodHandles#convertArguments
- */
- public MethodHandle asType(MethodType newType) {
- return MethodHandles.convertArguments(this, newType);
- }
-
- /**
- * Make an adapter which accepts a trailing array argument
- * and spreads its elements as positional arguments.
- * The new method handle adapts, as its <i>target</i>,
- * the current method handle. The type of the adapter will be
- * the same as the type of the target, except that the final
- * {@code arrayLength} parameters of the target's type are replaced
- * by a single array parameter of type {@code arrayType}.
- * <p>
- * If the array element type differs from any of the corresponding
- * argument types on the original target,
- * the original target is adapted to take the array elements directly,
- * as if by a call to {@link #asType asType}.
- * <p>
- * When called, the adapter replaces a trailing array argument
- * by the array's elements, each as its own argument to the target.
- * (The order of the arguments is preserved.)
- * They are converted pairwise by casting and/or unboxing
- * to the types of the trailing parameters of the target.
- * Finally the target is called.
- * What the target eventually returns is returned unchanged by the adapter.
- * <p>
- * Before calling the target, the adapter verifies that the array
- * contains exactly enough elements to provide a correct argument count
- * to the target method handle.
- * (The array may also be null when zero elements are required.)
- * @param arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments
- * @param arrayLength the number of arguments to spread from an incoming array argument
- * @return a new method handle which spreads its final array argument,
- * before calling the original method handle
- * @throws IllegalArgumentException if {@code arrayType} is not an array type
- * @throws IllegalArgumentException if target does not have at least
- * {@code arrayLength} parameter types
- * @throws WrongMethodTypeException if the implied {@code asType} call fails
- * @see #asCollector
- */
- public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
- Class<?> arrayElement = arrayType.getComponentType();
- if (arrayElement == null) throw newIllegalArgumentException("not an array type");
- MethodType oldType = type();
- int nargs = oldType.parameterCount();
- if (nargs < arrayLength) throw newIllegalArgumentException("bad spread array length");
- int keepPosArgs = nargs - arrayLength;
- MethodType newType = oldType.dropParameterTypes(keepPosArgs, nargs);
- newType = newType.insertParameterTypes(keepPosArgs, arrayType);
- return MethodHandles.spreadArguments(this, newType);
- }
-
- /**
- * Make an adapter which accepts a given number of trailing
- * positional arguments and collects them into an array argument.
- * The new method handle adapts, as its <i>target</i>,
- * the current method handle. The type of the adapter will be
- * the same as the type of the target, except that a single trailing
- * parameter (usually of type {@code arrayType}) is replaced by
- * {@code arrayLength} parameters whose type is element type of {@code arrayType}.
- * <p>
- * If the array type differs from the final argument type on the original target,
- * the original target is adapted to take the array type directly,
- * as if by a call to {@link #asType asType}.
- * <p>
- * When called, the adapter replaces its trailing {@code arrayLength}
- * arguments by a single new array of type {@code arrayType}, whose elements
- * comprise (in order) the replaced arguments.
- * Finally the target is called.
- * What the target eventually returns is returned unchanged by the adapter.
- * <p>
- * (The array may also be a shared constant when {@code arrayLength} is zero.)
- * <p>
- * (<em>Note:</em> The {@code arrayType} is often identical to the last
- * parameter type of the original target.
- * It is an explicit argument for symmetry with {@code asSpreader}, and also
- * to allow the target to use a simple {@code Object} as its last parameter type.)
- * <p>
- * In order to create a collecting adapter which is not restricted to a particular
- * number of collected arguments, use {@link #asVarargsCollector asVarargsCollector} instead.
- * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
- * @param arrayLength the number of arguments to collect into a new array argument
- * @return a new method handle which collects some trailing argument
- * into an array, before calling the original method handle
- * @throws IllegalArgumentException if {@code arrayType} is not an array type
- * or {@code arrayType} is not assignable to this method handle's trailing parameter type,
- * or {@code arrayLength} is not a legal array size
- * @throws WrongMethodTypeException if the implied {@code asType} call fails
- * @see #asSpreader
- * @see #asVarargsCollector
- */
- public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
- Class<?> arrayElement = arrayType.getComponentType();
- if (arrayElement == null) throw newIllegalArgumentException("not an array type");
- MethodType oldType = type();
- int nargs = oldType.parameterCount();
- if (nargs == 0) throw newIllegalArgumentException("no trailing argument");
- MethodType newType = oldType.dropParameterTypes(nargs-1, nargs);
- newType = newType.insertParameterTypes(nargs-1,
- java.util.Collections.<Class<?>>nCopies(arrayLength, arrayElement));
- return MethodHandles.collectArguments(this, newType);
- }
-
- /**
- * Make a <em>variable arity</em> adapter which is able to accept
- * any number of trailing positional arguments and collect them
- * into an array argument.
- * <p>
- * The type and behavior of the adapter will be the same as
- * the type and behavior of the target, except that certain
- * {@code invokeGeneric} and {@code asType} requests can lead to
- * trailing positional arguments being collected into target's
- * trailing parameter.
- * Also, the last parameter type of the adapter will be
- * {@code arrayType}, even if the target has a different
- * last parameter type.
- * <p>
- * When called with {@link #invokeExact invokeExact}, the adapter invokes
- * the target with no argument changes.
- * (<em>Note:</em> This behavior is different from a
- * {@linkplain #asCollector fixed arity collector},
- * since it accepts a whole array of indeterminate length,
- * rather than a fixed number of arguments.)
- * <p>
- * When called with {@link #invokeGeneric invokeGeneric}, if the caller
- * type is the same as the adapter, the adapter invokes the target as with
- * {@code invokeExact}.
- * (This is the normal behavior for {@code invokeGeneric} when types match.)
- * <p>
- * Otherwise, if the caller and adapter arity are the same, and the
- * trailing parameter type of the caller is a reference type identical to
- * or assignable to the trailing parameter type of the adapter,
- * the arguments and return values are converted pairwise,
- * as if by {@link MethodHandles#convertArguments convertArguments}.
- * (This is also normal behavior for {@code invokeGeneric} in such a case.)
- * <p>
- * Otherwise, the arities differ, or the adapter's trailing parameter
- * type is not assignable from the corresponding caller type.
- * In this case, the adapter replaces all trailing arguments from
- * the original trailing argument position onward, by
- * a new array of type {@code arrayType}, whose elements
- * comprise (in order) the replaced arguments.
- * <p>
- * The caller type must provides as least enough arguments,
- * and of the correct type, to satisfy the target's requirement for
- * positional arguments before the trailing array argument.
- * Thus, the caller must supply, at a minimum, {@code N-1} arguments,
- * where {@code N} is the arity of the target.
- * Also, there must exist conversions from the incoming arguments
- * to the target's arguments.
- * As with other uses of {@code invokeGeneric}, if these basic
- * requirements are not fulfilled, a {@code WrongMethodTypeException}
- * may be thrown.
- * <p>
- * In all cases, what the target eventually returns is returned unchanged by the adapter.
- * <p>
- * In the final case, it is exactly as if the target method handle were
- * temporarily adapted with a {@linkplain #asCollector fixed arity collector}
- * to the arity required by the caller type.
- * (As with {@code asCollector}, if the array length is zero,
- * a shared constant may be used instead of a new array.
- * If the implied call to {@code asCollector} would throw
- * an {@code IllegalArgumentException} or {@code WrongMethodTypeException},
- * the call to the variable arity adapter must throw
- * {@code WrongMethodTypeException}.)
- * <p>
- * The behavior of {@link #asType asType} is also specialized for
- * variable arity adapters, to maintain the invariant that
- * {@code invokeGeneric} is always equivalent to an {@code asType}
- * call to adjust the target type, followed by {@code invokeExact}.
- * Therefore, a variable arity adapter responds
- * to an {@code asType} request by building a fixed arity collector,
- * if and only if the adapter and requested type differ either
- * in arity or trailing argument type.
- * The resulting fixed arity collector has its type further adjusted
- * (if necessary) to the requested type by pairwise conversion,
- * as if by another application of {@code asType}.
- * <p>
- * When a method handle is obtained by executing an {@code ldc} instruction
- * of a {@code CONSTANT_MethodHandle} constant, and the target method is marked
- * as a variable arity method (with the modifier bit {@code 0x0080}),
- * the method handle will accept multiple arities, as if the method handle
- * constant were created by means of a call to {@code asVarargsCollector}.
- * <p>
- * In order to create a collecting adapter which collects a predetermined
- * number of arguments, and whose type reflects this predetermined number,
- * use {@link #asCollector asCollector} instead.
- * <p>
- * No method handle transformations produce new method handles with
- * variable arity, unless they are documented as doing so.
- * Therefore, besides {@code asVarargsCollector},
- * all methods in {@code MethodHandle} and {@code MethodHandles}
- * will return a method handle with fixed arity,
- * except in the cases where they are specified to return their original
- * operand (e.g., {@code asType} of the method handle's own type).
- * <p>
- * Calling {@code asVarargsCollector} on a method handle which is already
- * of variable arity will produce a method handle with the same type and behavior.
- * It may (or may not) return the original variable arity method handle.
- * <p>
- * Here is an example, of a list-making variable arity method handle:
- * <blockquote><pre>
-MethodHandle asList = publicLookup()
- .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
- .asVarargsCollector(Object[].class);
-assertEquals("[]", asList.invokeGeneric().toString());
-assertEquals("[1]", asList.invokeGeneric(1).toString());
-assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString());
-Object[] argv = { "three", "thee", "tee" };
-assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString());
-List ls = (List) asList.invokeGeneric((Object)argv);
-assertEquals(1, ls.size());
-assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
- * </pre></blockquote>
- * <p style="font-size:smaller;">
- * <em>Discussion:</em>
- * These rules are designed as a dynamically-typed variation
- * of the Java rules for variable arity methods.
- * In both cases, callers to a variable arity method or method handle
- * can either pass zero or more positional arguments, or else pass
- * pre-collected arrays of any length. Users should be aware of the
- * special role of the final argument, and of the effect of a
- * type match on that final argument, which determines whether
- * or not a single trailing argument is interpreted as a whole
- * array or a single element of an array to be collected.
- * Note that the dynamic type of the trailing argument has no
- * effect on this decision, only a comparison between the static
- * type descriptor of the call site and the type of the method handle.)
- * <p style="font-size:smaller;">
- * As a result of the previously stated rules, the variable arity behavior
- * of a method handle may be suppressed, by binding it to the exact invoker
- * of its own type, as follows:
- * <blockquote><pre>
-MethodHandle vamh = publicLookup()
- .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
- .asVarargsCollector(Object[].class);
-MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
-assert(vamh.type().equals(mh.type()));
-assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString());
-boolean failed = false;
-try { mh.invokeGeneric(1,2,3); }
-catch (WrongMethodTypeException ex) { failed = true; }
-assert(failed);
- * </pre></blockquote>
- * This transformation has no behavioral effect if the method handle is
- * not of variable arity.
- *
- * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
- * @return a new method handle which can collect any number of trailing arguments
- * into an array, before calling the original method handle
- * @throws IllegalArgumentException if {@code arrayType} is not an array type
- * or {@code arrayType} is not assignable to this method handle's trailing parameter type
- * @see #asCollector
- * @see #isVarargsCollector
- */
- public MethodHandle asVarargsCollector(Class<?> arrayType) {
- Class<?> arrayElement = arrayType.getComponentType();
- if (arrayElement == null) throw newIllegalArgumentException("not an array type");
- return MethodHandles.asVarargsCollector(this, arrayType);
- }
-
- /**
- * Determine if this method handle
- * supports {@linkplain #asVarargsCollector variable arity} calls.
- * Such method handles arise from the following sources:
- * <ul>
- * <li>a call to {@linkplain #asVarargsCollector asVarargsCollector}
- * <li>a call to a {@linkplain java.dyn.MethodHandles.Lookup lookup method}
- * which resolves to a variable arity Java method or constructor
- * <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
- * which resolves to a variable arity Java method or constructor
- * </ul>
- * @return true if this method handle accepts more than one arity of {@code invokeGeneric} calls
- * @see #asVarargsCollector
- */
- public boolean isVarargsCollector() {
- return false;
- }
-
- /**
- * Bind a value {@code x} to the first argument of a method handle, without invoking it.
- * The new method handle adapts, as its <i>target</i>,
- * to the current method handle.
- * The type of the bound handle will be
- * the same as the type of the target, except that a single leading
- * reference parameter will be omitted.
- * <p>
- * When called, the bound handle inserts the given value {@code x}
- * as a new leading argument to the target. The other arguments are
- * also passed unchanged.
- * What the target eventually returns is returned unchanged by the bound handle.
- * <p>
- * The reference {@code x} must be convertible to the first parameter
- * type of the target.
- * @param x the value to bind to the first argument of the target
- * @return a new method handle which collects some trailing argument
- * into an array, before calling the original method handle
- * @throws IllegalArgumentException if the target does not have a
- * leading parameter type that is a reference type
- * @throws ClassCastException if {@code x} cannot be converted
- * to the leading parameter type of the target
- * @see MethodHandles#insertArguments
- */
- public MethodHandle bindTo(Object x) {
- return MethodHandles.insertArguments(this, 0, x);
- }
-
- /**
- * Returns a string representation of the method handle,
- * starting with the string {@code "MethodHandle"} and
- * ending with the string representation of the method handle's type.
- * In other words, this method returns a string equal to the value of:
- * <blockquote><pre>
- * "MethodHandle" + type().toString()
- * </pre></blockquote>
- * <p>
- * Note: Future releases of this API may add further information
- * to the string representation.
- * Therefore, the present syntax should not be parsed by applications.
- *
- * @return a string representation of the method handle
- */
- @Override
- public String toString() {
- return getNameString(this);
- }
-}
--- a/jdk/src/share/classes/java/dyn/MethodHandleImpl.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1106 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.util.VerifyType;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import sun.dyn.empty.Empty;
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.Wrapper;
-import sun.misc.Unsafe;
-import static java.dyn.MethodHandleStatics.*;
-import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
-
-/**
- * Trusted implementation code for MethodHandle.
- * @author jrose
- */
-/*non-public*/ abstract class MethodHandleImpl {
- /// Factory methods to create method handles:
-
- private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE;
-
- static void initStatics() {
- // Trigger preceding sequence.
- }
-
- /** Look up a given method.
- * Callable only from java.dyn and related packages.
- * <p>
- * The resulting method handle type will be of the given type,
- * with a receiver type {@code rcvc} prepended if the member is not static.
- * <p>
- * Access checks are made as of the given lookup class.
- * In particular, if the method is protected and {@code defc} is in a
- * different package from the lookup class, then {@code rcvc} must be
- * the lookup class or a subclass.
- * @param token Proof that the lookup class has access to this package.
- * @param member Resolved method or constructor to call.
- * @param name Name of the desired method.
- * @param rcvc Receiver type of desired non-static method (else null)
- * @param doDispatch whether the method handle will test the receiver type
- * @param lookupClass access-check relative to this class
- * @return a direct handle to the matching method
- * @throws IllegalAccessException if the given method cannot be accessed by the lookup class
- */
- static
- MethodHandle findMethod(MemberName method,
- boolean doDispatch, Class<?> lookupClass) throws IllegalAccessException {
- MethodType mtype = method.getMethodType();
- if (!method.isStatic()) {
- // adjust the advertised receiver type to be exactly the one requested
- // (in the case of invokespecial, this will be the calling class)
- Class<?> recvType = method.getDeclaringClass();
- mtype = mtype.insertParameterTypes(0, recvType);
- }
- DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
- if (!mh.isValid())
- throw method.makeAccessException("no access", lookupClass);
- assert(mh.type() == mtype);
- if (!method.isVarargs())
- return mh;
- else
- return mh.asVarargsCollector(mtype.parameterType(mtype.parameterCount()-1));
- }
-
- static
- MethodHandle makeAllocator(MethodHandle rawConstructor) {
- MethodType rawConType = rawConstructor.type();
- // Wrap the raw (unsafe) constructor with the allocation of a suitable object.
- MethodHandle allocator
- = AllocateObject.make(rawConType.parameterType(0), rawConstructor);
- assert(allocator.type()
- .equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
- return allocator;
- }
-
- static final class AllocateObject<C> extends BoundMethodHandle {
- private static final Unsafe unsafe = Unsafe.getUnsafe();
-
- private final Class<C> allocateClass;
- private final MethodHandle rawConstructor;
-
- private AllocateObject(MethodHandle invoker,
- Class<C> allocateClass, MethodHandle rawConstructor) {
- super(invoker);
- this.allocateClass = allocateClass;
- this.rawConstructor = rawConstructor;
- }
- static MethodHandle make(Class<?> allocateClass, MethodHandle rawConstructor) {
- MethodType rawConType = rawConstructor.type();
- assert(rawConType.parameterType(0) == allocateClass);
- MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass);
- int nargs = rawConType.parameterCount() - 1;
- if (nargs < INVOKES.length) {
- MethodHandle invoke = INVOKES[nargs];
- MethodType conType = CON_TYPES[nargs];
- MethodHandle gcon = convertArguments(rawConstructor, conType, rawConType, null);
- if (gcon == null) return null;
- MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
- assert(galloc.type() == newType.generic());
- return convertArguments(galloc, newType, galloc.type(), null);
- } else {
- MethodHandle invoke = VARARGS_INVOKE;
- MethodType conType = CON_TYPES[nargs];
- MethodHandle gcon = spreadArguments(rawConstructor, conType, 1);
- if (gcon == null) return null;
- MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
- return collectArguments(galloc, newType, 1, null);
- }
- }
- @Override
- public String toString() {
- return addTypeString(allocateClass.getSimpleName(), this);
- }
- @SuppressWarnings("unchecked")
- private C allocate() throws InstantiationException {
- return (C) unsafe.allocateInstance(allocateClass);
- }
- private C invoke_V(Object... av) throws Throwable {
- C obj = allocate();
- rawConstructor.invokeExact((Object)obj, av);
- return obj;
- }
- private C invoke_L0() throws Throwable {
- C obj = allocate();
- rawConstructor.invokeExact((Object)obj);
- return obj;
- }
- private C invoke_L1(Object a0) throws Throwable {
- C obj = allocate();
- rawConstructor.invokeExact((Object)obj, a0);
- return obj;
- }
- private C invoke_L2(Object a0, Object a1) throws Throwable {
- C obj = allocate();
- rawConstructor.invokeExact((Object)obj, a0, a1);
- return obj;
- }
- private C invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
- C obj = allocate();
- rawConstructor.invokeExact((Object)obj, a0, a1, a2);
- return obj;
- }
- private C invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- C obj = allocate();
- rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3);
- return obj;
- }
- private C invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
- C obj = allocate();
- rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4);
- return obj;
- }
- private C invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
- C obj = allocate();
- rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5);
- return obj;
- }
- private C invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
- C obj = allocate();
- rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6);
- return obj;
- }
- private C invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
- C obj = allocate();
- rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7);
- return obj;
- }
- static MethodHandle[] makeInvokes() {
- ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
- MethodHandles.Lookup lookup = IMPL_LOOKUP;
- for (;;) {
- int nargs = invokes.size();
- String name = "invoke_L"+nargs;
- MethodHandle invoke = null;
- try {
- invoke = lookup.findVirtual(AllocateObject.class, name, MethodType.genericMethodType(nargs));
- } catch (ReflectiveOperationException ex) {
- }
- if (invoke == null) break;
- invokes.add(invoke);
- }
- assert(invokes.size() == 9); // current number of methods
- return invokes.toArray(new MethodHandle[0]);
- };
- static final MethodHandle[] INVOKES = makeInvokes();
- // For testing use this:
- //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
- static final MethodHandle VARARGS_INVOKE;
- static {
- try {
- VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
- } catch (ReflectiveOperationException ex) {
- throw uncaughtException(ex);
- }
- }
- // Corresponding generic constructor types:
- static final MethodType[] CON_TYPES = new MethodType[INVOKES.length];
- static {
- for (int i = 0; i < INVOKES.length; i++)
- CON_TYPES[i] = makeConType(INVOKES[i]);
- }
- static final MethodType VARARGS_CON_TYPE = makeConType(VARARGS_INVOKE);
- static MethodType makeConType(MethodHandle invoke) {
- MethodType invType = invoke.type();
- return invType.changeParameterType(0, Object.class).changeReturnType(void.class);
- }
- }
-
- static
- MethodHandle accessField(MemberName member, boolean isSetter,
- Class<?> lookupClass) {
- // Use sun. misc.Unsafe to dig up the dirt on the field.
- MethodHandle mh = new FieldAccessor(member, isSetter);
- return mh;
- }
-
- static
- MethodHandle accessArrayElement(Class<?> arrayClass, boolean isSetter) {
- if (!arrayClass.isArray())
- throw newIllegalArgumentException("not an array: "+arrayClass);
- Class<?> elemClass = arrayClass.getComponentType();
- MethodHandle[] mhs = FieldAccessor.ARRAY_CACHE.get(elemClass);
- if (mhs == null) {
- if (!FieldAccessor.doCache(elemClass))
- return FieldAccessor.ahandle(arrayClass, isSetter);
- mhs = new MethodHandle[] {
- FieldAccessor.ahandle(arrayClass, false),
- FieldAccessor.ahandle(arrayClass, true)
- };
- if (mhs[0].type().parameterType(0) == Class.class) {
- mhs[0] = MethodHandles.insertArguments(mhs[0], 0, elemClass);
- mhs[1] = MethodHandles.insertArguments(mhs[1], 0, elemClass);
- }
- synchronized (FieldAccessor.ARRAY_CACHE) {} // memory barrier
- FieldAccessor.ARRAY_CACHE.put(elemClass, mhs);
- }
- return mhs[isSetter ? 1 : 0];
- }
-
- static final class FieldAccessor<C,V> extends BoundMethodHandle {
- private static final Unsafe unsafe = Unsafe.getUnsafe();
- final Object base; // for static refs only
- final long offset;
- final String name;
-
- FieldAccessor(MemberName field, boolean isSetter) {
- super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
- this.offset = (long) field.getVMIndex();
- this.name = field.getName();
- this.base = staticBase(field);
- }
- @Override
- public String toString() { return addTypeString(name, this); }
-
- int getFieldI(C obj) { return unsafe.getInt(obj, offset); }
- void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); }
- long getFieldJ(C obj) { return unsafe.getLong(obj, offset); }
- void setFieldJ(C obj, long x) { unsafe.putLong(obj, offset, x); }
- float getFieldF(C obj) { return unsafe.getFloat(obj, offset); }
- void setFieldF(C obj, float x) { unsafe.putFloat(obj, offset, x); }
- double getFieldD(C obj) { return unsafe.getDouble(obj, offset); }
- void setFieldD(C obj, double x) { unsafe.putDouble(obj, offset, x); }
- boolean getFieldZ(C obj) { return unsafe.getBoolean(obj, offset); }
- void setFieldZ(C obj, boolean x) { unsafe.putBoolean(obj, offset, x); }
- byte getFieldB(C obj) { return unsafe.getByte(obj, offset); }
- void setFieldB(C obj, byte x) { unsafe.putByte(obj, offset, x); }
- short getFieldS(C obj) { return unsafe.getShort(obj, offset); }
- void setFieldS(C obj, short x) { unsafe.putShort(obj, offset, x); }
- char getFieldC(C obj) { return unsafe.getChar(obj, offset); }
- void setFieldC(C obj, char x) { unsafe.putChar(obj, offset, x); }
- @SuppressWarnings("unchecked")
- V getFieldL(C obj) { return (V) unsafe.getObject(obj, offset); }
- @SuppressWarnings("unchecked")
- void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); }
- // cast (V) is OK here, since we wrap convertArguments around the MH.
-
- static Object staticBase(MemberName field) {
- if (!field.isStatic()) return null;
- Class c = field.getDeclaringClass();
- java.lang.reflect.Field f;
- try {
- // FIXME: Should not have to create 'f' to get this value.
- f = c.getDeclaredField(field.getName());
- return unsafe.staticFieldBase(f);
- } catch (Exception ee) {
- throw uncaughtException(ee);
- }
- }
-
- int getStaticI() { return unsafe.getInt(base, offset); }
- void setStaticI(int x) { unsafe.putInt(base, offset, x); }
- long getStaticJ() { return unsafe.getLong(base, offset); }
- void setStaticJ(long x) { unsafe.putLong(base, offset, x); }
- float getStaticF() { return unsafe.getFloat(base, offset); }
- void setStaticF(float x) { unsafe.putFloat(base, offset, x); }
- double getStaticD() { return unsafe.getDouble(base, offset); }
- void setStaticD(double x) { unsafe.putDouble(base, offset, x); }
- boolean getStaticZ() { return unsafe.getBoolean(base, offset); }
- void setStaticZ(boolean x) { unsafe.putBoolean(base, offset, x); }
- byte getStaticB() { return unsafe.getByte(base, offset); }
- void setStaticB(byte x) { unsafe.putByte(base, offset, x); }
- short getStaticS() { return unsafe.getShort(base, offset); }
- void setStaticS(short x) { unsafe.putShort(base, offset, x); }
- char getStaticC() { return unsafe.getChar(base, offset); }
- void setStaticC(char x) { unsafe.putChar(base, offset, x); }
- V getStaticL() { return (V) unsafe.getObject(base, offset); }
- void setStaticL(V x) { unsafe.putObject(base, offset, x); }
-
- static String fname(Class<?> vclass, boolean isSetter, boolean isStatic) {
- String stem;
- if (!isStatic)
- stem = (!isSetter ? "getField" : "setField");
- else
- stem = (!isSetter ? "getStatic" : "setStatic");
- return stem + Wrapper.basicTypeChar(vclass);
- }
- static MethodType ftype(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) {
- MethodType type;
- if (!isStatic) {
- if (!isSetter)
- return MethodType.methodType(vclass, cclass);
- else
- return MethodType.methodType(void.class, cclass, vclass);
- } else {
- if (!isSetter)
- return MethodType.methodType(vclass);
- else
- return MethodType.methodType(void.class, vclass);
- }
- }
- static MethodHandle fhandle(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) {
- String name = FieldAccessor.fname(vclass, isSetter, isStatic);
- if (cclass.isPrimitive()) throw newIllegalArgumentException("primitive "+cclass);
- Class<?> ecclass = Object.class; //erase this type
- Class<?> evclass = vclass;
- if (!evclass.isPrimitive()) evclass = Object.class;
- MethodType type = FieldAccessor.ftype(ecclass, evclass, isSetter, isStatic);
- MethodHandle mh;
- try {
- mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type);
- } catch (ReflectiveOperationException ex) {
- throw uncaughtException(ex);
- }
- if (evclass != vclass || (!isStatic && ecclass != cclass)) {
- MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic);
- strongType = strongType.insertParameterTypes(0, FieldAccessor.class);
- mh = MethodHandles.convertArguments(mh, strongType);
- }
- return mh;
- }
-
- /// Support for array element access
- static final HashMap<Class<?>, MethodHandle[]> ARRAY_CACHE =
- new HashMap<Class<?>, MethodHandle[]>();
- // FIXME: Cache on the classes themselves, not here.
- static boolean doCache(Class<?> elemClass) {
- if (elemClass.isPrimitive()) return true;
- ClassLoader cl = elemClass.getClassLoader();
- return cl == null || cl == ClassLoader.getSystemClassLoader();
- }
- static int getElementI(int[] a, int i) { return a[i]; }
- static void setElementI(int[] a, int i, int x) { a[i] = x; }
- static long getElementJ(long[] a, int i) { return a[i]; }
- static void setElementJ(long[] a, int i, long x) { a[i] = x; }
- static float getElementF(float[] a, int i) { return a[i]; }
- static void setElementF(float[] a, int i, float x) { a[i] = x; }
- static double getElementD(double[] a, int i) { return a[i]; }
- static void setElementD(double[] a, int i, double x) { a[i] = x; }
- static boolean getElementZ(boolean[] a, int i) { return a[i]; }
- static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; }
- static byte getElementB(byte[] a, int i) { return a[i]; }
- static void setElementB(byte[] a, int i, byte x) { a[i] = x; }
- static short getElementS(short[] a, int i) { return a[i]; }
- static void setElementS(short[] a, int i, short x) { a[i] = x; }
- static char getElementC(char[] a, int i) { return a[i]; }
- static void setElementC(char[] a, int i, char x) { a[i] = x; }
- static Object getElementL(Object[] a, int i) { return a[i]; }
- static void setElementL(Object[] a, int i, Object x) { a[i] = x; }
- static <V> V getElementL(Class<V[]> aclass, V[] a, int i) { return aclass.cast(a)[i]; }
- static <V> void setElementL(Class<V[]> aclass, V[] a, int i, V x) { aclass.cast(a)[i] = x; }
-
- static String aname(Class<?> aclass, boolean isSetter) {
- Class<?> vclass = aclass.getComponentType();
- if (vclass == null) throw new IllegalArgumentException();
- return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(vclass);
- }
- static MethodType atype(Class<?> aclass, boolean isSetter) {
- Class<?> vclass = aclass.getComponentType();
- if (!isSetter)
- return MethodType.methodType(vclass, aclass, int.class);
- else
- return MethodType.methodType(void.class, aclass, int.class, vclass);
- }
- static MethodHandle ahandle(Class<?> aclass, boolean isSetter) {
- Class<?> vclass = aclass.getComponentType();
- String name = FieldAccessor.aname(aclass, isSetter);
- Class<?> caclass = null;
- if (!vclass.isPrimitive() && vclass != Object.class) {
- caclass = aclass;
- aclass = Object[].class;
- vclass = Object.class;
- }
- MethodType type = FieldAccessor.atype(aclass, isSetter);
- if (caclass != null)
- type = type.insertParameterTypes(0, Class.class);
- MethodHandle mh;
- try {
- mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type);
- } catch (ReflectiveOperationException ex) {
- throw uncaughtException(ex);
- }
- if (caclass != null) {
- MethodType strongType = FieldAccessor.atype(caclass, isSetter);
- mh = MethodHandles.insertArguments(mh, 0, caclass);
- mh = MethodHandles.convertArguments(mh, strongType);
- }
- return mh;
- }
- }
-
- /** Bind a predetermined first argument to the given direct method handle.
- * Callable only from MethodHandles.
- * @param token Proof that the caller has access to this package.
- * @param target Any direct method handle.
- * @param receiver Receiver (or first static method argument) to pre-bind.
- * @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
- */
- static
- MethodHandle bindReceiver(MethodHandle target, Object receiver) {
- if (target instanceof AdapterMethodHandle &&
- ((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY
- ) {
- Object info = MethodHandleNatives.getTargetInfo(target);
- if (info instanceof DirectMethodHandle) {
- DirectMethodHandle dmh = (DirectMethodHandle) info;
- if (receiver == null ||
- dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
- MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0);
- MethodType newType = target.type().dropParameterTypes(0, 1);
- return convertArguments(bmh, newType, bmh.type(), null);
- }
- }
- }
- if (target instanceof DirectMethodHandle)
- return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0);
- return null; // let caller try something else
- }
-
- /** Bind a predetermined argument to the given arbitrary method handle.
- * Callable only from MethodHandles.
- * @param token Proof that the caller has access to this package.
- * @param target Any method handle.
- * @param receiver Argument (which can be a boxed primitive) to pre-bind.
- * @return a suitable BoundMethodHandle
- */
- static
- MethodHandle bindArgument(MethodHandle target, int argnum, Object receiver) {
- return new BoundMethodHandle(target, receiver, argnum);
- }
-
- static MethodHandle convertArguments(MethodHandle target,
- MethodType newType,
- MethodType oldType,
- int[] permutationOrNull) {
- assert(oldType.parameterCount() == target.type().parameterCount());
- if (permutationOrNull != null) {
- int outargs = oldType.parameterCount(), inargs = newType.parameterCount();
- if (permutationOrNull.length != outargs)
- throw newIllegalArgumentException("wrong number of arguments in permutation");
- // Make the individual outgoing argument types match up first.
- Class<?>[] callTypeArgs = new Class<?>[outargs];
- for (int i = 0; i < outargs; i++)
- callTypeArgs[i] = newType.parameterType(permutationOrNull[i]);
- MethodType callType = MethodType.methodType(oldType.returnType(), callTypeArgs);
- target = convertArguments(target, callType, oldType, null);
- assert(target != null);
- oldType = target.type();
- List<Integer> goal = new ArrayList<Integer>(); // i*TOKEN
- List<Integer> state = new ArrayList<Integer>(); // i*TOKEN
- List<Integer> drops = new ArrayList<Integer>(); // not tokens
- List<Integer> dups = new ArrayList<Integer>(); // not tokens
- final int TOKEN = 10; // to mark items which are symbolic only
- // state represents the argument values coming into target
- for (int i = 0; i < outargs; i++) {
- state.add(permutationOrNull[i] * TOKEN);
- }
- // goal represents the desired state
- for (int i = 0; i < inargs; i++) {
- if (state.contains(i * TOKEN)) {
- goal.add(i * TOKEN);
- } else {
- // adapter must initially drop all unused arguments
- drops.add(i);
- }
- }
- // detect duplications
- while (state.size() > goal.size()) {
- for (int i2 = 0; i2 < state.size(); i2++) {
- int arg1 = state.get(i2);
- int i1 = state.indexOf(arg1);
- if (i1 != i2) {
- // found duplicate occurrence at i2
- int arg2 = (inargs++) * TOKEN;
- state.set(i2, arg2);
- dups.add(goal.indexOf(arg1));
- goal.add(arg2);
- }
- }
- }
- assert(state.size() == goal.size());
- int size = goal.size();
- while (!state.equals(goal)) {
- // Look for a maximal sequence of adjacent misplaced arguments,
- // and try to rotate them into place.
- int bestRotArg = -10 * TOKEN, bestRotLen = 0;
- int thisRotArg = -10 * TOKEN, thisRotLen = 0;
- for (int i = 0; i < size; i++) {
- int arg = state.get(i);
- // Does this argument match the current run?
- if (arg == thisRotArg + TOKEN) {
- thisRotArg = arg;
- thisRotLen += 1;
- if (bestRotLen < thisRotLen) {
- bestRotLen = thisRotLen;
- bestRotArg = thisRotArg;
- }
- } else {
- // The old sequence (if any) stops here.
- thisRotLen = 0;
- thisRotArg = -10 * TOKEN;
- // But maybe a new one starts here also.
- int wantArg = goal.get(i);
- final int MAX_ARG_ROTATION = AdapterMethodHandle.MAX_ARG_ROTATION;
- if (arg != wantArg &&
- arg >= wantArg - TOKEN * MAX_ARG_ROTATION &&
- arg <= wantArg + TOKEN * MAX_ARG_ROTATION) {
- thisRotArg = arg;
- thisRotLen = 1;
- }
- }
- }
- if (bestRotLen >= 2) {
- // Do a rotation if it can improve argument positioning
- // by at least 2 arguments. This is not always optimal,
- // but it seems to catch common cases.
- int dstEnd = state.indexOf(bestRotArg);
- int srcEnd = goal.indexOf(bestRotArg);
- int rotBy = dstEnd - srcEnd;
- int dstBeg = dstEnd - (bestRotLen - 1);
- int srcBeg = srcEnd - (bestRotLen - 1);
- assert((dstEnd | dstBeg | srcEnd | srcBeg) >= 0); // no negs
- // Make a span which covers both source and destination.
- int rotBeg = Math.min(dstBeg, srcBeg);
- int rotEnd = Math.max(dstEnd, srcEnd);
- int score = 0;
- for (int i = rotBeg; i <= rotEnd; i++) {
- if ((int)state.get(i) != (int)goal.get(i))
- score += 1;
- }
- List<Integer> rotSpan = state.subList(rotBeg, rotEnd+1);
- Collections.rotate(rotSpan, -rotBy); // reverse direction
- for (int i = rotBeg; i <= rotEnd; i++) {
- if ((int)state.get(i) != (int)goal.get(i))
- score -= 1;
- }
- if (score >= 2) {
- // Improved at least two argument positions. Do it.
- List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray());
- Collections.rotate(ptypes.subList(rotBeg, rotEnd+1), -rotBy);
- MethodType rotType = MethodType.methodType(oldType.returnType(), ptypes);
- MethodHandle nextTarget
- = AdapterMethodHandle.makeRotateArguments(rotType, target,
- rotBeg, rotSpan.size(), rotBy);
- if (nextTarget != null) {
- //System.out.println("Rot: "+rotSpan+" by "+rotBy);
- target = nextTarget;
- oldType = rotType;
- continue;
- }
- }
- // Else de-rotate, and drop through to the swap-fest.
- Collections.rotate(rotSpan, rotBy);
- }
-
- // Now swap like the wind!
- List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray());
- for (int i = 0; i < size; i++) {
- // What argument do I want here?
- int arg = goal.get(i);
- if (arg != state.get(i)) {
- // Where is it now?
- int j = state.indexOf(arg);
- Collections.swap(ptypes, i, j);
- MethodType swapType = MethodType.methodType(oldType.returnType(), ptypes);
- target = AdapterMethodHandle.makeSwapArguments(swapType, target, i, j);
- if (target == null) throw newIllegalArgumentException("cannot swap");
- assert(target.type() == swapType);
- oldType = swapType;
- Collections.swap(state, i, j);
- }
- }
- // One pass of swapping must finish the job.
- assert(state.equals(goal));
- }
- while (!dups.isEmpty()) {
- // Grab a contiguous trailing sequence of dups.
- int grab = dups.size() - 1;
- int dupArgPos = dups.get(grab), dupArgCount = 1;
- while (grab - 1 >= 0) {
- int dup0 = dups.get(grab - 1);
- if (dup0 != dupArgPos - 1) break;
- dupArgPos -= 1;
- dupArgCount += 1;
- grab -= 1;
- }
- //if (dupArgCount > 1) System.out.println("Dup: "+dups.subList(grab, dups.size()));
- dups.subList(grab, dups.size()).clear();
- // In the new target type drop that many args from the tail:
- List<Class<?>> ptypes = oldType.parameterList();
- ptypes = ptypes.subList(0, ptypes.size() - dupArgCount);
- MethodType dupType = MethodType.methodType(oldType.returnType(), ptypes);
- target = AdapterMethodHandle.makeDupArguments(dupType, target, dupArgPos, dupArgCount);
- if (target == null)
- throw newIllegalArgumentException("cannot dup");
- oldType = target.type();
- }
- while (!drops.isEmpty()) {
- // Grab a contiguous initial sequence of drops.
- int dropArgPos = drops.get(0), dropArgCount = 1;
- while (dropArgCount < drops.size()) {
- int drop1 = drops.get(dropArgCount);
- if (drop1 != dropArgPos + dropArgCount) break;
- dropArgCount += 1;
- }
- //if (dropArgCount > 1) System.out.println("Drop: "+drops.subList(0, dropArgCount));
- drops.subList(0, dropArgCount).clear();
- List<Class<?>> dropTypes = newType.parameterList()
- .subList(dropArgPos, dropArgPos + dropArgCount);
- MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes);
- target = AdapterMethodHandle.makeDropArguments(dropType, target, dropArgPos, dropArgCount);
- if (target == null) throw newIllegalArgumentException("cannot drop");
- oldType = target.type();
- }
- }
- if (newType == oldType)
- return target;
- if (oldType.parameterCount() != newType.parameterCount())
- throw newIllegalArgumentException("mismatched parameter count");
- MethodHandle res = AdapterMethodHandle.makePairwiseConvert(newType, target);
- if (res != null)
- return res;
- int argc = oldType.parameterCount();
- // The JVM can't do it directly, so fill in the gap with a Java adapter.
- // TO DO: figure out what to put here from case-by-case experience
- // Use a heavier method: Convert all the arguments to Object,
- // then back to the desired types. We might have to use Java-based
- // method handles to do this.
- MethodType objType = MethodType.genericMethodType(argc);
- MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(objType, target);
- if (objTarget == null)
- objTarget = FromGeneric.make(target);
- res = AdapterMethodHandle.makePairwiseConvert(newType, objTarget);
- if (res != null)
- return res;
- return ToGeneric.make(newType, objTarget);
- }
-
- static MethodHandle spreadArguments(MethodHandle target,
- MethodType newType,
- int spreadArg) {
- // TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
- MethodType oldType = target.type();
- // spread the last argument of newType to oldType
- int spreadCount = oldType.parameterCount() - spreadArg;
- Class<Object[]> spreadArgType = Object[].class;
- MethodHandle res = AdapterMethodHandle.makeSpreadArguments(newType, target, spreadArgType, spreadArg, spreadCount);
- if (res != null)
- return res;
- // try an intermediate adapter
- Class<?> spreadType = null;
- if (spreadArg < 0 || spreadArg >= newType.parameterCount()
- || !VerifyType.isSpreadArgType(spreadType = newType.parameterType(spreadArg)))
- throw newIllegalArgumentException("no restarg in "+newType);
- Class<?>[] ptypes = oldType.parameterArray();
- for (int i = 0; i < spreadCount; i++)
- ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i);
- MethodType midType = MethodType.methodType(newType.returnType(), ptypes);
- // after spreading, some arguments may need further conversion
- MethodHandle target2 = convertArguments(target, midType, oldType, null);
- if (target2 == null)
- throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType);
- res = AdapterMethodHandle.makeSpreadArguments(newType, target2, spreadArgType, spreadArg, spreadCount);
- if (res != null)
- return res;
- res = SpreadGeneric.make(target2, spreadCount);
- if (res != null)
- res = convertArguments(res, newType, res.type(), null);
- return res;
- }
-
- static MethodHandle collectArguments(MethodHandle target,
- MethodType newType,
- int collectArg,
- MethodHandle collector) {
- MethodType oldType = target.type(); // (a...,c)=>r
- if (collector == null) {
- int numCollect = newType.parameterCount() - oldType.parameterCount() + 1;
- collector = ValueConversions.varargsArray(numCollect);
- }
- // newType // (a..., b...)=>r
- MethodType colType = collector.type(); // (b...)=>c
- // oldType // (a..., b...)=>r
- assert(newType.parameterCount() == collectArg + colType.parameterCount());
- assert(oldType.parameterCount() == collectArg + 1);
- MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, null);
- MethodHandle gcollector = convertArguments(collector, colType.generic(), colType, null);
- if (gtarget == null || gcollector == null) return null;
- MethodHandle gresult = FilterGeneric.makeArgumentCollector(gcollector, gtarget);
- MethodHandle result = convertArguments(gresult, newType, gresult.type(), null);
- return result;
- }
-
- static MethodHandle filterArgument(MethodHandle target,
- int pos,
- MethodHandle filter) {
- MethodType ttype = target.type(), gttype = ttype.generic();
- if (ttype != gttype) {
- target = convertArguments(target, gttype, ttype, null);
- ttype = gttype;
- }
- MethodType ftype = filter.type(), gftype = ftype.generic();
- if (ftype.parameterCount() != 1)
- throw new InternalError();
- if (ftype != gftype) {
- filter = convertArguments(filter, gftype, ftype, null);
- ftype = gftype;
- }
- if (ftype == ttype) {
- // simple unary case
- return FilterOneArgument.make(filter, target);
- }
- return FilterGeneric.makeArgumentFilter(pos, filter, target);
- }
-
- static MethodHandle foldArguments(MethodHandle target,
- MethodType newType,
- MethodHandle combiner) {
- MethodType oldType = target.type();
- MethodType ctype = combiner.type();
- MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, null);
- MethodHandle gcombiner = convertArguments(combiner, ctype.generic(), ctype, null);
- if (gtarget == null || gcombiner == null) return null;
- MethodHandle gresult = FilterGeneric.makeArgumentFolder(gcombiner, gtarget);
- MethodHandle result = convertArguments(gresult, newType, gresult.type(), null);
- return result;
- }
-
- static
- MethodHandle dropArguments(MethodHandle target,
- MethodType newType, int argnum) {
- int drops = newType.parameterCount() - target.type().parameterCount();
- MethodHandle res = AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops);
- if (res != null)
- return res;
- throw new UnsupportedOperationException("NYI");
- }
-
- private static class GuardWithTest extends BoundMethodHandle {
- private final MethodHandle test, target, fallback;
- private GuardWithTest(MethodHandle invoker,
- MethodHandle test, MethodHandle target, MethodHandle fallback) {
- super(invoker);
- this.test = test;
- this.target = target;
- this.fallback = fallback;
- }
- static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) {
- MethodType type = target.type();
- int nargs = type.parameterCount();
- if (nargs < INVOKES.length) {
- MethodHandle invoke = INVOKES[nargs];
- MethodType gtype = type.generic();
- assert(invoke.type().dropParameterTypes(0,1) == gtype);
- MethodHandle gtest = convertArguments(test, gtype.changeReturnType(boolean.class), test.type(), null);
- MethodHandle gtarget = convertArguments(target, gtype, type, null);
- MethodHandle gfallback = convertArguments(fallback, gtype, type, null);
- if (gtest == null || gtarget == null || gfallback == null) return null;
- MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
- return convertArguments(gguard, type, gtype, null);
- } else {
- MethodHandle invoke = VARARGS_INVOKE;
- MethodType gtype = MethodType.genericMethodType(1);
- assert(invoke.type().dropParameterTypes(0,1) == gtype);
- MethodHandle gtest = spreadArguments(test, gtype.changeReturnType(boolean.class), 0);
- MethodHandle gtarget = spreadArguments(target, gtype, 0);
- MethodHandle gfallback = spreadArguments(fallback, gtype, 0);
- MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
- if (gtest == null || gtarget == null || gfallback == null) return null;
- return collectArguments(gguard, type, 0, null);
- }
- }
- @Override
- public String toString() {
- return addTypeString(target, this);
- }
- private Object invoke_V(Object... av) throws Throwable {
- if ((boolean) test.invokeExact(av))
- return target.invokeExact(av);
- return fallback.invokeExact(av);
- }
- private Object invoke_L0() throws Throwable {
- if ((boolean) test.invokeExact())
- return target.invokeExact();
- return fallback.invokeExact();
- }
- private Object invoke_L1(Object a0) throws Throwable {
- if ((boolean) test.invokeExact(a0))
- return target.invokeExact(a0);
- return fallback.invokeExact(a0);
- }
- private Object invoke_L2(Object a0, Object a1) throws Throwable {
- if ((boolean) test.invokeExact(a0, a1))
- return target.invokeExact(a0, a1);
- return fallback.invokeExact(a0, a1);
- }
- private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
- if ((boolean) test.invokeExact(a0, a1, a2))
- return target.invokeExact(a0, a1, a2);
- return fallback.invokeExact(a0, a1, a2);
- }
- private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- if ((boolean) test.invokeExact(a0, a1, a2, a3))
- return target.invokeExact(a0, a1, a2, a3);
- return fallback.invokeExact(a0, a1, a2, a3);
- }
- private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
- if ((boolean) test.invokeExact(a0, a1, a2, a3, a4))
- return target.invokeExact(a0, a1, a2, a3, a4);
- return fallback.invokeExact(a0, a1, a2, a3, a4);
- }
- private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
- if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5))
- return target.invokeExact(a0, a1, a2, a3, a4, a5);
- return fallback.invokeExact(a0, a1, a2, a3, a4, a5);
- }
- private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
- if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6))
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
- return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6);
- }
- private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
- if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7))
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
- return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
- }
- static MethodHandle[] makeInvokes() {
- ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
- MethodHandles.Lookup lookup = IMPL_LOOKUP;
- for (;;) {
- int nargs = invokes.size();
- String name = "invoke_L"+nargs;
- MethodHandle invoke = null;
- try {
- invoke = lookup.findVirtual(GuardWithTest.class, name, MethodType.genericMethodType(nargs));
- } catch (ReflectiveOperationException ex) {
- }
- if (invoke == null) break;
- invokes.add(invoke);
- }
- assert(invokes.size() == 9); // current number of methods
- return invokes.toArray(new MethodHandle[0]);
- };
- static final MethodHandle[] INVOKES = makeInvokes();
- // For testing use this:
- //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
- static final MethodHandle VARARGS_INVOKE;
- static {
- try {
- VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true));
- } catch (ReflectiveOperationException ex) {
- throw uncaughtException(ex);
- }
- }
- }
-
- static
- MethodHandle makeGuardWithTest(MethodHandle test,
- MethodHandle target,
- MethodHandle fallback) {
- return GuardWithTest.make(test, target, fallback);
- }
-
- private static class GuardWithCatch extends BoundMethodHandle {
- private final MethodHandle target;
- private final Class<? extends Throwable> exType;
- private final MethodHandle catcher;
- GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
- this(INVOKES[target.type().parameterCount()], target, exType, catcher);
- }
- GuardWithCatch(MethodHandle invoker,
- MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
- super(invoker);
- this.target = target;
- this.exType = exType;
- this.catcher = catcher;
- }
- @Override
- public String toString() {
- return addTypeString(target, this);
- }
- private Object invoke_V(Object... av) throws Throwable {
- try {
- return target.invokeExact(av);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, av);
- }
- }
- private Object invoke_L0() throws Throwable {
- try {
- return target.invokeExact();
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t);
- }
- }
- private Object invoke_L1(Object a0) throws Throwable {
- try {
- return target.invokeExact(a0);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0);
- }
- }
- private Object invoke_L2(Object a0, Object a1) throws Throwable {
- try {
- return target.invokeExact(a0, a1);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1);
- }
- }
- private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2);
- }
- }
- private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2, a3);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2, a3);
- }
- }
- private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2, a3, a4);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2, a3, a4);
- }
- }
- private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2, a3, a4, a5);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5);
- }
- }
- private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
- }
- }
- private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
- try {
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
- } catch (Throwable t) {
- if (!exType.isInstance(t)) throw t;
- return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
- }
- }
- static MethodHandle[] makeInvokes() {
- ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
- MethodHandles.Lookup lookup = IMPL_LOOKUP;
- for (;;) {
- int nargs = invokes.size();
- String name = "invoke_L"+nargs;
- MethodHandle invoke = null;
- try {
- invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
- } catch (ReflectiveOperationException ex) {
- }
- if (invoke == null) break;
- invokes.add(invoke);
- }
- assert(invokes.size() == 9); // current number of methods
- return invokes.toArray(new MethodHandle[0]);
- };
- static final MethodHandle[] INVOKES = makeInvokes();
- // For testing use this:
- //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
- static final MethodHandle VARARGS_INVOKE;
- static {
- try {
- VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
- } catch (ReflectiveOperationException ex) {
- throw uncaughtException(ex);
- }
- }
- }
-
-
- static
- MethodHandle makeGuardWithCatch(MethodHandle target,
- Class<? extends Throwable> exType,
- MethodHandle catcher) {
- MethodType type = target.type();
- MethodType ctype = catcher.type();
- int nargs = type.parameterCount();
- if (nargs < GuardWithCatch.INVOKES.length) {
- MethodType gtype = type.generic();
- MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
- MethodHandle gtarget = convertArguments(target, gtype, type, null);
- MethodHandle gcatcher = convertArguments(catcher, gcatchType, ctype, null);
- MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher);
- if (gtarget == null || gcatcher == null || gguard == null) return null;
- return convertArguments(gguard, type, gtype, null);
- } else {
- MethodType gtype = MethodType.genericMethodType(0, true);
- MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
- MethodHandle gtarget = spreadArguments(target, gtype, 0);
- MethodHandle gcatcher = spreadArguments(catcher, gcatchType, 1);
- MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher);
- if (gtarget == null || gcatcher == null || gguard == null) return null;
- return collectArguments(gguard, type, 0, null);
- }
- }
-
- static
- MethodHandle throwException(MethodType type) {
- return AdapterMethodHandle.makeRetypeRaw(type, throwException());
- }
-
- static MethodHandle THROW_EXCEPTION;
- static MethodHandle throwException() {
- if (THROW_EXCEPTION != null) return THROW_EXCEPTION;
- try {
- THROW_EXCEPTION
- = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
- MethodType.methodType(Empty.class, Throwable.class));
- } catch (ReflectiveOperationException ex) {
- throw new RuntimeException(ex);
- }
- return THROW_EXCEPTION;
- }
- static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
-
- // Linkage support:
- static void registerBootstrap(Class<?> callerClass, MethodHandle bootstrapMethod) {
- MethodHandleNatives.registerBootstrap(callerClass, bootstrapMethod);
- }
- static MethodHandle getBootstrap(Class<?> callerClass) {
- return MethodHandleNatives.getBootstrap(callerClass);
- }
-
- static MethodHandle asVarargsCollector(MethodHandle target, Class<?> arrayType) {
- return AdapterMethodHandle.makeVarargsCollector(target, arrayType);
- }
-}
--- a/jdk/src/share/classes/java/dyn/MethodHandleNatives.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.dyn.MethodHandles.Lookup;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Field;
-import static java.dyn.MethodHandleNatives.Constants.*;
-import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
-
-/**
- * The JVM interface for the method handles package is all here.
- * This is an interface internal and private to an implemetantion of JSR 292.
- * <em>This class is not part of the JSR 292 standard.</em>
- * @author jrose
- */
-class MethodHandleNatives {
-
- private MethodHandleNatives() { } // static only
-
- /// MethodName support
-
- static native void init(MemberName self, Object ref);
- static native void expand(MemberName self);
- static native void resolve(MemberName self, Class<?> caller);
- static native int getMembers(Class<?> defc, String matchName, String matchSig,
- int matchFlags, Class<?> caller, int skip, MemberName[] results);
-
- /// MethodHandle support
-
- /** Initialize the method handle to adapt the call. */
- static native void init(AdapterMethodHandle self, MethodHandle target, int argnum);
- /** Initialize the method handle to call the correct method, directly. */
- static native void init(BoundMethodHandle self, Object target, int argnum);
- /** Initialize the method handle to call as if by an invoke* instruction. */
- static native void init(DirectMethodHandle self, Object ref, boolean doDispatch, Class<?> caller);
-
- /** Initialize a method type, once per form. */
- static native void init(MethodType self);
-
- /** Tell the JVM about a class's bootstrap method. */
- static native void registerBootstrap(Class<?> caller, MethodHandle bootstrapMethod);
-
- /** Ask the JVM about a class's bootstrap method. */
- static native MethodHandle getBootstrap(Class<?> caller);
-
- /** Tell the JVM that we need to change the target of an invokedynamic. */
- static native void setCallSiteTarget(CallSite site, MethodHandle target);
-
- /** Fetch the vmtarget field.
- * It will be sanitized as necessary to avoid exposing non-Java references.
- * This routine is for debugging and reflection.
- */
- static native Object getTarget(MethodHandle self, int format);
-
- /** Fetch the name of the handled method, if available.
- * This routine is for debugging and reflection.
- */
- static MemberName getMethodName(MethodHandle self) {
- return (MemberName) getTarget(self, ETF_METHOD_NAME);
- }
-
- /** Fetch the reflective version of the handled method, if available.
- */
- static AccessibleObject getTargetMethod(MethodHandle self) {
- return (AccessibleObject) getTarget(self, ETF_REFLECT_METHOD);
- }
-
- /** Fetch the target of this method handle.
- * If it directly targets a method, return a MemberName for the method.
- * If it is chained to another method handle, return that handle.
- */
- static Object getTargetInfo(MethodHandle self) {
- return getTarget(self, ETF_HANDLE_OR_METHOD_NAME);
- }
-
- static Object[] makeTarget(Class<?> defc, String name, String sig, int mods, Class<?> refc) {
- return new Object[] { defc, name, sig, mods, refc };
- }
-
- /** Fetch MH-related JVM parameter.
- * which=0 retrieves MethodHandlePushLimit
- * which=1 retrieves stack slot push size (in address units)
- */
- static native int getConstant(int which);
-
- /** Java copy of MethodHandlePushLimit in range 2..255. */
- static final int JVM_PUSH_LIMIT;
- /** JVM stack motion (in words) after one slot is pushed, usually -1.
- */
- static final int JVM_STACK_MOVE_UNIT;
-
- /** Which conv-ops are implemented by the JVM? */
- static final int CONV_OP_IMPLEMENTED_MASK;
-
- private static native void registerNatives();
- static {
- int JVM_PUSH_LIMIT_;
- int JVM_STACK_MOVE_UNIT_;
- int CONV_OP_IMPLEMENTED_MASK_;
- try {
- registerNatives();
- JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT);
- JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT);
- CONV_OP_IMPLEMENTED_MASK_ = getConstant(Constants.GC_CONV_OP_IMPLEMENTED_MASK);
- //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
- } catch (UnsatisfiedLinkError ee) {
- // ignore; if we use init() methods later we'll see linkage errors
- JVM_PUSH_LIMIT_ = 3; // arbitrary
- JVM_STACK_MOVE_UNIT_ = -1; // arbitrary
- CONV_OP_IMPLEMENTED_MASK_ = 0;
- JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
- JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
- throw ee; // just die; hopeless to try to run with an older JVM
- }
- JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
- JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
- if (CONV_OP_IMPLEMENTED_MASK_ == 0)
- CONV_OP_IMPLEMENTED_MASK_ = DEFAULT_CONV_OP_IMPLEMENTED_MASK;
- CONV_OP_IMPLEMENTED_MASK = CONV_OP_IMPLEMENTED_MASK_;
- }
-
- // All compile-time constants go here.
- // There is an opportunity to check them against the JVM's idea of them.
- static class Constants {
- Constants() { } // static only
- // MethodHandleImpl
- static final int // for getConstant
- GC_JVM_PUSH_LIMIT = 0,
- GC_JVM_STACK_MOVE_UNIT = 1,
- GC_CONV_OP_IMPLEMENTED_MASK = 2;
- static final int
- ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
- ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self)
- ETF_METHOD_NAME = 2, // ultimate method as MemberName
- ETF_REFLECT_METHOD = 3; // ultimate method as java.lang.reflect object (sans refClass)
-
- // MemberName
- // The JVM uses values of -2 and above for vtable indexes.
- // Field values are simple positive offsets.
- // Ref: src/share/vm/oops/methodOop.hpp
- // This value is negative enough to avoid such numbers,
- // but not too negative.
- static final int
- MN_IS_METHOD = 0x00010000, // method (not constructor)
- MN_IS_CONSTRUCTOR = 0x00020000, // constructor
- MN_IS_FIELD = 0x00040000, // field
- MN_IS_TYPE = 0x00080000, // nested type
- MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
- MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers
- VM_INDEX_UNINITIALIZED = -99;
-
- // AdapterMethodHandle
- /** Conversions recognized by the JVM.
- * They must align with the constants in java.dyn_AdapterMethodHandle,
- * in the JVM file hotspot/src/share/vm/classfile/javaClasses.hpp.
- */
- static final int
- OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
- OP_RETYPE_RAW = 0x1, // no argument changes; straight retype
- OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument
- OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another
- OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive
- OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper (NYI)
- OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg)
- OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg)
- OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS)
- OP_DROP_ARGS = 0x9, // remove one or more argument slots
- OP_COLLECT_ARGS = 0xA, // combine one or more arguments into a varargs (NYI)
- OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size)
- OP_FLYBY = 0xC, // operate first on reified argument list (NYI)
- OP_RICOCHET = 0xD, // run an adapter chain on the return value (NYI)
- CONV_OP_LIMIT = 0xE; // limit of CONV_OP enumeration
- /** Shift and mask values for decoding the AMH.conversion field.
- * These numbers are shared with the JVM for creating AMHs.
- */
- static final int
- CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
- CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
- CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK
- CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK
- CONV_DEST_TYPE_SHIFT = 12, // byte 2 has the adapter BasicType (if needed)
- CONV_SRC_TYPE_SHIFT = 16, // byte 2 has the source BasicType (if needed)
- CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
- CONV_STACK_MOVE_MASK = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1;
-
- /** Which conv-ops are implemented by the JVM? */
- static final int DEFAULT_CONV_OP_IMPLEMENTED_MASK =
- // Value to use if the corresponding JVM query fails.
- ((1<<OP_RETYPE_ONLY)
- |(1<<OP_RETYPE_RAW)
- |(1<<OP_CHECK_CAST)
- |(1<<OP_PRIM_TO_PRIM)
- |(1<<OP_REF_TO_PRIM)
- |(1<<OP_SWAP_ARGS)
- |(1<<OP_ROT_ARGS)
- |(1<<OP_DUP_ARGS)
- |(1<<OP_DROP_ARGS)
- //|(1<<OP_SPREAD_ARGS)
- );
-
- /**
- * Basic types as encoded in the JVM. These code values are not
- * intended for use outside this class. They are used as part of
- * a private interface between the JVM and this class.
- */
- static final int
- T_BOOLEAN = 4,
- T_CHAR = 5,
- T_FLOAT = 6,
- T_DOUBLE = 7,
- T_BYTE = 8,
- T_SHORT = 9,
- T_INT = 10,
- T_LONG = 11,
- T_OBJECT = 12,
- //T_ARRAY = 13
- T_VOID = 14;
- //T_ADDRESS = 15
-
- /**
- * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries.
- */
- static final int
- REF_getField = 1,
- REF_getStatic = 2,
- REF_putField = 3,
- REF_putStatic = 4,
- REF_invokeVirtual = 5,
- REF_invokeStatic = 6,
- REF_invokeSpecial = 7,
- REF_newInvokeSpecial = 8,
- REF_invokeInterface = 9;
- }
-
- private static native int getNamedCon(int which, Object[] name);
- static boolean verifyConstants() {
- Object[] box = { null };
- for (int i = 0; ; i++) {
- box[0] = null;
- int vmval = getNamedCon(i, box);
- if (box[0] == null) break;
- String name = (String) box[0];
- try {
- Field con = Constants.class.getDeclaredField(name);
- int jval = con.getInt(null);
- if (jval != vmval)
- throw new InternalError(name+": JVM has "+vmval+" while Java has "+jval);
- } catch (Exception ex) {
- throw new InternalError(name+": access failed, got "+ex);
- }
- }
- return true;
- }
- static {
- verifyConstants();
- }
-
- // Up-calls from the JVM.
- // These must NOT be public.
-
- /**
- * The JVM is linking an invokedynamic instruction. Create a reified call site for it.
- */
- static CallSite makeDynamicCallSite(MethodHandle bootstrapMethod,
- String name, MethodType type,
- Object info,
- MemberName callerMethod, int callerBCI) {
- return CallSite.makeSite(bootstrapMethod, name, type, info, callerMethod, callerBCI);
- }
-
- /**
- * Called by the JVM to check the length of a spread array.
- */
- static void checkSpreadArgument(Object av, int n) {
- MethodHandleStatics.checkSpreadArgument(av, n);
- }
-
- /**
- * The JVM wants a pointer to a MethodType. Oblige it by finding or creating one.
- */
- static MethodType findMethodHandleType(Class<?> rtype, Class<?>[] ptypes) {
- return MethodType.makeImpl(rtype, ptypes, true);
- }
-
- /**
- * The JVM wants to use a MethodType with invokeGeneric. Give the runtime fair warning.
- */
- static void notifyGenericMethodType(MethodType type) {
- type.form().notifyGenericMethodType();
- }
-
- /**
- * The JVM wants to raise an exception. Here's the path.
- */
- static void raiseException(int code, Object actual, Object required) {
- String message;
- // disregard the identity of the actual object, if it is not a class:
- if (!(actual instanceof Class) && !(actual instanceof MethodType))
- actual = actual.getClass();
- if (actual != null)
- message = "required "+required+" but encountered "+actual;
- else
- message = "required "+required;
- switch (code) {
- case 192: // checkcast
- throw new ClassCastException(message);
- default:
- throw new InternalError("unexpected code "+code+": "+message);
- }
- }
-
- /**
- * The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help.
- * It will make an up-call to this method. (Do not change the name or signature.)
- */
- static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
- Class<?> defc, String name, Object type) {
- try {
- Lookup lookup = IMPL_LOOKUP.in(callerClass);
- switch (refKind) {
- case REF_getField: return lookup.findGetter( defc, name, (Class<?>) type );
- case REF_getStatic: return lookup.findStaticGetter( defc, name, (Class<?>) type );
- case REF_putField: return lookup.findSetter( defc, name, (Class<?>) type );
- case REF_putStatic: return lookup.findStaticSetter( defc, name, (Class<?>) type );
- case REF_invokeVirtual: return lookup.findVirtual( defc, name, (MethodType) type );
- case REF_invokeStatic: return lookup.findStatic( defc, name, (MethodType) type );
- case REF_invokeSpecial: return lookup.findSpecial( defc, name, (MethodType) type, callerClass );
- case REF_newInvokeSpecial: return lookup.findConstructor( defc, (MethodType) type );
- case REF_invokeInterface: return lookup.findVirtual( defc, name, (MethodType) type );
- }
- throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type);
- } catch (ReflectiveOperationException ex) {
- Error err = new IncompatibleClassChangeError();
- err.initCause(ex);
- throw err;
- }
- }
-}
--- a/jdk/src/share/classes/java/dyn/MethodHandleStatics.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * This class consists exclusively of static names internal to the
- * method handle implementation.
- * Usage: {@code import static java.dyn.MethodHandleStatics.*}
- * @author John Rose, JSR 292 EG
- */
-/*non-public*/ class MethodHandleStatics {
-
- private MethodHandleStatics() { } // do not instantiate
-
- /*non-public*/ static String getNameString(MethodHandle target, MethodType type) {
- if (type == null)
- type = target.type();
- MemberName name = null;
- if (target != null)
- name = MethodHandleNatives.getMethodName(target);
- if (name == null)
- return "invoke" + type;
- return name.getName() + type;
- }
-
- /*non-public*/ static String getNameString(MethodHandle target, MethodHandle typeHolder) {
- return getNameString(target, typeHolder == null ? (MethodType) null : typeHolder.type());
- }
-
- /*non-public*/ static String getNameString(MethodHandle target) {
- return getNameString(target, (MethodType) null);
- }
-
- /*non-public*/ static String addTypeString(Object obj, MethodHandle target) {
- String str = String.valueOf(obj);
- if (target == null) return str;
- int paren = str.indexOf('(');
- if (paren >= 0) str = str.substring(0, paren);
- return str + target.type();
- }
-
- static void checkSpreadArgument(Object av, int n) {
- if (av == null ? n != 0 : ((Object[])av).length != n)
- throw newIllegalArgumentException("Array is not of length "+n);
- }
-
- // handy shared exception makers (they simplify the common case code)
- /*non-public*/ static RuntimeException newIllegalStateException(String message) {
- return new IllegalStateException(message);
- }
- /*non-public*/ static RuntimeException newIllegalStateException(String message, Object obj) {
- return new IllegalStateException(message(message, obj));
- }
- /*non-public*/ static RuntimeException newIllegalArgumentException(String message) {
- return new IllegalArgumentException(message);
- }
- /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj) {
- return new IllegalArgumentException(message(message, obj));
- }
- /*non-public*/ static Error uncaughtException(Exception ex) {
- Error err = new InternalError("uncaught exception");
- err.initCause(ex);
- return err;
- }
- private static String message(String message, Object obj) {
- if (obj != null) message = message + ": " + obj;
- return message;
- }
-}
--- a/jdk/src/share/classes/java/dyn/MethodHandles.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2331 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.lang.reflect.*;
-import sun.dyn.WrapperInstance;
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.VerifyAccess;
-import sun.dyn.util.Wrapper;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import sun.reflect.Reflection;
-import static java.dyn.MethodHandleStatics.*;
-
-/**
- * This class consists exclusively of static methods that operate on or return
- * method handles. They fall into several categories:
- * <ul>
- * <li>Lookup methods which help create method handles for methods and fields.
- * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
- * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
- * <li>Wrapper methods which can convert between method handles and other function-like "SAM types".
- * </ul>
- * <p>
- * @author John Rose, JSR 292 EG
- */
-public class MethodHandles {
-
- private MethodHandles() { } // do not instantiate
-
- private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
- static { MethodHandleImpl.initStatics(); }
- // See IMPL_LOOKUP below.
-
- //// Method handle creation from ordinary methods.
-
- /**
- * Return a {@link Lookup lookup object} on the caller,
- * which has the capability to access any method handle that the caller has access to,
- * including direct method handles to private fields and methods.
- * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
- * Do not store it in place where untrusted code can access it.
- */
- public static Lookup lookup() {
- return new Lookup();
- }
-
- /**
- * Return a {@link Lookup lookup object} which is trusted minimally.
- * It can only be used to create method handles to
- * publicly accessible fields and methods.
- * <p>
- * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
- * of this lookup object will be {@link java.lang.Object}.
- * <p>
- * The lookup class can be changed to any other class {@code C} using an expression of the form
- * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
- * Since all classes have equal access to public names,
- * such a change would confer no new access rights.
- */
- public static Lookup publicLookup() {
- return Lookup.PUBLIC_LOOKUP;
- }
-
- /**
- * A <em>lookup object</em> is a factory for creating method handles,
- * when the creation requires access checking.
- * Method handles do not perform
- * access checks when they are called, but rather when they are created.
- * Therefore, method handle access
- * restrictions must be enforced when a method handle is created.
- * The caller class against which those restrictions are enforced
- * is known as the {@linkplain #lookupClass lookup class}.
- * <p>
- * A lookup class which needs to create method handles will call
- * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
- * When the {@code Lookup} factory object is created, the identity of the lookup class is
- * determined, and securely stored in the {@code Lookup} object.
- * The lookup class (or its delegates) may then use factory methods
- * on the {@code Lookup} object to create method handles for access-checked members.
- * This includes all methods, constructors, and fields which are allowed to the lookup class,
- * even private ones.
- * <p>
- * The factory methods on a {@code Lookup} object correspond to all major
- * use cases for methods, constructors, and fields.
- * Here is a summary of the correspondence between these factory methods and
- * the behavior the resulting method handles:
- * <code>
- * <table border=1 cellpadding=5 summary="lookup method behaviors">
- * <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
- * <td>FT f;</td><td>(T) this.f;</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
- * <td>static<br>FT f;</td><td>(T) C.f;</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
- * <td>FT f;</td><td>this.f = x;</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
- * <td>static<br>FT f;</td><td>C.f = arg;</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
- * <td>T m(A*);</td><td>(T) this.m(arg*);</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
- * <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
- * <td>T m(A*);</td><td>(T) super.m(arg*);</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
- * <td>C(A*);</td><td>(T) new C(arg*);</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
- * <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
- * <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
- * <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
- * <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td>
- * </tr>
- * <tr>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
- * <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
- * </tr>
- * </table>
- * </code>
- * Here, the type {@code C} is the class or interface being searched for a member,
- * documented as a parameter named {@code refc} in the lookup methods.
- * The method or constructor type {@code MT} is composed from the return type {@code T}
- * and the sequence of argument types {@code A*}.
- * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}.
- * The formal parameter {@code this} stands for the self-reference of type {@code C};
- * if it is present, it is always the leading argument to the method handle invocation.
- * The name {@code arg} stands for all the other method handle arguments.
- * In the code examples for the Core Reflection API, the name {@code thisOrNull}
- * stands for a null reference if the accessed method or field is static,
- * and {@code this} otherwise.
- * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand
- * for reflective objects corresponding to the given members.
- * <p>
- * The equivalence between looked-up method handles and underlying
- * class members can break down in a few ways:
- * <ul>
- * <li>If {@code C} is not symbolically accessible from the lookup class's loader,
- * the lookup can still succeed, even when there is no equivalent
- * Java expression or bytecoded constant.
- * <li>Likewise, if {@code T} or {@code MT}
- * is not symbolically accessible from the lookup class's loader,
- * the lookup can still succeed.
- * For example, lookups for {@code MethodHandle.invokeExact} and
- * {@code MethodHandle.invokeGeneric} will always succeed, regardless of requested type.
- * <li>If there is a security manager installed, it can forbid the lookup
- * on various grounds (<a href="#secmgr">see below</a>).
- * By contrast, the {@code ldc} instruction is not subject to
- * security manager checks.
- * </ul>
- *
- * <h3><a name="access"></a>Access checking</h3>
- * Access checks are applied in the factory methods of {@code Lookup},
- * when a method handle is created.
- * This is a key difference from the Core Reflection API, since
- * {@link java.lang.reflect.Method#invoke Method.invoke}
- * performs access checking against every caller, on every call.
- * <p>
- * All access checks start from a {@code Lookup} object, which
- * compares its recorded lookup class against all requests to
- * create method handles.
- * A single {@code Lookup} object can be used to create any number
- * of access-checked method handles, all checked against a single
- * lookup class.
- * <p>
- * A {@code Lookup} object can be shared with other trusted code,
- * such as a metaobject protocol.
- * A shared {@code Lookup} object delegates the capability
- * to create method handles on private members of the lookup class.
- * Even if privileged code uses the {@code Lookup} object,
- * the access checking is confined to the privileges of the
- * original lookup class.
- * <p>
- * A lookup can fail, because
- * the containing class is not accessible to the lookup class, or
- * because the desired class member is missing, or because the
- * desired class member is not accessible to the lookup class.
- * In any of these cases, a {@code ReflectiveOperationException} will be
- * thrown from the attempted lookup. The exact class will be one of
- * the following:
- * <ul>
- * <li>NoSuchMethodException — if a method is requested but does not exist
- * <li>NoSuchFieldException — if a field is requested but does not exist
- * <li>IllegalAccessException — if the member exists but an access check fails
- * </ul>
- * <p>
- * In general, the conditions under which a method handle may be
- * looked up for a method {@code M} are exactly equivalent to the conditions
- * under which the lookup class could have compiled and resolved a call to {@code M}.
- * And the effect of invoking the method handle resulting from the lookup
- * is exactly equivalent to executing the compiled and resolved call to {@code M}.
- * The same point is true of fields and constructors.
- * <p>
- * In some cases, access between nested classes is obtained by the Java compiler by creating
- * an wrapper method to access a private method of another class
- * in the same top-level declaration.
- * For example, a nested class {@code C.D}
- * can access private members within other related classes such as
- * {@code C}, {@code C.D.E}, or {@code C.B},
- * but the Java compiler may need to generate wrapper methods in
- * those related classes. In such cases, a {@code Lookup} object on
- * {@code C.E} would be unable to those private members.
- * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
- * which can transform a lookup on {@code C.E} into one on any of those other
- * classes, without special elevation of privilege.
- * <p>
- * Although bytecode instructions can only refer to classes in
- * a related class loader, this API can search for methods in any
- * class, as long as a reference to its {@code Class} object is
- * available. Such cross-loader references are also possible with the
- * Core Reflection API, and are impossible to bytecode instructions
- * such as {@code invokestatic} or {@code getfield}.
- * There is a {@linkplain java.lang.SecurityManager security manager API}
- * to allow applications to check such cross-loader references.
- * These checks apply to both the {@code MethodHandles.Lookup} API
- * and the Core Reflection API
- * (as found on {@link java.lang.Class Class}).
- * <p>
- * Access checks only apply to named and reflected methods,
- * constructors, and fields.
- * Other method handle creation methods, such as
- * {@link #convertArguments MethodHandles.convertArguments},
- * do not require any access checks, and are done
- * with static methods of {@link MethodHandles},
- * independently of any {@code Lookup} object.
- *
- * <h3>Security manager interactions</h3>
- * <a name="secmgr"></a>
- * If a security manager is present, member lookups are subject to
- * additional checks.
- * From one to four calls are made to the security manager.
- * Any of these calls can refuse access by throwing a
- * {@link java.lang.SecurityException SecurityException}.
- * Define {@code smgr} as the security manager,
- * {@code refc} as the containing class in which the member
- * is being sought, and {@code defc} as the class in which the
- * member is actually defined.
- * The calls are made according to the following rules:
- * <ul>
- * <li>In all cases, {@link SecurityManager#checkMemberAccess
- * smgr.checkMemberAccess(refc, Member.PUBLIC)} is called.
- * <li>If the class loader of the lookup class is not
- * the same as or an ancestor of the class loader of {@code refc},
- * then {@link SecurityManager#checkPackageAccess
- * smgr.checkPackageAccess(refcPkg)} is called,
- * where {@code refcPkg} is the package of {@code refc}.
- * <li>If the retrieved member is not public,
- * {@link SecurityManager#checkMemberAccess
- * smgr.checkMemberAccess(defc, Member.DECLARED)} is called.
- * (Note that {@code defc} might be the same as {@code refc}.)
- * <li>If the retrieved member is not public,
- * and if {@code defc} and {@code refc} are in different class loaders,
- * and if the class loader of the lookup class is not
- * the same as or an ancestor of the class loader of {@code defc},
- * then {@link SecurityManager#checkPackageAccess
- * smgr.checkPackageAccess(defcPkg)} is called,
- * where {@code defcPkg} is the package of {@code defc}.
- * </ul>
- * In all cases, the requesting class presented to the security
- * manager will be the lookup class from the current {@code Lookup} object.
- */
- public static final
- class Lookup {
- /** The class on behalf of whom the lookup is being performed. */
- private final Class<?> lookupClass;
-
- /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
- private final int allowedModes;
-
- /** A single-bit mask representing {@code public} access,
- * which may contribute to the result of {@link #lookupModes lookupModes}.
- * The value, {@code 0x01}, happens to be the same as the value of the
- * {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}.
- */
- public static final int PUBLIC = Modifier.PUBLIC;
-
- /** A single-bit mask representing {@code private} access,
- * which may contribute to the result of {@link #lookupModes lookupModes}.
- * The value, {@code 0x02}, happens to be the same as the value of the
- * {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}.
- */
- public static final int PRIVATE = Modifier.PRIVATE;
-
- /** A single-bit mask representing {@code protected} access,
- * which may contribute to the result of {@link #lookupModes lookupModes}.
- * The value, {@code 0x04}, happens to be the same as the value of the
- * {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}.
- */
- public static final int PROTECTED = Modifier.PROTECTED;
-
- /** A single-bit mask representing {@code package} access (default access),
- * which may contribute to the result of {@link #lookupModes lookupModes}.
- * The value is {@code 0x08}, which does not correspond meaningfully to
- * any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
- */
- public static final int PACKAGE = Modifier.STATIC;
-
- private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
- private static final int TRUSTED = -1;
-
- private static int fixmods(int mods) {
- mods &= (ALL_MODES - PACKAGE);
- return (mods != 0) ? mods : PACKAGE;
- }
-
- /** Tells which class is performing the lookup. It is this class against
- * which checks are performed for visibility and access permissions.
- * <p>
- * The class implies a maximum level of access permission,
- * but the permissions may be additionally limited by the bitmask
- * {@link #lookupModes lookupModes}, which controls whether non-public members
- * can be accessed.
- */
- public Class<?> lookupClass() {
- return lookupClass;
- }
-
- // This is just for calling out to MethodHandleImpl.
- private Class<?> lookupClassOrNull() {
- return (allowedModes == TRUSTED) ? null : lookupClass;
- }
-
- /** Tells which access-protection classes of members this lookup object can produce.
- * The result is a bit-mask of the bits
- * {@linkplain #PUBLIC PUBLIC (0x01)},
- * {@linkplain #PRIVATE PRIVATE (0x02)},
- * {@linkplain #PROTECTED PROTECTED (0x04)},
- * and {@linkplain #PACKAGE PACKAGE (0x08)}.
- * <p>
- * A freshly-created lookup object
- * on the {@linkplain java.dyn.MethodHandles#lookup() caller's class}
- * has all possible bits set, since the caller class can access all its own members.
- * A lookup object on a new lookup class
- * {@linkplain java.dyn.MethodHandles.Lookup#in created from a previous lookup object}
- * may have some mode bits set to zero.
- * The purpose of this is to restrict access via the new lookup object,
- * so that it can access only names which can be reached by the original
- * lookup object, and also by the new lookup class.
- */
- public int lookupModes() {
- return allowedModes & ALL_MODES;
- }
-
- /** Embody the current class (the lookupClass) as a lookup class
- * for method handle creation.
- * Must be called by from a method in this package,
- * which in turn is called by a method not in this package.
- * <p>
- * Also, don't make it private, lest javac interpose
- * an access$N method.
- */
- Lookup() {
- this(getCallerClassAtEntryPoint(), ALL_MODES);
- // make sure we haven't accidentally picked up a privileged class:
- checkUnprivilegedlookupClass(lookupClass);
- }
-
- Lookup(Class<?> lookupClass) {
- this(lookupClass, ALL_MODES);
- }
-
- private Lookup(Class<?> lookupClass, int allowedModes) {
- this.lookupClass = lookupClass;
- this.allowedModes = allowedModes;
- }
-
- /**
- * Creates a lookup on the specified new lookup class.
- * The resulting object will report the specified
- * class as its own {@link #lookupClass lookupClass}.
- * <p>
- * However, the resulting {@code Lookup} object is guaranteed
- * to have no more access capabilities than the original.
- * In particular, access capabilities can be lost as follows:<ul>
- * <li>If the new lookup class differs from the old one,
- * protected members will not be accessible by virtue of inheritance.
- * (Protected members may continue to be accessible because of package sharing.)
- * <li>If the new lookup class is in a different package
- * than the old one, protected and default (package) members will not be accessible.
- * <li>If the new lookup class is not within the same package member
- * as the old one, private members will not be accessible.
- * <li>If the new lookup class is not accessible to the old lookup class,
- * then no members, not even public members, will be accessible.
- * (In all other cases, public members will continue to be accessible.)
- * </ul>
- *
- * @param requestedLookupClass the desired lookup class for the new lookup object
- * @return a lookup object which reports the desired lookup class
- * @throws NullPointerException if the argument is null
- */
- public Lookup in(Class<?> requestedLookupClass) {
- requestedLookupClass.getClass(); // null check
- if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all
- return new Lookup(requestedLookupClass, ALL_MODES);
- if (requestedLookupClass == this.lookupClass)
- return this; // keep same capabilities
- int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
- if ((newModes & PACKAGE) != 0
- && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
- newModes &= ~(PACKAGE|PRIVATE);
- }
- // Allow nestmate lookups to be created without special privilege:
- if ((newModes & PRIVATE) != 0
- && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
- newModes &= ~PRIVATE;
- }
- if (newModes == PUBLIC
- && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass)) {
- // The requested class it not accessible from the lookup class.
- // No permissions.
- newModes = 0;
- }
- checkUnprivilegedlookupClass(requestedLookupClass);
- return new Lookup(requestedLookupClass, newModes);
- }
-
- // Make sure outer class is initialized first.
- static { IMPL_NAMES.getClass(); }
-
- /** Version of lookup which is trusted minimally.
- * It can only be used to create method handles to
- * publicly accessible members.
- */
- static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
-
- /** Package-private version of lookup which is trusted. */
- static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
-
- private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
- String name = lookupClass.getName();
- if (name.startsWith("java.dyn."))
- throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
- }
-
- /**
- * Displays the name of the class from which lookups are to be made.
- * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.)
- * If there are restrictions on the access permitted to this lookup,
- * this is indicated by adding a suffix to the class name, consisting
- * of a slash and a keyword. The keyword represents the strongest
- * allowed access, and is chosen as follows:
- * <ul>
- * <li>If no access is allowed, the suffix is "/noaccess".
- * <li>If only public access is allowed, the suffix is "/public".
- * <li>If only public and package access are allowed, the suffix is "/package".
- * <li>If only public, package, and private access are allowed, the suffix is "/private".
- * </ul>
- * If none of the above cases apply, it is the case that full
- * access (public, package, private, and protected) is allowed.
- * In this case, no suffix is added.
- * This is true only of an object obtained originally from
- * {@link java.dyn.MethodHandles#lookup MethodHandles.lookup}.
- * Objects created by {@link java.dyn.MethodHandles.Lookup#in Lookup.in}
- * always have restricted access, and will display a suffix.
- * <p>
- * (It may seem strange that protected access should be
- * stronger than private access. Viewed independently from
- * package access, protected access is the first to be lost,
- * because it requires a direct subclass relationship between
- * caller and callee.)
- * @see #in
- */
- @Override
- public String toString() {
- String cname = lookupClass.getName();
- switch (allowedModes) {
- case 0: // no privileges
- return cname + "/noaccess";
- case PUBLIC:
- return cname + "/public";
- case PUBLIC|PACKAGE:
- return cname + "/package";
- case ALL_MODES & ~PROTECTED:
- return cname + "/private";
- case ALL_MODES:
- return cname;
- case TRUSTED:
- return "/trusted"; // internal only; not exported
- default: // Should not happen, but it's a bitfield...
- cname = cname + "/" + Integer.toHexString(allowedModes);
- assert(false) : cname;
- return cname;
- }
- }
-
- // call this from an entry point method in Lookup with extraFrames=0.
- private static Class<?> getCallerClassAtEntryPoint() {
- final int CALLER_DEPTH = 4;
- // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
- // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
- // Note: This should be the only use of getCallerClass in this file.
- assert(Reflection.getCallerClass(CALLER_DEPTH-1) == MethodHandles.class);
- return Reflection.getCallerClass(CALLER_DEPTH);
- }
-
- /**
- * Produces a method handle for a static method.
- * The type of the method handle will be that of the method.
- * (Since static methods do not take receivers, there is no
- * additional receiver argument inserted into the method handle type,
- * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.)
- * The method and all its argument types must be accessible to the lookup class.
- * If the method's class has not yet been initialized, that is done
- * immediately, before the method handle is returned.
- * <p>
- * The returned method handle will have
- * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
- * the method's variable arity modifier bit ({@code 0x0080}) is set.
- * @param refc the class from which the method is accessed
- * @param name the name of the method
- * @param type the type of the method
- * @return the desired method handle
- * @throws NoSuchMethodException if the method does not exist
- * @throws IllegalAccessException if access checking fails, or if the method is not {@code static}
- * @exception SecurityException if a security manager is present and it
- * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
- * @throws NullPointerException if any argument is null
- */
- public
- MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
- MemberName method = resolveOrFail(refc, name, type, true);
- checkMethod(refc, method, true);
- return MethodHandleImpl.findMethod(method, false, lookupClassOrNull());
- }
-
- /**
- * Produces a method handle for a virtual method.
- * The type of the method handle will be that of the method,
- * with the receiver type (usually {@code refc}) prepended.
- * The method and all its argument types must be accessible to the lookup class.
- * <p>
- * When called, the handle will treat the first argument as a receiver
- * and dispatch on the receiver's type to determine which method
- * implementation to enter.
- * (The dispatching action is identical with that performed by an
- * {@code invokevirtual} or {@code invokeinterface} instruction.)
- * <p>
- * The returned method handle will have
- * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
- * the method's variable arity modifier bit ({@code 0x0080}) is set.
- * <p>
- * Because of the general equivalence between {@code invokevirtual}
- * instructions and method handles produced by {@code findVirtual},
- * if the class is {@code MethodHandle} and the name string is
- * {@code invokeExact} or {@code invokeGeneric}, the resulting
- * method handle is equivalent to one produced by
- * {@link java.dyn.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
- * {@link java.dyn.MethodHandles#genericInvoker MethodHandles.genericInvoker}
- * with the same {@code type} argument.
- *
- * @param refc the class or interface from which the method is accessed
- * @param name the name of the method
- * @param type the type of the method, with the receiver argument omitted
- * @return the desired method handle
- * @throws NoSuchMethodException if the method does not exist
- * @throws IllegalAccessException if access checking fails, or if the method is {@code static}
- * @exception SecurityException if a security manager is present and it
- * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
- * @throws NullPointerException if any argument is null
- */
- public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
- MemberName method = resolveOrFail(refc, name, type, false);
- checkMethod(refc, method, false);
- MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
- return restrictProtectedReceiver(method, mh);
- }
-
- /**
- * Produces a method handle which creates an object and initializes it, using
- * the constructor of the specified type.
- * The parameter types of the method handle will be those of the constructor,
- * while the return type will be a reference to the constructor's class.
- * The constructor and all its argument types must be accessible to the lookup class.
- * If the constructor's class has not yet been initialized, that is done
- * immediately, before the method handle is returned.
- * <p>
- * Note: The requested type must have a return type of {@code void}.
- * This is consistent with the JVM's treatment of constructor type descriptors.
- * <p>
- * The returned method handle will have
- * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
- * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
- * @param refc the class or interface from which the method is accessed
- * @param type the type of the method, with the receiver argument omitted, and a void return type
- * @return the desired method handle
- * @throws NoSuchMethodException if the constructor does not exist
- * @throws IllegalAccessException if access checking fails
- * @exception SecurityException if a security manager is present and it
- * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
- * @throws NullPointerException if any argument is null
- */
- public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
- String name = "<init>";
- MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
- assert(ctor.isConstructor());
- checkAccess(refc, ctor);
- MethodHandle rawMH = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
- MethodHandle allocMH = MethodHandleImpl.makeAllocator(rawMH);
- return fixVarargs(allocMH, rawMH);
- }
-
- /** Return a version of MH which matches matchMH w.r.t. isVarargsCollector. */
- private static MethodHandle fixVarargs(MethodHandle mh, MethodHandle matchMH) {
- boolean va1 = mh.isVarargsCollector();
- boolean va2 = matchMH.isVarargsCollector();
- if (va1 == va2) {
- return mh;
- } else if (va2) {
- MethodType type = mh.type();
- int arity = type.parameterCount();
- return mh.asVarargsCollector(type.parameterType(arity-1));
- } else {
- throw new InternalError("already varargs, but template is not: "+mh);
- }
- }
-
- /**
- * Produces an early-bound method handle for a virtual method,
- * as if called from an {@code invokespecial}
- * instruction from {@code caller}.
- * The type of the method handle will be that of the method,
- * with a suitably restricted receiver type (such as {@code caller}) prepended.
- * The method and all its argument types must be accessible
- * to the caller.
- * <p>
- * When called, the handle will treat the first argument as a receiver,
- * but will not dispatch on the receiver's type.
- * (This direct invocation action is identical with that performed by an
- * {@code invokespecial} instruction.)
- * <p>
- * If the explicitly specified caller class is not identical with the
- * lookup class, or if this lookup object does not have private access
- * privileges, the access fails.
- * <p>
- * The returned method handle will have
- * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
- * the method's variable arity modifier bit ({@code 0x0080}) is set.
- * @param refc the class or interface from which the method is accessed
- * @param name the name of the method (which must not be "<init>")
- * @param type the type of the method, with the receiver argument omitted
- * @param specialCaller the proposed calling class to perform the {@code invokespecial}
- * @return the desired method handle
- * @throws NoSuchMethodException if the method does not exist
- * @throws IllegalAccessException if access checking fails
- * @exception SecurityException if a security manager is present and it
- * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
- * @throws NullPointerException if any argument is null
- */
- public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
- Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
- checkSpecialCaller(specialCaller);
- MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
- checkMethod(refc, method, false);
- MethodHandle mh = MethodHandleImpl.findMethod(method, false, specialCaller);
- return restrictReceiver(method, mh, specialCaller);
- }
-
- /**
- * Produces a method handle giving read access to a non-static field.
- * The type of the method handle will have a return type of the field's
- * value type.
- * The method handle's single argument will be the instance containing
- * the field.
- * Access checking is performed immediately on behalf of the lookup class.
- * @param refc the class or interface from which the method is accessed
- * @param name the field's name
- * @param type the field's type
- * @return a method handle which can load values from the field
- * @throws NoSuchFieldException if the field does not exist
- * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
- * @exception SecurityException if a security manager is present and it
- * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
- * @throws NullPointerException if any argument is null
- */
- public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
- return makeAccessor(refc, name, type, false, false);
- }
-
- /**
- * Produces a method handle giving write access to a non-static field.
- * The type of the method handle will have a void return type.
- * The method handle will take two arguments, the instance containing
- * the field, and the value to be stored.
- * The second argument will be of the field's value type.
- * Access checking is performed immediately on behalf of the lookup class.
- * @param refc the class or interface from which the method is accessed
- * @param name the field's name
- * @param type the field's type
- * @return a method handle which can store values into the field
- * @throws NoSuchFieldException if the field does not exist
- * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
- * @exception SecurityException if a security manager is present and it
- * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
- * @throws NullPointerException if any argument is null
- */
- public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
- return makeAccessor(refc, name, type, false, true);
- }
-
- /**
- * Produces a method handle giving read access to a static field.
- * The type of the method handle will have a return type of the field's
- * value type.
- * The method handle will take no arguments.
- * Access checking is performed immediately on behalf of the lookup class.
- * @param refc the class or interface from which the method is accessed
- * @param name the field's name
- * @param type the field's type
- * @return a method handle which can load values from the field
- * @throws NoSuchFieldException if the field does not exist
- * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
- * @exception SecurityException if a security manager is present and it
- * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
- * @throws NullPointerException if any argument is null
- */
- public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
- return makeAccessor(refc, name, type, true, false);
- }
-
- /**
- * Produces a method handle giving write access to a static field.
- * The type of the method handle will have a void return type.
- * The method handle will take a single
- * argument, of the field's value type, the value to be stored.
- * Access checking is performed immediately on behalf of the lookup class.
- * @param refc the class or interface from which the method is accessed
- * @param name the field's name
- * @param type the field's type
- * @return a method handle which can store values into the field
- * @throws NoSuchFieldException if the field does not exist
- * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
- * @exception SecurityException if a security manager is present and it
- * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
- * @throws NullPointerException if any argument is null
- */
- public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
- return makeAccessor(refc, name, type, true, true);
- }
-
- /**
- * Produces an early-bound method handle for a non-static method.
- * The receiver must have a supertype {@code defc} in which a method
- * of the given name and type is accessible to the lookup class.
- * The method and all its argument types must be accessible to the lookup class.
- * The type of the method handle will be that of the method,
- * without any insertion of an additional receiver parameter.
- * The given receiver will be bound into the method handle,
- * so that every call to the method handle will invoke the
- * requested method on the given receiver.
- * <p>
- * The returned method handle will have
- * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
- * the method's variable arity modifier bit ({@code 0x0080}) is set
- * <em>and</em> the trailing array argument is not the only argument.
- * (If the trailing array argument is the only argument,
- * the given receiver value will be bound to it.)
- * <p>
- * This is equivalent to the following code:
- * <blockquote><pre>
-MethodHandle mh0 = {@link #findVirtual findVirtual}(defc, name, type);
-MethodHandle mh1 = mh0.{@link MethodHandle#bindTo bindTo}(receiver);
-MethodType mt1 = mh1.type();
-if (mh0.isVarargsCollector() && mt1.parameterCount() > 0) {
- mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
-return mh1;
- * </pre></blockquote>
- * where {@code defc} is either {@code receiver.getClass()} or a super
- * type of that class, in which the requested method is accessible
- * to the lookup class.
- * (Note that {@code bindTo} does not preserve variable arity.)
- * @param receiver the object from which the method is accessed
- * @param name the name of the method
- * @param type the type of the method, with the receiver argument omitted
- * @return the desired method handle
- * @throws NoSuchMethodException if the method does not exist
- * @throws IllegalAccessException if access checking fails
- * @exception SecurityException if a security manager is present and it
- * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
- * @throws NullPointerException if any argument is null
- */
- public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
- Class<? extends Object> refc = receiver.getClass(); // may get NPE
- MemberName method = resolveOrFail(refc, name, type, false);
- checkMethod(refc, method, false);
- MethodHandle dmh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
- MethodHandle bmh = MethodHandleImpl.bindReceiver(dmh, receiver);
- if (bmh == null)
- throw method.makeAccessException("no access", this);
- if (dmh.type().parameterCount() == 0)
- return dmh; // bound the trailing parameter; no varargs possible
- return fixVarargs(bmh, dmh);
- }
-
- /**
- * Make a direct method handle to <i>m</i>, if the lookup class has permission.
- * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
- * If <i>m</i> is virtual, overriding is respected on every call.
- * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
- * The type of the method handle will be that of the method,
- * with the receiver type prepended (but only if it is non-static).
- * If the method's {@code accessible} flag is not set,
- * access checking is performed immediately on behalf of the lookup class.
- * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
- * <p>
- * The returned method handle will have
- * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
- * the method's variable arity modifier bit ({@code 0x0080}) is set.
- * @param m the reflected method
- * @return a method handle which can invoke the reflected method
- * @throws IllegalAccessException if access checking fails
- * @throws NullPointerException if the argument is null
- */
- public MethodHandle unreflect(Method m) throws IllegalAccessException {
- MemberName method = new MemberName(m);
- assert(method.isMethod());
- if (!m.isAccessible()) checkMethod(method.getDeclaringClass(), method, method.isStatic());
- MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
- if (!m.isAccessible()) mh = restrictProtectedReceiver(method, mh);
- return mh;
- }
-
- /**
- * Produces a method handle for a reflected method.
- * It will bypass checks for overriding methods on the receiver,
- * as if by a {@code invokespecial} instruction from within the {@code specialCaller}.
- * The type of the method handle will be that of the method,
- * with the special caller type prepended (and <em>not</em> the receiver of the method).
- * If the method's {@code accessible} flag is not set,
- * access checking is performed immediately on behalf of the lookup class,
- * as if {@code invokespecial} instruction were being linked.
- * <p>
- * The returned method handle will have
- * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
- * the method's variable arity modifier bit ({@code 0x0080}) is set.
- * @param m the reflected method
- * @param specialCaller the class nominally calling the method
- * @return a method handle which can invoke the reflected method
- * @throws IllegalAccessException if access checking fails
- * @throws NullPointerException if any argument is null
- */
- public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
- checkSpecialCaller(specialCaller);
- MemberName method = new MemberName(m);
- assert(method.isMethod());
- // ignore m.isAccessible: this is a new kind of access
- checkMethod(m.getDeclaringClass(), method, false);
- MethodHandle mh = MethodHandleImpl.findMethod(method, false, lookupClassOrNull());
- return restrictReceiver(method, mh, specialCaller);
- }
-
- /**
- * Produces a method handle for a reflected constructor.
- * The type of the method handle will be that of the constructor,
- * with the return type changed to the declaring class.
- * The method handle will perform a {@code newInstance} operation,
- * creating a new instance of the constructor's class on the
- * arguments passed to the method handle.
- * <p>
- * If the constructor's {@code accessible} flag is not set,
- * access checking is performed immediately on behalf of the lookup class.
- * <p>
- * The returned method handle will have
- * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
- * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
- * @param c the reflected constructor
- * @return a method handle which can invoke the reflected constructor
- * @throws IllegalAccessException if access checking fails
- * @throws NullPointerException if the argument is null
- */
- public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException {
- MemberName ctor = new MemberName(c);
- assert(ctor.isConstructor());
- if (!c.isAccessible()) checkAccess(c.getDeclaringClass(), ctor);
- MethodHandle rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
- MethodHandle allocator = MethodHandleImpl.makeAllocator(rawCtor);
- return fixVarargs(allocator, rawCtor);
- }
-
- /**
- * Produces a method handle giving read access to a reflected field.
- * The type of the method handle will have a return type of the field's
- * value type.
- * If the field is static, the method handle will take no arguments.
- * Otherwise, its single argument will be the instance containing
- * the field.
- * If the method's {@code accessible} flag is not set,
- * access checking is performed immediately on behalf of the lookup class.
- * @param f the reflected field
- * @return a method handle which can load values from the reflected field
- * @throws IllegalAccessException if access checking fails
- * @throws NullPointerException if the argument is null
- */
- public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
- return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false);
- }
-
- /**
- * Produces a method handle giving write access to a reflected field.
- * The type of the method handle will have a void return type.
- * If the field is static, the method handle will take a single
- * argument, of the field's value type, the value to be stored.
- * Otherwise, the two arguments will be the instance containing
- * the field, and the value to be stored.
- * If the method's {@code accessible} flag is not set,
- * access checking is performed immediately on behalf of the lookup class.
- * @param f the reflected field
- * @return a method handle which can store values into the reflected field
- * @throws IllegalAccessException if access checking fails
- * @throws NullPointerException if the argument is null
- */
- public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
- return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true);
- }
-
- /// Helper methods, all package-private.
-
- MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoSuchFieldException, IllegalAccessException {
- checkSymbolicClass(refc); // do this before attempting to resolve
- name.getClass(); type.getClass(); // NPE
- int mods = (isStatic ? Modifier.STATIC : 0);
- return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(),
- NoSuchFieldException.class);
- }
-
- MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoSuchMethodException, IllegalAccessException {
- checkSymbolicClass(refc); // do this before attempting to resolve
- name.getClass(); type.getClass(); // NPE
- int mods = (isStatic ? Modifier.STATIC : 0);
- return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(),
- NoSuchMethodException.class);
- }
-
- MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
- boolean searchSupers, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
- checkSymbolicClass(refc); // do this before attempting to resolve
- name.getClass(); type.getClass(); // NPE
- int mods = (isStatic ? Modifier.STATIC : 0);
- return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller,
- NoSuchMethodException.class);
- }
-
- void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
- Class<?> caller = lookupClassOrNull();
- if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
- throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
- }
-
- void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws IllegalAccessException {
- String message;
- if (m.isConstructor())
- message = "expected a method, not a constructor";
- else if (!m.isMethod())
- message = "expected a method";
- else if (wantStatic != m.isStatic())
- message = wantStatic ? "expected a static method" : "expected a non-static method";
- else
- { checkAccess(refc, m); return; }
- throw m.makeAccessException(message, this);
- }
-
- void checkAccess(Class<?> refc, MemberName m) throws IllegalAccessException {
- int allowedModes = this.allowedModes;
- if (allowedModes == TRUSTED) return;
- int mods = m.getModifiers();
- if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
- return; // common case
- int requestedModes = fixmods(mods); // adjust 0 => PACKAGE
- if ((requestedModes & allowedModes) != 0
- && VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
- mods, lookupClass()))
- return;
- if (((requestedModes & ~allowedModes) & PROTECTED) != 0
- && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
- // Protected members can also be checked as if they were package-private.
- return;
- throw m.makeAccessException(accessFailedMessage(refc, m), this);
- }
-
- String accessFailedMessage(Class<?> refc, MemberName m) {
- Class<?> defc = m.getDeclaringClass();
- int mods = m.getModifiers();
- // check the class first:
- boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
- (defc == refc ||
- Modifier.isPublic(refc.getModifiers())));
- if (!classOK && (allowedModes & PACKAGE) != 0) {
- classOK = (VerifyAccess.isClassAccessible(defc, lookupClass()) &&
- (defc == refc ||
- VerifyAccess.isClassAccessible(refc, lookupClass())));
- }
- if (!classOK)
- return "class is not public";
- if (Modifier.isPublic(mods))
- return "access to public member failed"; // (how?)
- if (Modifier.isPrivate(mods))
- return "member is private";
- if (Modifier.isProtected(mods))
- return "member is protected";
- return "member is private to package";
- }
-
- private static final boolean ALLOW_NESTMATE_ACCESS = false;
-
- void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
- if (allowedModes == TRUSTED) return;
- if ((allowedModes & PRIVATE) == 0
- || (specialCaller != lookupClass()
- && !(ALLOW_NESTMATE_ACCESS &&
- VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
- throw new MemberName(specialCaller).
- makeAccessException("no private access for invokespecial", this);
- }
-
- MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws IllegalAccessException {
- // The accessing class only has the right to use a protected member
- // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc.
- if (!method.isProtected() || method.isStatic()
- || allowedModes == TRUSTED
- || method.getDeclaringClass() == lookupClass()
- || (ALLOW_NESTMATE_ACCESS &&
- VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
- return mh;
- else
- return restrictReceiver(method, mh, lookupClass());
- }
- MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException {
- assert(!method.isStatic());
- Class<?> defc = method.getDeclaringClass(); // receiver type of mh is too wide
- if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
- throw method.makeAccessException("caller class must be a subclass below the method", caller);
- }
- MethodType rawType = mh.type();
- if (rawType.parameterType(0) == caller) return mh;
- MethodType narrowType = rawType.changeParameterType(0, caller);
- MethodHandle narrowMH = MethodHandleImpl.convertArguments(mh, narrowType, rawType, null);
- return fixVarargs(narrowMH, mh);
- }
-
- MethodHandle makeAccessor(Class<?> refc, String name, Class<?> type,
- boolean isStatic, boolean isSetter) throws NoSuchFieldException, IllegalAccessException {
- MemberName field = resolveOrFail(refc, name, type, isStatic);
- if (isStatic != field.isStatic())
- throw field.makeAccessException(isStatic
- ? "expected a static field"
- : "expected a non-static field", this);
- return makeAccessor(refc, field, false, isSetter);
- }
-
- MethodHandle makeAccessor(Class<?> refc, MemberName field,
- boolean trusted, boolean isSetter) throws IllegalAccessException {
- assert(field.isField());
- if (trusted)
- return MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
- checkAccess(refc, field);
- MethodHandle mh = MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
- return restrictProtectedReceiver(field, mh);
- }
- }
-
- /**
- * Produces a method handle giving read access to elements of an array.
- * The type of the method handle will have a return type of the array's
- * element type. Its first argument will be the array type,
- * and the second will be {@code int}.
- * @param arrayClass an array type
- * @return a method handle which can load values from the given array type
- * @throws NullPointerException if the argument is null
- * @throws IllegalArgumentException if arrayClass is not an array type
- */
- public static
- MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
- return MethodHandleImpl.accessArrayElement(arrayClass, false);
- }
-
- /**
- * Produces a method handle giving write access to elements of an array.
- * The type of the method handle will have a void return type.
- * Its last argument will be the array's element type.
- * The first and second arguments will be the array type and int.
- * @return a method handle which can store values into the array type
- * @throws NullPointerException if the argument is null
- * @throws IllegalArgumentException if arrayClass is not an array type
- */
- public static
- MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
- return MethodHandleImpl.accessArrayElement(arrayClass, true);
- }
-
- /// method handle invocation (reflective style)
-
- /**
- * Produces a method handle which will invoke any method handle of the
- * given {@code type} on a standard set of {@code Object} type arguments
- * and a single trailing {@code Object[]} array.
- * The resulting invoker will be a method handle with the following
- * arguments:
- * <ul>
- * <li>a single {@code MethodHandle} target
- * <li>zero or more {@code Object} values (counted by {@code objectArgCount})
- * <li>an {@code Object[]} array containing more arguments
- * </ul>
- * <p>
- * The invoker will behave like a call to {@link MethodHandle#invokeGeneric invokeGeneric} with
- * the indicated {@code type}.
- * That is, if the target is exactly of the given {@code type}, it will behave
- * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType}
- * is used to convert the target to the required {@code type}.
- * <p>
- * The type of the returned invoker will not be the given {@code type}, but rather
- * will have all parameter and return types replaced by {@code Object}, except for
- * the last parameter type, which will be the array type {@code Object[]}.
- * <p>
- * Before invoking its target, the invoker will spread the varargs array, apply
- * reference casts as necessary, and unbox and widen primitive arguments.
- * The return value of the invoker will be an {@code Object} reference,
- * boxing a primitive value if the original type returns a primitive,
- * and always null if the original type returns void.
- * <p>
- * This method is equivalent to the following code (though it may be more efficient):
- * <p><blockquote><pre>
-MethodHandle invoker = MethodHandles.genericInvoker(type);
-int spreadArgCount = type.parameterCount - objectArgCount;
-invoker = invoker.asSpreader(Object[].class, spreadArgCount);
-return invoker;
- * </pre></blockquote>
- * <p>
- * This method throws no reflective or security exceptions.
- * @param type the desired target type
- * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
- * @return a method handle suitable for invoking any method handle of the given type
- */
- static public
- MethodHandle spreadInvoker(MethodType type, int objectArgCount) {
- if (objectArgCount < 0 || objectArgCount > type.parameterCount())
- throw new IllegalArgumentException("bad argument count "+objectArgCount);
- return type.invokers().spreadInvoker(objectArgCount);
- }
-
- /**
- * Produces a special <em>invoker method handle</em> which can be used to
- * invoke any method handle of the given type, as if by {@code invokeExact}.
- * The resulting invoker will have a type which is
- * exactly equal to the desired type, except that it will accept
- * an additional leading argument of type {@code MethodHandle}.
- * <p>
- * This method is equivalent to the following code (though it may be more efficient):
- * <p><blockquote><pre>
-publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
- * </pre></blockquote>
- *
- * <p style="font-size:smaller;">
- * <em>Discussion:</em>
- * Invoker method handles can be useful when working with variable method handles
- * of unknown types.
- * For example, to emulate an {@code invokeExact} call to a variable method
- * handle {@code M}, extract its type {@code T},
- * look up the invoker method {@code X} for {@code T},
- * and call the invoker method, as {@code X.invokeGeneric(T, A...)}.
- * (It would not work to call {@code X.invokeExact}, since the type {@code T}
- * is unknown.)
- * If spreading, collecting, or other argument transformations are required,
- * they can be applied once to the invoker {@code X} and reused on many {@code M}
- * method handle values, as long as they are compatible with the type of {@code X}.
- * <p>
- * <em>(Note: The invoker method is not available via the Core Reflection API.
- * An attempt to call {@linkplain java.lang.reflect.Method#invoke Method.invoke}
- * on the declared {@code invokeExact} or {@code invokeGeneric} method will raise an
- * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
- * <p>
- * This method throws no reflective or security exceptions.
- * @param type the desired target type
- * @return a method handle suitable for invoking any method handle of the given type
- */
- static public
- MethodHandle exactInvoker(MethodType type) {
- return type.invokers().exactInvoker();
- }
-
- /**
- * Produces a special <em>invoker method handle</em> which can be used to
- * invoke any method handle of the given type, as if by {@code invokeGeneric}.
- * The resulting invoker will have a type which is
- * exactly equal to the desired type, except that it will accept
- * an additional leading argument of type {@code MethodHandle}.
- * <p>
- * Before invoking its target, the invoker will apply reference casts as
- * necessary and unbox and widen primitive arguments, as if by {@link #convertArguments convertArguments}.
- * The return value of the invoker will be an {@code Object} reference,
- * boxing a primitive value if the original type returns a primitive,
- * and always null if the original type returns void.
- * <p>
- * This method is equivalent to the following code (though it may be more efficient):
- * <p><blockquote><pre>
-publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
- * </pre></blockquote>
- * <p>
- * This method throws no reflective or security exceptions.
- * @param type the desired target type
- * @return a method handle suitable for invoking any method handle convertible to the given type
- */
- static public
- MethodHandle genericInvoker(MethodType type) {
- return type.invokers().genericInvoker();
- }
-
- /**
- * Perform value checking, exactly as if for an adapted method handle.
- * It is assumed that the given value is either null, of type T0,
- * or (if T0 is primitive) of the wrapper type corresponding to T0.
- * The following checks and conversions are made:
- * <ul>
- * <li>If T0 and T1 are references, then a cast to T1 is applied.
- * (The types do not need to be related in any particular way.)
- * <li>If T0 and T1 are primitives, then a widening or narrowing
- * conversion is applied, if one exists.
- * <li>If T0 is a primitive and T1 a reference, and
- * T0 has a wrapper type TW, a boxing conversion to TW is applied,
- * possibly followed by a reference conversion.
- * T1 must be TW or a supertype.
- * <li>If T0 is a reference and T1 a primitive, and
- * T1 has a wrapper type TW, an unboxing conversion is applied,
- * possibly preceded by a reference conversion.
- * T0 must be TW or a supertype.
- * <li>If T1 is void, the return value is discarded
- * <li>If T0 is void and T1 a reference, a null value is introduced.
- * <li>If T0 is void and T1 a primitive, a zero value is introduced.
- * </ul>
- * If the value is discarded, null will be returned.
- * @param valueType
- * @param value
- * @return the value, converted if necessary
- * @throws java.lang.ClassCastException if a cast fails
- */
- static
- <T0, T1> T1 checkValue(Class<T0> t0, Class<T1> t1, Object value)
- throws ClassCastException
- {
- if (t0 == t1) {
- // no conversion needed; just reassert the same type
- if (t0.isPrimitive())
- return Wrapper.asPrimitiveType(t1).cast(value);
- else
- return Wrapper.OBJECT.convert(value, t1);
- }
- boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
- if (!prim0) {
- // check contract with caller
- Wrapper.OBJECT.convert(value, t0);
- if (!prim1) {
- return Wrapper.OBJECT.convert(value, t1);
- }
- // convert reference to primitive by unboxing
- Wrapper w1 = Wrapper.forPrimitiveType(t1);
- return w1.convert(value, t1);
- }
- // check contract with caller:
- Wrapper.asWrapperType(t0).cast(value);
- Wrapper w1 = Wrapper.forPrimitiveType(t1);
- return w1.convert(value, t1);
- }
-
- static
- Object checkValue(Class<?> T1, Object value)
- throws ClassCastException
- {
- Class<?> T0;
- if (value == null)
- T0 = Object.class;
- else
- T0 = value.getClass();
- return checkValue(T0, T1, value);
- }
-
- /// method handle modification (creation from other method handles)
-
- /**
- * Produces a method handle which adapts the type of the
- * given method handle to a new type by pairwise argument conversion.
- * The original type and new type must have the same number of arguments.
- * The resulting method handle is guaranteed to report a type
- * which is equal to the desired new type.
- * <p>
- * If the original type and new type are equal, returns target.
- * <p>
- * The following conversions are applied as needed both to
- * arguments and return types. Let T0 and T1 be the differing
- * new and old parameter types (or old and new return types)
- * for corresponding values passed by the new and old method types.
- * Given those types T0, T1, one of the following conversions is applied
- * if possible:
- * <ul>
- * <li>If T0 and T1 are references, then a cast to T1 is applied.
- * (The types do not need to be related in any particular way.)
- * <li>If T0 and T1 are primitives, then a Java method invocation
- * conversion (JLS 5.3) is applied, if one exists.
- * <li>If T0 is a primitive and T1 a reference, a boxing
- * conversion is applied if one exists, possibly followed by
- * a reference conversion to a superclass.
- * T1 must be a wrapper class or a supertype of one.
- * <li>If T0 is a reference and T1 a primitive, an unboxing
- * conversion will be applied at runtime, possibly followed
- * by a Java method invocation conversion (JLS 5.3)
- * on the primitive value. (These are the widening conversions.)
- * T0 must be a wrapper class or a supertype of one.
- * (In the case where T0 is Object, these are the conversions
- * allowed by java.lang.reflect.Method.invoke.)
- * <li>If the return type T1 is void, any returned value is discarded
- * <li>If the return type T0 is void and T1 a reference, a null value is introduced.
- * <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
- * </ul>
- * @param target the method handle to invoke after arguments are retyped
- * @param newType the expected type of the new method handle
- * @return a method handle which delegates to {@code target} after performing
- * any necessary argument conversions, and arranges for any
- * necessary return value conversions
- * @throws NullPointerException if either argument is null
- * @throws WrongMethodTypeException if the conversion cannot be made
- * @see MethodHandle#asType
- * @see MethodHandles#explicitCastArguments
- */
- public static
- MethodHandle convertArguments(MethodHandle target, MethodType newType) {
- MethodType oldType = target.type();
- if (oldType.equals(newType))
- return target;
- MethodHandle res = null;
- try {
- res = MethodHandleImpl.convertArguments(target,
- newType, oldType, null);
- } catch (IllegalArgumentException ex) {
- }
- if (res == null)
- throw new WrongMethodTypeException("cannot convert to "+newType+": "+target);
- return res;
- }
-
- /**
- * Produces a method handle which adapts the type of the
- * given method handle to a new type by pairwise argument conversion.
- * The original type and new type must have the same number of arguments.
- * The resulting method handle is guaranteed to report a type
- * which is equal to the desired new type.
- * <p>
- * If the original type and new type are equal, returns target.
- * <p>
- * The same conversions are allowed as for {@link #convertArguments convertArguments},
- * and some additional conversions are also applied if those conversions fail.
- * Given types T0, T1, one of the following conversions is applied
- * in addition, if the conversions specified for {@code convertArguments}
- * would be insufficient:
- * <ul>
- * <li>If T0 and T1 are references, and T1 is an interface type,
- * then the value of type T0 is passed as a T1 without a cast.
- * (This treatment of interfaces follows the usage of the bytecode verifier.)
- * <li>If T0 and T1 are primitives and one is boolean,
- * the boolean is treated as a one-bit unsigned integer.
- * (This treatment follows the usage of the bytecode verifier.)
- * A conversion from another primitive type behaves as if
- * it first converts to byte, and then masks all but the low bit.
- * <li>If a primitive value would be converted by {@code convertArguments}
- * using Java method invocation conversion (JLS 5.3),
- * Java casting conversion (JLS 5.5) may be used also.
- * This allows primitives to be narrowed as well as widened.
- * </ul>
- * @param target the method handle to invoke after arguments are retyped
- * @param newType the expected type of the new method handle
- * @return a method handle which delegates to {@code target} after performing
- * any necessary argument conversions, and arranges for any
- * necessary return value conversions
- * @throws NullPointerException if either argument is null
- * @throws WrongMethodTypeException if the conversion cannot be made
- * @see MethodHandle#asType
- * @see MethodHandles#convertArguments
- */
- public static
- MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
- return convertArguments(target, newType); // FIXME!
- }
-
- /*
- FIXME: Reconcile javadoc with 10/22/2010 EG notes on conversion:
-
- Both converters arrange for their method handles to convert arguments
- and return values. The conversion rules are the same for arguments
- and return values, and depend only on source and target types, S and
- T. The conversions allowed by castConvertArguments are a strict
- superset of those performed by convertArguments.
-
- In all cases, if S and T are references, a simple checkcast is done.
- If neither S nor T is a primitive, no attempt is made to unbox and
- box. A failed conversion throws ClassCastException.
-
- If T is void, the value is dropped.
-
- For compatibility with reflection, if S is void and T is a reference,
- a null value is produced.
-
- For compatibility with reflection, if S is a reference and T is a
- primitive, S is first unboxed and then undergoes primitive conversion.
- In the case of 'convertArguments', only assignment conversion is
- performed (no narrowing primitive conversion).
-
- If S is a primitive, S is boxed, and then the above rules are applied.
- If S and T are both primitives, the boxing will be undetectable; only
- the primitive conversions will be apparent to the user. The key point
- is that if S is a primitive type, the implementation may box it and
- treat is as Object, without loss of information, or it may use a "fast
- path" which does not use boxing.
-
- Notwithstanding the rules above, for compatibility with the verifier,
- if T is an interface, it is treated as if it were Object. [KEEP THIS?]
-
- Also, for compatibility with the verifier, a boolean may be undergo
- widening or narrowing conversion to any other primitive type. [KEEP THIS?]
- */
-
- /**
- * Produces a method handle which adapts the calling sequence of the
- * given method handle to a new type, by reordering the arguments.
- * The resulting method handle is guaranteed to report a type
- * which is equal to the desired new type.
- * <p>
- * The given array controls the reordering.
- * Call {@code #I} the number of incoming parameters (the value
- * {@code newType.parameterCount()}, and call {@code #O} the number
- * of outgoing parameters (the value {@code target.type().parameterCount()}).
- * Then the length of the reordering array must be {@code #O},
- * and each element must be a non-negative number less than {@code #I}.
- * For every {@code N} less than {@code #O}, the {@code N}-th
- * outgoing argument will be taken from the {@code I}-th incoming
- * argument, where {@code I} is {@code reorder[N]}.
- * <p>
- * No argument or return value conversions are applied.
- * The type of each incoming argument, as determined by {@code newType},
- * must be identical to the type of the corresponding outgoing argument
- * or arguments in the target method handle.
- * The return type of {@code newType} must be identical to the return
- * type of the original target.
- * <p>
- * The reordering array need not specify an actual permutation.
- * An incoming argument will be duplicated if its index appears
- * more than once in the array, and an incoming argument will be dropped
- * if its index does not appear in the array.
- * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
- * incoming arguments which are not mentioned in the reordering array
- * are may be any type, as determined only by {@code newType}.
- * <blockquote><pre>
-MethodType intfn1 = MethodType.methodType(int.class, int.class);
-MethodType intfn2 = MethodType.methodType(int.class, int.class, int.class);
-MethodHandle sub = ... {int x, int y => x-y} ...;
-assert(sub.type().equals(intfn2));
-MethodHandle sub1 = MethodHandles.permuteArguments(sub, intfn2, 0, 1);
-MethodHandle rsub = MethodHandles.permuteArguments(sub, intfn2, 1, 0);
-assert((int)rsub.invokeExact(1, 100) == 99);
-MethodHandle add = ... {int x, int y => x+y} ...;
-assert(add.type().equals(intfn2));
-MethodHandle twice = MethodHandles.permuteArguments(add, intfn1, 0, 0);
-assert(twice.type().equals(intfn1));
-assert((int)twice.invokeExact(21) == 42);
- * </pre></blockquote>
- * @param target the method handle to invoke after arguments are reordered
- * @param newType the expected type of the new method handle
- * @param reorder a string which controls the reordering
- * @return a method handle which delegates to {@code target} after it
- * drops unused arguments and moves and/or duplicates the other arguments
- * @throws NullPointerException if any argument is null
- */
- public static
- MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
- MethodType oldType = target.type();
- checkReorder(reorder, newType, oldType);
- return MethodHandleImpl.convertArguments(target,
- newType, oldType,
- reorder);
- }
-
- private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
- if (reorder.length == oldType.parameterCount()) {
- int limit = newType.parameterCount();
- boolean bad = false;
- for (int i : reorder) {
- if (i < 0 || i >= limit) {
- bad = true; break;
- }
- }
- if (!bad) return;
- }
- throw newIllegalArgumentException("bad reorder array");
- }
-
- /**
- * Equivalent to the following code:
- * <p><blockquote><pre>
- * int spreadPos = newType.parameterCount() - 1;
- * Class<?> spreadType = newType.parameterType(spreadPos);
- * int spreadCount = target.type().parameterCount() - spreadPos;
- * MethodHandle adapter = target.asSpreader(spreadType, spreadCount);
- * adapter = adapter.asType(newType);
- * return adapter;
- * </pre></blockquote>
- * @param target the method handle to invoke after argument spreading
- * @param newType the expected type of the new method handle
- * @return a method handle which spreads its final argument,
- * before calling the original method handle
- */
- /*non-public*/ static
- MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
- MethodType oldType = target.type();
- int inargs = newType.parameterCount();
- int outargs = oldType.parameterCount();
- int spreadPos = inargs - 1;
- int numSpread = (outargs - spreadPos);
- MethodHandle res = null;
- if (spreadPos >= 0 && numSpread >= 0) {
- res = MethodHandleImpl.spreadArguments(target, newType, spreadPos);
- }
- if (res == null) {
- throw newIllegalArgumentException("cannot spread "+newType+" to " +oldType);
- }
- return res;
- }
-
- /**
- * Equivalent to the following code:
- * <p><blockquote><pre>
- * int collectPos = target.type().parameterCount() - 1;
- * Class<?> collectType = target.type().parameterType(collectPos);
- * if (!collectType.isArray()) collectType = Object[].class;
- * int collectCount = newType.parameterCount() - collectPos;
- * MethodHandle adapter = target.asCollector(collectType, collectCount);
- * adapter = adapter.asType(newType);
- * return adapter;
- * </pre></blockquote>
- * @param target the method handle to invoke after argument collection
- * @param newType the expected type of the new method handle
- * @return a method handle which collects some trailing argument
- * into an array, before calling the original method handle
- */
- /*non-public*/ static
- MethodHandle collectArguments(MethodHandle target, MethodType newType) {
- MethodType oldType = target.type();
- int inargs = newType.parameterCount();
- int outargs = oldType.parameterCount();
- int collectPos = outargs - 1;
- int numCollect = (inargs - collectPos);
- if (collectPos < 0 || numCollect < 0)
- throw newIllegalArgumentException("wrong number of arguments");
- MethodHandle res = MethodHandleImpl.collectArguments(target, newType, collectPos, null);
- if (res == null) {
- throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
- }
- return res;
- }
-
- /**
- * Produces a method handle of the requested return type which returns the given
- * constant value every time it is invoked.
- * <p>
- * Before the method handle is returned, the passed-in value is converted to the requested type.
- * If the requested type is primitive, widening primitive conversions are attempted,
- * else reference conversions are attempted.
- * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)},
- * unless the type is {@code void}, in which case it is {@code identity(type)}.
- * @param type the return type of the desired method handle
- * @param value the value to return
- * @return a method handle of the given return type and no arguments, which always returns the given value
- * @throws NullPointerException if the {@code type} argument is null
- * @throws ClassCastException if the value cannot be converted to the required return type
- * @throws IllegalArgumentException if the given type is {@code void.class}
- */
- public static
- MethodHandle constant(Class<?> type, Object value) {
- if (type.isPrimitive()) {
- if (type == void.class)
- throw newIllegalArgumentException("void type");
- Wrapper w = Wrapper.forPrimitiveType(type);
- return identity(type).bindTo(w.convert(value, type));
- } else {
- return identity(type).bindTo(type.cast(value));
- }
- }
-
- /**
- * Produces a method handle which returns its sole argument when invoked.
- * <p>The identity function for {@code void} takes no arguments and returns no values.
- * @param type the type of the sole parameter and return value of the desired method handle
- * @return a unary method handle which accepts and returns the given type
- * @throws NullPointerException if the argument is null
- * @throws IllegalArgumentException if the given type is {@code void.class}
- */
- public static
- MethodHandle identity(Class<?> type) {
- if (type == void.class)
- throw newIllegalArgumentException("void type");
- else if (type == Object.class)
- return ValueConversions.identity();
- else if (type.isPrimitive())
- return ValueConversions.identity(Wrapper.forPrimitiveType(type));
- else
- return AdapterMethodHandle.makeRetypeRaw(
- MethodType.methodType(type, type), ValueConversions.identity());
- }
-
- /**
- * Produces a method handle which calls the original method handle {@code target},
- * after inserting the given argument(s) at the given position.
- * The formal parameters to {@code target} which will be supplied by those
- * arguments are called <em>bound parameters</em>, because the new method
- * will contain bindings for those parameters take from {@code values}.
- * The type of the new method handle will drop the types for the bound
- * parameters from the original target type, since the new method handle
- * will no longer require those arguments to be supplied by its callers.
- * <p>
- * Each given argument object must match the corresponding bound parameter type.
- * If a bound parameter type is a primitive, the argument object
- * must be a wrapper, and will be unboxed to produce the primitive value.
- * <p>
- * The <i>pos</i> may range between zero and <i>N</i> (inclusively),
- * where <i>N</i> is the number of argument types in resulting method handle
- * (after bound parameter types are dropped).
- * @param target the method handle to invoke after the argument is inserted
- * @param pos where to insert the argument (zero for the first)
- * @param values the series of arguments to insert
- * @return a method handle which inserts an additional argument,
- * before calling the original method handle
- * @throws NullPointerException if the {@code target} argument or the {@code values} array is null
- * @see MethodHandle#bindTo
- */
- public static
- MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
- int insCount = values.length;
- MethodType oldType = target.type();
- ArrayList<Class<?>> ptypes =
- new ArrayList<Class<?>>(oldType.parameterList());
- int outargs = oldType.parameterCount();
- int inargs = outargs - insCount;
- if (inargs < 0)
- throw newIllegalArgumentException("too many values to insert");
- if (pos < 0 || pos > inargs)
- throw newIllegalArgumentException("no argument type to append");
- MethodHandle result = target;
- for (int i = 0; i < insCount; i++) {
- Object value = values[i];
- Class<?> valueType = oldType.parameterType(pos+i);
- value = checkValue(valueType, value);
- if (pos == 0 && !valueType.isPrimitive()) {
- // At least for now, make bound method handles a special case.
- MethodHandle bmh = MethodHandleImpl.bindReceiver(result, value);
- if (bmh != null) {
- result = bmh;
- continue;
- }
- // else fall through to general adapter machinery
- }
- result = MethodHandleImpl.bindArgument(result, pos, value);
- }
- return result;
- }
-
- /**
- * Produces a method handle which calls the original method handle,
- * after dropping the given argument(s) at the given position.
- * The type of the new method handle will insert the given argument
- * type(s), at that position, into the original handle's type.
- * <p>
- * The <i>pos</i> may range between zero and <i>N</i>,
- * where <i>N</i> is the number of argument types in <i>target</i>,
- * meaning to drop the first or last argument (respectively),
- * or an argument somewhere in between.
- * <p>
- * <b>Example:</b>
- * <p><blockquote><pre>
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-...
-MethodHandle cat = lookup().findVirtual(String.class,
- "concat", methodType(String.class, String.class));
-assertEquals("xy", (String) cat.invokeExact("x", "y"));
-MethodHandle d0 = dropArguments(cat, 0, String.class);
-assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
-MethodHandle d1 = dropArguments(cat, 1, String.class);
-assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
-MethodHandle d2 = dropArguments(cat, 2, String.class);
-assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
-MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
-assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
- * </pre></blockquote>
- * @param target the method handle to invoke after the arguments are dropped
- * @param valueTypes the type(s) of the argument(s) to drop
- * @param pos position of first argument to drop (zero for the leftmost)
- * @return a method handle which drops arguments of the given types,
- * before calling the original method handle
- * @throws NullPointerException if the {@code target} argument is null,
- * or if the {@code valueTypes} list or any of its elements is null
- * @throws IllegalArgumentException if any of the {@code valueTypes} is {@code void.class}
- */
- public static
- MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
- if (valueTypes.size() == 0) return target;
- MethodType oldType = target.type();
- int outargs = oldType.parameterCount();
- int inargs = outargs + valueTypes.size();
- if (pos < 0 || pos >= inargs)
- throw newIllegalArgumentException("no argument type to remove");
- ArrayList<Class<?>> ptypes =
- new ArrayList<Class<?>>(oldType.parameterList());
- ptypes.addAll(pos, valueTypes);
- MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
- return MethodHandleImpl.dropArguments(target, newType, pos);
- }
-
- /**
- * Produces a method handle which calls the original method handle,
- * after dropping the given argument(s) at the given position.
- * The type of the new method handle will insert the given argument
- * type(s), at that position, into the original handle's type.
- * This method is equivalent to the following code:
- * <code>
- * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
- * </code>
- * @param target the method handle to invoke after the arguments are dropped
- * @param valueTypes the type(s) of the argument(s) to drop
- * @param pos position of first argument to drop (zero for the leftmost)
- * @return a method handle which drops arguments of the given types,
- * before calling the original method handle
- * @throws NullPointerException if the {@code target} argument is null,
- * or if the {@code valueTypes} array or any of its elements is null
- * @throws IllegalArgumentException if any of the {@code valueTypes} is {@code void.class}
- */
- public static
- MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
- return dropArguments(target, pos, Arrays.asList(valueTypes));
- }
-
- /**
- * Adapt a target method handle {@code target} by pre-processing
- * one or more of its arguments, each with its own unary filter function,
- * and then calling the target with each pre-processed argument
- * replaced by the result of its corresponding filter function.
- * <p>
- * The pre-processing is performed by one or more method handles,
- * specified in the elements of the {@code filters} array.
- * Null arguments in the array are ignored, and the corresponding arguments left unchanged.
- * (If there are no non-null elements in the array, the original target is returned.)
- * Each filter is applied to the corresponding argument of the adapter.
- * <p>
- * If a filter {@code F} applies to the {@code N}th argument of
- * the method handle, then {@code F} must be a method handle which
- * takes exactly one argument. The type of {@code F}'s sole argument
- * replaces the corresponding argument type of the target
- * in the resulting adapted method handle.
- * The return type of {@code F} must be identical to the corresponding
- * parameter type of the target.
- * <p>
- * It is an error if there are elements of {@code filters}
- * which do not correspond to argument positions in the target.
- * <b>Example:</b>
- * <p><blockquote><pre>
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-...
-MethodHandle cat = lookup().findVirtual(String.class,
- "concat", methodType(String.class, String.class));
-MethodHandle upcase = lookup().findVirtual(String.class,
- "toUpperCase", methodType(String.class));
-assertEquals("xy", (String) cat.invokeExact("x", "y"));
-MethodHandle f0 = filterArguments(cat, 0, upcase);
-assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
-MethodHandle f1 = filterArguments(cat, 1, upcase);
-assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
-MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
-assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
- * </pre></blockquote>
- *
- * @param target the method handle to invoke after arguments are filtered
- * @param pos the position of the first argument to filter
- * @param filters method handles to call initially on filtered arguments
- * @return method handle which incorporates the specified argument filtering logic
- * @throws NullPointerException if the {@code target} argument is null
- * or if the {@code filters} array is null
- * @throws IllegalArgumentException if a non-null element of {@code filters}
- * does not match a corresponding argument type of {@code target} as described above,
- * or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()}
- */
- public static
- MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
- MethodType targetType = target.type();
- MethodHandle adapter = target;
- MethodType adapterType = targetType;
- int maxPos = targetType.parameterCount();
- if (pos + filters.length > maxPos)
- throw newIllegalArgumentException("too many filters");
- int curPos = pos-1; // pre-incremented
- for (MethodHandle filter : filters) {
- curPos += 1;
- if (filter == null) continue; // ignore null elements of filters
- MethodType filterType = filter.type();
- if (filterType.parameterCount() != 1
- || filterType.returnType() != targetType.parameterType(curPos))
- throw newIllegalArgumentException("target and filter types do not match");
- adapterType = adapterType.changeParameterType(curPos, filterType.parameterType(0));
- adapter = MethodHandleImpl.filterArgument(adapter, curPos, filter);
- }
- MethodType midType = adapter.type();
- if (midType != adapterType)
- adapter = MethodHandleImpl.convertArguments(adapter, adapterType, midType, null);
- return adapter;
- }
-
- /**
- * Adapt a target method handle {@code target} by post-processing
- * its return value with a unary filter function.
- * <p>
- * If a filter {@code F} applies to the return value of
- * the target method handle, then {@code F} must be a method handle which
- * takes exactly one argument. The return type of {@code F}
- * replaces the return type of the target
- * in the resulting adapted method handle.
- * The argument type of {@code F} must be identical to the
- * return type of the target.
- * <b>Example:</b>
- * <p><blockquote><pre>
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-...
-MethodHandle cat = lookup().findVirtual(String.class,
- "concat", methodType(String.class, String.class));
-MethodHandle length = lookup().findVirtual(String.class,
- "length", methodType(int.class));
-System.out.println((String) cat.invokeExact("x", "y")); // xy
-MethodHandle f0 = filterReturnValue(cat, length);
-System.out.println((int) f0.invokeExact("x", "y")); // 2
- * </pre></blockquote>
- * @param target the method handle to invoke before filtering the return value
- * @param filter method handle to call on the return value
- * @return method handle which incorporates the specified return value filtering logic
- * @throws NullPointerException if either argument is null
- * @throws IllegalArgumentException if {@code filter}
- * does not match the return type of {@code target} as described above
- */
- public static
- MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
- MethodType targetType = target.type();
- MethodType filterType = filter.type();
- if (filterType.parameterCount() != 1
- || filterType.parameterType(0) != targetType.returnType())
- throw newIllegalArgumentException("target and filter types do not match");
- // result = fold( lambda(retval, arg...) { filter(retval) },
- // lambda( arg...) { target(arg...) } )
- // FIXME: Too many nodes here.
- MethodHandle returner = dropArguments(filter, 1, targetType.parameterList());
- return foldArguments(returner, target);
- }
-
- /**
- * Adapt a target method handle {@code target} by pre-processing
- * some of its arguments, and then calling the target with
- * the result of the pre-processing, plus all original arguments.
- * <p>
- * The pre-processing is performed by a second method handle, the {@code combiner}.
- * The first {@code N} arguments passed to the adapter,
- * are copied to the combiner, which then produces a result.
- * (Here, {@code N} is defined as the parameter count of the adapter.)
- * After this, control passes to the {@code target}, with both the result
- * of the combiner, and all the original incoming arguments.
- * <p>
- * The first argument type of the target must be identical with the
- * return type of the combiner.
- * The resulting adapter is the same type as the target, except that the
- * initial argument type of the target is dropped.
- * <p>
- * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments
- * that either the {@code combiner} or {@code target} does not wish to receive.
- * If some of the incoming arguments are destined only for the combiner,
- * consider using {@link MethodHandle#asCollector asCollector} instead, since those
- * arguments will not need to be live on the stack on entry to the
- * target.)
- * <p>
- * The first argument of the target must be identical with the
- * return value of the combiner.
- * <p> Here is pseudocode for the resulting adapter:
- * <blockquote><pre>
- * // there are N arguments in the A sequence
- * T target(V, A[N]..., B...);
- * V combiner(A...);
- * T adapter(A... a, B... b) {
- * V v = combiner(a...);
- * return target(v, a..., b...);
- * }
- * </pre></blockquote>
- * @param target the method handle to invoke after arguments are combined
- * @param combiner method handle to call initially on the incoming arguments
- * @return method handle which incorporates the specified argument folding logic
- * @throws NullPointerException if either argument is null
- * @throws IllegalArgumentException if the first argument type of
- * {@code target} is not the same as {@code combiner}'s return type,
- * or if the following argument types of {@code target}
- * are not identical with the argument types of {@code combiner}
- */
- public static
- MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
- MethodType targetType = target.type();
- MethodType combinerType = combiner.type();
- int foldArgs = combinerType.parameterCount();
- boolean ok = (targetType.parameterCount() >= 1 + foldArgs);
- if (ok && !combinerType.parameterList().equals(targetType.parameterList().subList(1, foldArgs+1)))
- ok = false;
- if (ok && !combinerType.returnType().equals(targetType.parameterType(0)))
- ok = false;
- if (!ok)
- throw misMatchedTypes("target and combiner types", targetType, combinerType);
- MethodType newType = targetType.dropParameterTypes(0, 1);
- return MethodHandleImpl.foldArguments(target, newType, combiner);
- }
-
- /**
- * Make a method handle which adapts a target method handle,
- * by guarding it with a test, a boolean-valued method handle.
- * If the guard fails, a fallback handle is called instead.
- * All three method handles must have the same corresponding
- * argument and return types, except that the return type
- * of the test must be boolean, and the test is allowed
- * to have fewer arguments than the other two method handles.
- * <p> Here is pseudocode for the resulting adapter:
- * <blockquote><pre>
- * boolean test(A...);
- * T target(A...,B...);
- * T fallback(A...,B...);
- * T adapter(A... a,B... b) {
- * if (test(a...))
- * return target(a..., b...);
- * else
- * return fallback(a..., b...);
- * }
- * </pre></blockquote>
- * Note that the test arguments ({@code a...} in the pseudocode) cannot
- * be modified by execution of the test, and so are passed unchanged
- * from the caller to the target or fallback as appropriate.
- * @param test method handle used for test, must return boolean
- * @param target method handle to call if test passes
- * @param fallback method handle to call if test fails
- * @return method handle which incorporates the specified if/then/else logic
- * @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if {@code test} does not return boolean,
- * or if all three method types do not match (with the return
- * type of {@code test} changed to match that of {@code target}).
- */
- public static
- MethodHandle guardWithTest(MethodHandle test,
- MethodHandle target,
- MethodHandle fallback) {
- MethodType gtype = test.type();
- MethodType ttype = target.type();
- MethodType ftype = fallback.type();
- if (!ttype.equals(ftype))
- throw misMatchedTypes("target and fallback types", ttype, ftype);
- if (gtype.returnType() != boolean.class)
- throw newIllegalArgumentException("guard type is not a predicate "+gtype);
- List<Class<?>> targs = ttype.parameterList();
- List<Class<?>> gargs = gtype.parameterList();
- if (!targs.equals(gargs)) {
- int gpc = gargs.size(), tpc = targs.size();
- if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
- throw misMatchedTypes("target and test types", ttype, gtype);
- test = dropArguments(test, gpc, targs.subList(gpc, tpc));
- gtype = test.type();
- }
- return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
- }
-
- static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
- return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
- }
-
- /**
- * Make a method handle which adapts a target method handle,
- * by running it inside an exception handler.
- * If the target returns normally, the adapter returns that value.
- * If an exception matching the specified type is thrown, the fallback
- * handle is called instead on the exception, plus the original arguments.
- * <p>
- * The target and handler must have the same corresponding
- * argument and return types, except that handler may omit trailing arguments
- * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
- * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
- * <p> Here is pseudocode for the resulting adapter:
- * <blockquote><pre>
- * T target(A..., B...);
- * T handler(ExType, A...);
- * T adapter(A... a, B... b) {
- * try {
- * return target(a..., b...);
- * } catch (ExType ex) {
- * return handler(ex, a...);
- * }
- * }
- * </pre></blockquote>
- * Note that the saved arguments ({@code a...} in the pseudocode) cannot
- * be modified by execution of the target, and so are passed unchanged
- * from the caller to the handler, if the handler is invoked.
- * <p>
- * The target and handler must return the same type, even if the handler
- * always throws. (This might happen, for instance, because the handler
- * is simulating a {@code finally} clause).
- * To create such a throwing handler, compose the handler creation logic
- * with {@link #throwException throwException},
- * in order to create a method handle of the correct return type.
- * @param target method handle to call
- * @param exType the type of exception which the handler will catch
- * @param handler method handle to call if a matching exception is thrown
- * @return method handle which incorporates the specified try/catch logic
- * @throws NullPointerException if any argument is null
- * @throws IllegalArgumentException if {@code handler} does not accept
- * the given exception type, or if the method handle types do
- * not match in their return types and their
- * corresponding parameters
- */
- public static
- MethodHandle catchException(MethodHandle target,
- Class<? extends Throwable> exType,
- MethodHandle handler) {
- MethodType ttype = target.type();
- MethodType htype = handler.type();
- if (htype.parameterCount() < 1 ||
- !htype.parameterType(0).isAssignableFrom(exType))
- throw newIllegalArgumentException("handler does not accept exception type "+exType);
- if (htype.returnType() != ttype.returnType())
- throw misMatchedTypes("target and handler return types", ttype, htype);
- List<Class<?>> targs = ttype.parameterList();
- List<Class<?>> hargs = htype.parameterList();
- hargs = hargs.subList(1, hargs.size()); // omit leading parameter from handler
- if (!targs.equals(hargs)) {
- int hpc = hargs.size(), tpc = targs.size();
- if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
- throw misMatchedTypes("target and handler types", ttype, htype);
- handler = dropArguments(handler, hpc, hargs.subList(hpc, tpc));
- htype = handler.type();
- }
- return MethodHandleImpl.makeGuardWithCatch(target, exType, handler);
- }
-
- /**
- * Produces a method handle which will throw exceptions of the given {@code exType}.
- * The method handle will accept a single argument of {@code exType},
- * and immediately throw it as an exception.
- * The method type will nominally specify a return of {@code returnType}.
- * The return type may be anything convenient: It doesn't matter to the
- * method handle's behavior, since it will never return normally.
- * @return method handle which can throw the given exceptions
- * @throws NullPointerException if either argument is null
- */
- public static
- MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
- return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType));
- }
-
- /**
- * Produces an instance of the given "SAM" interface which redirects
- * its calls to the given method handle.
- * <p>
- * A SAM interface is an interface which declares a single abstract method.
- * When determining the unique abstract method of a SAM interface,
- * the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
- * are disregarded. For example, {@link java.util.Comparator} is a SAM interface,
- * even though it re-declares the {@code Object.equals} method.
- * Also, if the SAM interface has a supertype,
- * the SAM interface may override an inherited method.
- * Any such overrides are respected, and the method handle will be accessible
- * by either the inherited method or the SAM method.
- * In particular, a {@linkplain java.lang.reflect.Method#isBridge bridge method}
- * may be created if the methods have different return types.
- * <p>
- * The type must be public. No additional access checks are performed.
- * <p>
- * The resulting instance of the required SAM type will respond to
- * invocation of the SAM type's single abstract method by calling
- * the given {@code target} on the incoming arguments,
- * and returning or throwing whatever the {@code target}
- * returns or throws. The invocation will be as if by
- * {@code target.invokeGeneric}.
- * The target's type will be checked before the SAM
- * instance is created, as if by a call to {@code asType},
- * which may result in a {@code WrongMethodTypeException}.
- * <p>
- * The wrapper instance will implement the requested SAM interface
- * and its super-types, but no other SAM types.
- * This means that the SAM instance will not unexpectedly
- * pass an {@code instanceof} test for any unrequested type.
- * <p style="font-size:smaller;">
- * <em>Implementation Note:</em>
- * Therefore, each SAM instance must implement a unique SAM type.
- * Implementations may not bundle together
- * multiple SAM types onto single implementation classes
- * in the style of {@link java.awt.AWTEventMulticaster}.
- * <p>
- * The method handle may throw an <em>undeclared exception</em>,
- * which means any checked exception (or other checked throwable)
- * not declared by the SAM type's single abstract method.
- * If this happens, the throwable will be wrapped in an instance of
- * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
- * and thrown in that wrapped form.
- * <p>
- * Like {@link java.lang.Integer#valueOf Integer.valueOf},
- * {@code asInstance} is a factory method whose results are defined
- * by their behavior.
- * It is not guaranteed to return a new instance for every call.
- * <p>
- * Future versions of this API may accept additional types,
- * such as abstract classes with single abstract methods.
- * Future versions of this API may also equip wrapper instances
- * with one or more additional public "marker" interfaces.
- *
- * @param target the method handle to invoke from the wrapper
- * @param samType the desired type of the wrapper, a SAM type
- * @return a correctly-typed wrapper for the given {@code target}
- * @throws NullPointerException if either argument is null
- * @throws IllegalArgumentException if the {@code samType} is not a
- * valid argument to this method
- * @throws WrongMethodTypeException if the {@code target} cannot
- * be converted to the type required by the SAM type
- */
- // Other notes to implementors:
- // <p>
- // No stable mapping is promised between the SAM type and
- // the implementation class C. Over time, several implementation
- // classes might be used for the same SAM type.
- // <p>
- // If the implementation is able
- // to prove that a wrapper of the required SAM type
- // has already been created for a given
- // method handle, or for another method handle with the
- // same behavior, the implementation may return that wrapper in place of
- // a new wrapper.
- // <p>
- // This method is designed to apply to common use cases
- // where a single method handle must interoperate with
- // an interface that implements a function-like
- // API. Additional variations, such as SAM classes with
- // private constructors, or interfaces with multiple but related
- // entry points, must be covered by hand-written or automatically
- // generated adapter classes.
- //
- public static
- <T> T asInstance(final MethodHandle target, final Class<T> samType) {
- // POC implementation only; violates the above contract several ways
- final Method sam = getSamMethod(samType);
- if (sam == null)
- throw new IllegalArgumentException("not a SAM type: "+samType.getName());
- MethodType samMT = MethodType.methodType(sam.getReturnType(), sam.getParameterTypes());
- MethodHandle checkTarget = target.asType(samMT); // make throw WMT
- checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
- final MethodHandle vaTarget = checkTarget.asSpreader(Object[].class, samMT.parameterCount());
- return samType.cast(Proxy.newProxyInstance(
- samType.getClassLoader(),
- new Class[]{ samType, WrapperInstance.class },
- new InvocationHandler() {
- private Object getArg(String name) {
- if ((Object)name == "getWrapperInstanceTarget") return target;
- if ((Object)name == "getWrapperInstanceType") return samType;
- throw new AssertionError();
- }
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if (method.getDeclaringClass() == WrapperInstance.class)
- return getArg(method.getName());
- if (method.equals(sam))
- return vaTarget.invokeExact(args);
- if (isObjectMethod(method))
- return callObjectMethod(this, method, args);
- throw new InternalError();
- }
- }));
- }
-
- /**
- * Determine if the given object was produced by a call to {@link #asInstance asInstance}.
- * @param x any reference
- * @return true if the reference is not null and points to an object produced by {@code asInstance}
- */
- public static
- boolean isWrapperInstance(Object x) {
- return x instanceof WrapperInstance;
- }
-
- private static WrapperInstance asWrapperInstance(Object x) {
- try {
- if (x != null)
- return (WrapperInstance) x;
- } catch (ClassCastException ex) {
- }
- throw new IllegalArgumentException("not a wrapper instance");
- }
-
- /**
- * Produces or recovers a target method handle which is behaviorally
- * equivalent to the SAM method of this wrapper instance.
- * The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
- * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
- * @param x any reference
- * @return a method handle implementing the SAM method
- * @throws IllegalArgumentException if the reference x is not to a wrapper instance
- */
- public static
- MethodHandle wrapperInstanceTarget(Object x) {
- return asWrapperInstance(x).getWrapperInstanceTarget();
- }
-
- /**
- * Recover the SAM type for which this wrapper instance was created.
- * The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
- * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
- * @param x any reference
- * @return the SAM type for which the wrapper was created
- * @throws IllegalArgumentException if the reference x is not to a wrapper instance
- */
- public static
- Class<?> wrapperInstanceType(Object x) {
- return asWrapperInstance(x).getWrapperInstanceType();
- }
-
- private static
- boolean isObjectMethod(Method m) {
- switch (m.getName()) {
- case "toString":
- return (m.getReturnType() == String.class
- && m.getParameterTypes().length == 0);
- case "hashCode":
- return (m.getReturnType() == int.class
- && m.getParameterTypes().length == 0);
- case "equals":
- return (m.getReturnType() == boolean.class
- && m.getParameterTypes().length == 1
- && m.getParameterTypes()[0] == Object.class);
- }
- return false;
- }
-
- private static
- Object callObjectMethod(Object self, Method m, Object[] args) {
- assert(isObjectMethod(m)) : m;
- switch (m.getName()) {
- case "toString":
- return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
- case "hashCode":
- return System.identityHashCode(self);
- case "equals":
- return (self == args[0]);
- }
- return null;
- }
-
- private static
- Method getSamMethod(Class<?> samType) {
- Method sam = null;
- for (Method m : samType.getMethods()) {
- int mod = m.getModifiers();
- if (Modifier.isAbstract(mod)) {
- if (sam != null && !isObjectMethod(sam))
- return null; // too many abstract methods
- sam = m;
- }
- }
- if (!samType.isInterface() && getSamConstructor(samType) == null)
- return null; // wrong kind of constructor
- return sam;
- }
-
- private static
- Constructor getSamConstructor(Class<?> samType) {
- for (Constructor c : samType.getDeclaredConstructors()) {
- if (c.getParameterTypes().length == 0) {
- int mod = c.getModifiers();
- if (Modifier.isPublic(mod) || Modifier.isProtected(mod))
- return c;
- }
- }
- return null;
- }
-
- /*non-public*/
- static MethodHandle asVarargsCollector(MethodHandle target, Class<?> arrayType) {
- return MethodHandleImpl.asVarargsCollector(target, arrayType);
- }
-}
--- a/jdk/src/share/classes/java/dyn/MethodType.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,841 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import sun.dyn.util.BytecodeDescriptor;
-import static java.dyn.MethodHandleStatics.*;
-
-/**
- * A method type represents the arguments and return type accepted and
- * returned by a method handle, or the arguments and return type passed
- * and expected by a method handle caller. Method types must be properly
- * matched between a method handle and all its callers,
- * and the JVM's operations enforce this matching at, specifically
- * during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact}
- * and {@link MethodHandle#invokeGeneric MethodHandle.invokeGeneric}, and during execution
- * of {@code invokedynamic} instructions.
- * <p>
- * The structure is a return type accompanied by any number of parameter types.
- * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
- * (For ease of exposition, we treat {@code void} as if it were a type.
- * In fact, it denotes the absence of a return type.)
- * <p>
- * All instances of {@code MethodType} are immutable.
- * Two instances are completely interchangeable if they compare equal.
- * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
- * <p>
- * This type can be created only by factory methods.
- * All factory methods may cache values, though caching is not guaranteed.
- * Some factory methods are static, while others are virtual methods which
- * modify precursor method types, e.g., by changing a selected parameter.
- * <p>
- * Factory methods which operate on groups of parameter types
- * are systematically presented in two versions, so that both Java arrays and
- * Java lists can be used to work with groups of parameter types.
- * The query methods {@code parameterArray} and {@code parameterList}
- * also provide a choice between arrays and lists.
- * <p>
- * {@code MethodType} objects are sometimes derived from bytecode instructions
- * such as {@code invokedynamic}, specifically from the type descriptor strings associated
- * with the instructions in a class file's constant pool.
- * <p>
- * Like classes and strings, method types can also be represented directly
- * in a class file's constant pool as constants.
- * A method type may be loaded by an {@code ldc} instruction which refers
- * to a suitable {@code CONSTANT_MethodType} constant pool entry.
- * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
- * For more details, see the <a href="package-summary.html#mtcon">package summary</a>.
- * <p>
- * When the JVM materializes a {@code MethodType} from a descriptor string,
- * all classes named in the descriptor must be accessible, and will be loaded.
- * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
- * This loading may occur at any time before the {@code MethodType} object is first derived.
- * @author John Rose, JSR 292 EG
- */
-public final
-class MethodType implements java.io.Serializable {
- private static final long serialVersionUID = 292L; // {rtype, {ptype...}}
-
- // The rtype and ptypes fields define the structural identity of the method type:
- private final Class<?> rtype;
- private final Class<?>[] ptypes;
-
- // The remaining fields are caches of various sorts:
- private MethodTypeForm form; // erased form, plus cached data about primitives
- private MethodType wrapAlt; // alternative wrapped/unwrapped version
- private Invokers invokers; // cache of handy higher-order adapters
-
- /**
- * Check the given parameters for validity and store them into the final fields.
- */
- private MethodType(Class<?> rtype, Class<?>[] ptypes) {
- checkRtype(rtype);
- checkPtypes(ptypes);
- this.rtype = rtype;
- this.ptypes = ptypes;
- }
-
- /*trusted*/ MethodTypeForm form() { return form; }
- /*trusted*/ Class<?> rtype() { return rtype; }
- /*trusted*/ Class<?>[] ptypes() { return ptypes; }
-
- private static void checkRtype(Class<?> rtype) {
- rtype.equals(rtype); // null check
- }
- private static int checkPtype(Class<?> ptype) {
- ptype.getClass(); //NPE
- if (ptype == void.class)
- throw newIllegalArgumentException("parameter type cannot be void");
- if (ptype == double.class || ptype == long.class) return 1;
- return 0;
- }
- /** Return number of extra slots (count of long/double args). */
- private static int checkPtypes(Class<?>[] ptypes) {
- int slots = 0;
- for (Class<?> ptype : ptypes) {
- slots += checkPtype(ptype);
- }
- checkSlotCount(ptypes.length + slots);
- return slots;
- }
- private static void checkSlotCount(int count) {
- if ((count & 0xFF) != count)
- throw newIllegalArgumentException("bad parameter count "+count);
- }
- private static IndexOutOfBoundsException newIndexOutOfBoundsException(Object num) {
- if (num instanceof Integer) num = "bad index: "+num;
- return new IndexOutOfBoundsException(num.toString());
- }
-
- static final HashMap<MethodType,MethodType> internTable
- = new HashMap<MethodType, MethodType>();
-
- static final Class<?>[] NO_PTYPES = {};
-
- /**
- * Find or create an instance of the given method type.
- * @param rtype the return type
- * @param ptypes the parameter types
- * @return a method type with the given components
- * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
- * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
- */
- public static
- MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
- return makeImpl(rtype, ptypes, false);
- }
-
- /**
- * Finds or creates a method type with the given components.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * @return a method type with the given components
- * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
- * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
- */
- public static
- MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) {
- boolean notrust = false; // random List impl. could return evil ptypes array
- return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust);
- }
-
- /**
- * Finds or creates a method type with the given components.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * The leading parameter type is prepended to the remaining array.
- * @return a method type with the given components
- * @throws NullPointerException if {@code rtype} or {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is null
- * @throws IllegalArgumentException if {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is {@code void.class}
- */
- public static
- MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
- Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
- ptypes1[0] = ptype0;
- System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
- return makeImpl(rtype, ptypes1, true);
- }
-
- /**
- * Finds or creates a method type with the given components.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * The resulting method has no parameter types.
- * @return a method type with the given return value
- * @throws NullPointerException if {@code rtype} is null
- */
- public static
- MethodType methodType(Class<?> rtype) {
- return makeImpl(rtype, NO_PTYPES, true);
- }
-
- /**
- * Finds or creates a method type with the given components.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * The resulting method has the single given parameter type.
- * @return a method type with the given return value and parameter type
- * @throws NullPointerException if {@code rtype} or {@code ptype0} is null
- * @throws IllegalArgumentException if {@code ptype0} is {@code void.class}
- */
- public static
- MethodType methodType(Class<?> rtype, Class<?> ptype0) {
- return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
- }
-
- /**
- * Finds or creates a method type with the given components.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * The resulting method has the same parameter types as {@code ptypes},
- * and the specified return type.
- * @throws NullPointerException if {@code rtype} or {@code ptypes} is null
- */
- public static
- MethodType methodType(Class<?> rtype, MethodType ptypes) {
- return makeImpl(rtype, ptypes.ptypes, true);
- }
-
- /**
- * Sole factory method to find or create an interned method type.
- * @param rtype desired return type
- * @param ptypes desired parameter types
- * @param trusted whether the ptypes can be used without cloning
- * @return the unique method type of the desired structure
- */
- /*trusted*/ static
- MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
- if (ptypes == null || ptypes.length == 0) {
- ptypes = NO_PTYPES; trusted = true;
- }
- MethodType mt1 = new MethodType(rtype, ptypes);
- MethodType mt0;
- synchronized (internTable) {
- mt0 = internTable.get(mt1);
- if (mt0 != null)
- return mt0;
- }
- if (!trusted)
- // defensively copy the array passed in by the user
- mt1 = new MethodType(rtype, ptypes.clone());
- // promote the object to the Real Thing, and reprobe
- MethodTypeForm form = MethodTypeForm.findForm(mt1);
- mt1.form = form;
- if (form.erasedType == mt1) {
- // This is a principal (erased) type; show it to the JVM.
- MethodHandleNatives.init(mt1);
- }
- synchronized (internTable) {
- mt0 = internTable.get(mt1);
- if (mt0 != null)
- return mt0;
- internTable.put(mt1, mt1);
- }
- return mt1;
- }
-
- private static final MethodType[] objectOnlyTypes = new MethodType[20];
-
- /**
- * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * All parameters and the return type will be {@code Object},
- * except the final varargs parameter if any, which will be {@code Object[]}.
- * @param objectArgCount number of parameters (excluding the varargs parameter if any)
- * @param varargs whether there will be a varargs parameter, of type {@code Object[]}
- * @return a totally generic method type, given only its count of parameters and varargs
- * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
- * @see #genericMethodType(int)
- */
- public static
- MethodType genericMethodType(int objectArgCount, boolean varargs) {
- MethodType mt;
- checkSlotCount(objectArgCount);
- int ivarargs = (!varargs ? 0 : 1);
- int ootIndex = objectArgCount*2 + ivarargs;
- if (ootIndex < objectOnlyTypes.length) {
- mt = objectOnlyTypes[ootIndex];
- if (mt != null) return mt;
- }
- Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
- Arrays.fill(ptypes, Object.class);
- if (ivarargs != 0) ptypes[objectArgCount] = Object[].class;
- mt = makeImpl(Object.class, ptypes, true);
- if (ootIndex < objectOnlyTypes.length) {
- objectOnlyTypes[ootIndex] = mt; // cache it here also!
- }
- return mt;
- }
-
- /**
- * Finds or creates a method type whose components are all {@code Object}.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * All parameters and the return type will be Object.
- * @param objectArgCount number of parameters
- * @return a totally generic method type, given only its count of parameters
- * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
- * @see #genericMethodType(int, boolean)
- */
- public static
- MethodType genericMethodType(int objectArgCount) {
- return genericMethodType(objectArgCount, false);
- }
-
- /**
- * Finds or creates a method type with a single different parameter type.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * @param num the index (zero-based) of the parameter type to change
- * @param nptype a new parameter type to replace the old one with
- * @return the same type, except with the selected parameter changed
- * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
- * @throws IllegalArgumentException if {@code nptype} is {@code void.class}
- * @throws NullPointerException if {@code nptype} is null
- */
- public MethodType changeParameterType(int num, Class<?> nptype) {
- if (parameterType(num) == nptype) return this;
- checkPtype(nptype);
- Class<?>[] nptypes = ptypes.clone();
- nptypes[num] = nptype;
- return makeImpl(rtype, nptypes, true);
- }
-
- /**
- * Finds or creates a method type with additional parameter types.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * @param num the position (zero-based) of the inserted parameter type(s)
- * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
- * @return the same type, except with the selected parameter(s) inserted
- * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
- * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
- * or if the resulting method type would have more than 255 parameter slots
- * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
- */
- public MethodType insertParameterTypes(int num, Class<?>... ptypesToInsert) {
- int len = ptypes.length;
- if (num < 0 || num > len)
- throw newIndexOutOfBoundsException(num);
- int ins = checkPtypes(ptypesToInsert);
- checkSlotCount(parameterSlotCount() + ptypesToInsert.length + ins);
- int ilen = ptypesToInsert.length;
- if (ilen == 0) return this;
- Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+ilen);
- System.arraycopy(nptypes, num, nptypes, num+ilen, len-num);
- System.arraycopy(ptypesToInsert, 0, nptypes, num, ilen);
- return makeImpl(rtype, nptypes, true);
- }
-
- /**
- * Finds or creates a method type with additional parameter types.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
- * @return the same type, except with the selected parameter(s) appended
- * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
- * or if the resulting method type would have more than 255 parameter slots
- * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
- */
- public MethodType appendParameterTypes(Class<?>... ptypesToInsert) {
- return insertParameterTypes(parameterCount(), ptypesToInsert);
- }
-
- /**
- * Finds or creates a method type with additional parameter types.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * @param num the position (zero-based) of the inserted parameter type(s)
- * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
- * @return the same type, except with the selected parameter(s) inserted
- * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
- * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
- * or if the resulting method type would have more than 255 parameter slots
- * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
- */
- public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
- return insertParameterTypes(num, ptypesToInsert.toArray(NO_PTYPES));
- }
-
- /**
- * Finds or creates a method type with additional parameter types.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
- * @return the same type, except with the selected parameter(s) appended
- * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
- * or if the resulting method type would have more than 255 parameter slots
- * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
- */
- public MethodType appendParameterTypes(List<Class<?>> ptypesToInsert) {
- return insertParameterTypes(parameterCount(), ptypesToInsert);
- }
-
- /**
- * Finds or creates a method type with some parameter types omitted.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * @param start the index (zero-based) of the first parameter type to remove
- * @param end the index (greater than {@code start}) of the first parameter type after not to remove
- * @return the same type, except with the selected parameter(s) removed
- * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
- * or if {@code end} is negative or greater than {@code parameterCount()}
- * or if {@code start} is greater than {@code end}
- */
- public MethodType dropParameterTypes(int start, int end) {
- int len = ptypes.length;
- if (!(0 <= start && start <= end && end <= len))
- throw newIndexOutOfBoundsException("start="+start+" end="+end);
- if (start == end) return this;
- Class<?>[] nptypes;
- if (start == 0) {
- if (end == len) {
- // drop all parameters
- nptypes = NO_PTYPES;
- } else {
- // drop initial parameter(s)
- nptypes = Arrays.copyOfRange(ptypes, end, len);
- }
- } else {
- if (end == len) {
- // drop trailing parameter(s)
- nptypes = Arrays.copyOfRange(ptypes, 0, start);
- } else {
- int tail = len - end;
- nptypes = Arrays.copyOfRange(ptypes, 0, start + tail);
- System.arraycopy(ptypes, end, nptypes, start, tail);
- }
- }
- return makeImpl(rtype, nptypes, true);
- }
-
- /**
- * Finds or creates a method type with a different return type.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * @param nrtype a return parameter type to replace the old one with
- * @return the same type, except with the return type change
- * @throws NullPointerException if {@code nrtype} is null
- */
- public MethodType changeReturnType(Class<?> nrtype) {
- if (returnType() == nrtype) return this;
- return makeImpl(nrtype, ptypes, true);
- }
-
- /**
- * Reports if this type contains a primitive argument or return value.
- * The return type {@code void} counts as a primitive.
- * @return true if any of the types are primitives
- */
- public boolean hasPrimitives() {
- return form.hasPrimitives();
- }
-
- /**
- * Reports if this type contains a wrapper argument or return value.
- * Wrappers are types which box primitive values, such as {@link Integer}.
- * The reference type {@code java.lang.Void} counts as a wrapper.
- * @return true if any of the types are wrappers
- */
- public boolean hasWrappers() {
- return unwrap() != this;
- }
-
- /**
- * Erases all reference types to {@code Object}.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * All primitive types (including {@code void}) will remain unchanged.
- * @return a version of the original type with all reference types replaced
- */
- public MethodType erase() {
- return form.erasedType();
- }
-
- /**
- * Converts all types, both reference and primitive, to {@code Object}.
- * Convenience method for {@link #genericMethodType(int) genericMethodType}.
- * The expression {@code type.wrap().erase()} produces the same value
- * as {@code type.generic()}.
- * @return a version of the original type with all types replaced
- */
- public MethodType generic() {
- return genericMethodType(parameterCount());
- }
-
- /**
- * Converts all primitive types to their corresponding wrapper types.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * All reference types (including wrapper types) will remain unchanged.
- * A {@code void} return type is changed to the type {@code java.lang.Void}.
- * The expression {@code type.wrap().erase()} produces the same value
- * as {@code type.generic()}.
- * @return a version of the original type with all primitive types replaced
- */
- public MethodType wrap() {
- return hasPrimitives() ? wrapWithPrims(this) : this;
- }
-
- /**
- * Convert all wrapper types to their corresponding primitive types.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * All primitive types (including {@code void}) will remain unchanged.
- * A return type of {@code java.lang.Void} is changed to {@code void}.
- * @return a version of the original type with all wrapper types replaced
- */
- public MethodType unwrap() {
- MethodType noprims = !hasPrimitives() ? this : wrapWithPrims(this);
- return unwrapWithNoPrims(noprims);
- }
-
- private static MethodType wrapWithPrims(MethodType pt) {
- assert(pt.hasPrimitives());
- MethodType wt = pt.wrapAlt;
- if (wt == null) {
- // fill in lazily
- wt = MethodTypeForm.canonicalize(pt, MethodTypeForm.WRAP, MethodTypeForm.WRAP);
- assert(wt != null);
- pt.wrapAlt = wt;
- }
- return wt;
- }
-
- private static MethodType unwrapWithNoPrims(MethodType wt) {
- assert(!wt.hasPrimitives());
- MethodType uwt = wt.wrapAlt;
- if (uwt == null) {
- // fill in lazily
- uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP);
- if (uwt == null)
- uwt = wt; // type has no wrappers or prims at all
- wt.wrapAlt = uwt;
- }
- return uwt;
- }
-
- /**
- * Returns the parameter type at the specified index, within this method type.
- * @param num the index (zero-based) of the desired parameter type
- * @return the selected parameter type
- * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
- */
- public Class<?> parameterType(int num) {
- return ptypes[num];
- }
- /**
- * Returns the number of parameter types in this method type.
- * @return the number of parameter types
- */
- public int parameterCount() {
- return ptypes.length;
- }
- /**
- * Returns the return type of this method type.
- * @return the return type
- */
- public Class<?> returnType() {
- return rtype;
- }
-
- /**
- * Presents the parameter types as a list (a convenience method).
- * The list will be immutable.
- * @return the parameter types (as an immutable list)
- */
- public List<Class<?>> parameterList() {
- return Collections.unmodifiableList(Arrays.asList(ptypes));
- }
-
- /**
- * Presents the parameter types as an array (a convenience method).
- * Changes to the array will not result in changes to the type.
- * @return the parameter types (as a fresh copy if necessary)
- */
- public Class<?>[] parameterArray() {
- return ptypes.clone();
- }
-
- /**
- * Compares the specified object with this type for equality.
- * That is, it returns <tt>true</tt> if and only if the specified object
- * is also a method type with exactly the same parameters and return type.
- * @param x object to compare
- * @see Object#equals(Object)
- */
- @Override
- public boolean equals(Object x) {
- return this == x || x instanceof MethodType && equals((MethodType)x);
- }
-
- private boolean equals(MethodType that) {
- return this.rtype == that.rtype
- && Arrays.equals(this.ptypes, that.ptypes);
- }
-
- /**
- * Returns the hash code value for this method type.
- * It is defined to be the same as the hashcode of a List
- * whose elements are the return type followed by the
- * parameter types.
- * @return the hash code value for this method type
- * @see Object#hashCode()
- * @see #equals(Object)
- * @see List#hashCode()
- */
- @Override
- public int hashCode() {
- int hashCode = 31 + rtype.hashCode();
- for (Class<?> ptype : ptypes)
- hashCode = 31*hashCode + ptype.hashCode();
- return hashCode;
- }
-
- /**
- * Returns a string representation of the method type,
- * of the form {@code "(PT0,PT1...)RT"}.
- * The string representation of a method type is a
- * parenthesis enclosed, comma separated list of type names,
- * followed immediately by the return type.
- * <p>
- * Each type is represented by its
- * {@link java.lang.Class#getSimpleName simple name}.
- */
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("(");
- for (int i = 0; i < ptypes.length; i++) {
- if (i > 0) sb.append(",");
- sb.append(ptypes[i].getSimpleName());
- }
- sb.append(")");
- sb.append(rtype.getSimpleName());
- return sb.toString();
- }
-
- /// Queries which have to do with the bytecode architecture
-
- /** Reports the number of JVM stack slots required to invoke a method
- * of this type. Note that (for historic reasons) the JVM requires
- * a second stack slot to pass long and double arguments.
- * So this method returns {@link #parameterCount() parameterCount} plus the
- * number of long and double parameters (if any).
- * <p>
- * This method is included for the benfit of applications that must
- * generate bytecodes that process method handles and invokedynamic.
- * @return the number of JVM stack slots for this type's parameters
- */
- /*non-public*/ int parameterSlotCount() {
- return form.parameterSlotCount();
- }
-
- /*non-public*/ Invokers invokers() {
- Invokers inv = invokers;
- if (inv != null) return inv;
- invokers = inv = new Invokers(this);
- return inv;
- }
-
- /** Reports the number of JVM stack slots which carry all parameters including and after
- * the given position, which must be in the range of 0 to
- * {@code parameterCount} inclusive. Successive parameters are
- * more shallowly stacked, and parameters are indexed in the bytecodes
- * according to their trailing edge. Thus, to obtain the depth
- * in the outgoing call stack of parameter {@code N}, obtain
- * the {@code parameterSlotDepth} of its trailing edge
- * at position {@code N+1}.
- * <p>
- * Parameters of type {@code long} and {@code double} occupy
- * two stack slots (for historical reasons) and all others occupy one.
- * Therefore, the number returned is the number of arguments
- * <em>including</em> and <em>after</em> the given parameter,
- * <em>plus</em> the number of long or double arguments
- * at or after after the argument for the given parameter.
- * <p>
- * This method is included for the benfit of applications that must
- * generate bytecodes that process method handles and invokedynamic.
- * @param num an index (zero-based, inclusive) within the parameter types
- * @return the index of the (shallowest) JVM stack slot transmitting the
- * given parameter
- * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
- */
- /*non-public*/ int parameterSlotDepth(int num) {
- if (num < 0 || num > ptypes.length)
- parameterType(num); // force a range check
- return form.parameterToArgSlot(num-1);
- }
-
- /** Reports the number of JVM stack slots required to receive a return value
- * from a method of this type.
- * If the {@link #returnType() return type} is void, it will be zero,
- * else if the return type is long or double, it will be two, else one.
- * <p>
- * This method is included for the benfit of applications that must
- * generate bytecodes that process method handles and invokedynamic.
- * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
- * Will be removed for PFD.
- */
- /*non-public*/ int returnSlotCount() {
- return form.returnSlotCount();
- }
-
- /**
- * Find or create an instance of a method type, given the spelling of its bytecode descriptor.
- * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
- * Any class or interface name embedded in the descriptor string
- * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
- * on the given loader (or if it is null, on the system class loader).
- * <p>
- * Note that it is possible to encounter method types which cannot be
- * constructed by this method, because their component types are
- * not all reachable from a common class loader.
- * <p>
- * This method is included for the benfit of applications that must
- * generate bytecodes that process method handles and {@code invokedynamic}.
- * @param descriptor a bytecode-level type descriptor string "(T...)T"
- * @param loader the class loader in which to look up the types
- * @return a method type matching the bytecode-level type descriptor
- * @throws IllegalArgumentException if the string is not well-formed
- * @throws TypeNotPresentException if a named type cannot be found
- */
- public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
- throws IllegalArgumentException, TypeNotPresentException
- {
- List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
- Class<?> rtype = types.remove(types.size() - 1);
- Class<?>[] ptypes = types.toArray(NO_PTYPES);
- return makeImpl(rtype, ptypes, true);
- }
-
- /**
- * Produces a bytecode descriptor representation of the method type.
- * <p>
- * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
- * Two distinct classes which share a common name but have different class loaders
- * will appear identical when viewed within descriptor strings.
- * <p>
- * This method is included for the benfit of applications that must
- * generate bytecodes that process method handles and {@code invokedynamic}.
- * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
- * because the latter requires a suitable class loader argument.
- * @return the bytecode type descriptor representation
- */
- public String toMethodDescriptorString() {
- return BytecodeDescriptor.unparse(this);
- }
-
- /// Serialization.
-
- /**
- * There are no serializable fields for {@code MethodType}.
- */
- private static final java.io.ObjectStreamField[] serialPersistentFields = { };
-
- /**
- * Save the {@code MethodType} instance to a stream.
- *
- * @serialData
- * For portability, the serialized format does not refer to named fields.
- * Instead, the return type and parameter type arrays are written directly
- * from the {@code writeObject} method, using two calls to {@code s.writeObject}
- * as follows:
- * <blockquote><pre>
-s.writeObject(this.returnType());
-s.writeObject(this.parameterArray());
- * </pre></blockquote>
- * <p>
- * The deserialized field values are checked as if they were
- * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
- * For example, null values, or {@code void} parameter types,
- * will lead to exceptions during deserialization.
- * @param the stream to write the object to
- */
- private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
- s.defaultWriteObject(); // requires serialPersistentFields to be an empty array
- s.writeObject(returnType());
- s.writeObject(parameterArray());
- }
-
- /**
- * Reconstitute the {@code MethodType} instance from a stream (that is,
- * deserialize it).
- * This instance is a scratch object with bogus final fields.
- * It provides the parameters to the factory method called by
- * {@link #readResolve readResolve}.
- * After that call it is discarded.
- * @param the stream to read the object from
- * @see #MethodType()
- * @see #readResolve
- * @see #writeObject
- */
- private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
- s.defaultReadObject(); // requires serialPersistentFields to be an empty array
-
- Class<?> returnType = (Class<?>) s.readObject();
- Class<?>[] parameterArray = (Class<?>[]) s.readObject();
-
- // Probably this object will never escape, but let's check
- // the field values now, just to be sure.
- checkRtype(returnType);
- checkPtypes(parameterArray);
-
- parameterArray = parameterArray.clone(); // make sure it is unshared
- MethodType_init(returnType, parameterArray);
- }
-
- /**
- * For serialization only.
- * Sets the final fields to null, pending {@code Unsafe.putObject}.
- */
- private MethodType() {
- this.rtype = null;
- this.ptypes = null;
- }
- private void MethodType_init(Class<?> rtype, Class<?>[] ptypes) {
- // In order to communicate these values to readResolve, we must
- // store them into the implementation-specific final fields.
- checkRtype(rtype);
- checkPtypes(ptypes);
- unsafe.putObject(this, rtypeOffset, rtype);
- unsafe.putObject(this, ptypesOffset, ptypes);
- }
-
- // Support for resetting final fields while deserializing
- private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
- private static final long rtypeOffset, ptypesOffset;
- static {
- try {
- rtypeOffset = unsafe.objectFieldOffset
- (MethodType.class.getDeclaredField("rtype"));
- ptypesOffset = unsafe.objectFieldOffset
- (MethodType.class.getDeclaredField("ptypes"));
- } catch (Exception ex) {
- throw new Error(ex);
- }
- }
-
- /**
- * Resolves and initializes a {@code MethodType} object
- * after serialization.
- * @return the fully initialized {@code MethodType} object
- */
- private Object readResolve() {
- // Do not use a trusted path for deserialization:
- //return makeImpl(rtype, ptypes, true);
- // Verify all operands, and make sure ptypes is unshared:
- return methodType(rtype, ptypes);
- }
-}
--- a/jdk/src/share/classes/java/dyn/MethodTypeForm.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,476 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.util.Wrapper;
-import static java.dyn.MethodHandleStatics.*;
-
-/**
- * Shared information for a group of method types, which differ
- * only by reference types, and therefore share a common erasure
- * and wrapping.
- * <p>
- * For an empirical discussion of the structure of method types,
- * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
- * the thread "Avoiding Boxing" on jvm-languages</a>.
- * There are approximately 2000 distinct erased method types in the JDK.
- * There are a little over 10 times that number of unerased types.
- * No more than half of these are likely to be loaded at once.
- * @author John Rose
- */
-class MethodTypeForm {
- final int[] argToSlotTable, slotToArgTable;
- final long argCounts; // packed slot & value counts
- final long primCounts; // packed prim & double counts
- final int vmslots; // total number of parameter slots
- final MethodType erasedType; // the canonical erasure
-
- /*lazy*/ MethodType primsAsBoxes; // replace prims by wrappers
- /*lazy*/ MethodType primArgsAsBoxes; // wrap args only; make raw return
- /*lazy*/ MethodType primsAsInts; // replace prims by int/long
- /*lazy*/ MethodType primsAsLongs; // replace prims by long
- /*lazy*/ MethodType primsAtEnd; // reorder primitives to the end
-
- // Cached adapter information:
- /*lazy*/ ToGeneric toGeneric; // convert cs. with prims to w/o
- /*lazy*/ FromGeneric fromGeneric; // convert cs. w/o prims to with
- /*lazy*/ SpreadGeneric[] spreadGeneric; // expand one argument to many
- /*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly
- /*lazy*/ MethodHandle genericInvoker; // hook for invokeGeneric
-
- public MethodType erasedType() {
- return erasedType;
- }
-
- protected MethodTypeForm(MethodType erasedType) {
- this.erasedType = erasedType;
-
- Class<?>[] ptypes = erasedType.ptypes();
- int ptypeCount = ptypes.length;
- int pslotCount = ptypeCount; // temp. estimate
- int rtypeCount = 1; // temp. estimate
- int rslotCount = 1; // temp. estimate
-
- int[] argToSlotTab = null, slotToArgTab = null;
-
- // Walk the argument types, looking for primitives.
- int pac = 0, lac = 0, prc = 0, lrc = 0;
- Class<?> epts[] = ptypes;
- for (int i = 0; i < epts.length; i++) {
- Class<?> pt = epts[i];
- if (pt != Object.class) {
- assert(pt.isPrimitive());
- ++pac;
- if (hasTwoArgSlots(pt)) ++lac;
- }
- }
- pslotCount += lac; // #slots = #args + #longs
- Class<?> rt = erasedType.returnType();
- if (rt != Object.class) {
- ++prc; // even void.class counts as a prim here
- if (hasTwoArgSlots(rt)) ++lrc;
- // adjust #slots, #args
- if (rt == void.class)
- rtypeCount = rslotCount = 0;
- else
- rslotCount += lrc;
- }
- if (lac != 0) {
- int slot = ptypeCount + lac;
- slotToArgTab = new int[slot+1];
- argToSlotTab = new int[1+ptypeCount];
- argToSlotTab[0] = slot; // argument "-1" is past end of slots
- for (int i = 0; i < epts.length; i++) {
- Class<?> pt = epts[i];
- if (hasTwoArgSlots(pt)) --slot;
- --slot;
- slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
- argToSlotTab[1+i] = slot;
- }
- assert(slot == 0); // filled the table
- }
- this.primCounts = pack(lrc, prc, lac, pac);
- this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
- if (slotToArgTab == null) {
- int slot = ptypeCount; // first arg is deepest in stack
- slotToArgTab = new int[slot+1];
- argToSlotTab = new int[1+ptypeCount];
- argToSlotTab[0] = slot; // argument "-1" is past end of slots
- for (int i = 0; i < ptypeCount; i++) {
- --slot;
- slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
- argToSlotTab[1+i] = slot;
- }
- }
- this.argToSlotTable = argToSlotTab;
- this.slotToArgTable = slotToArgTab;
-
- if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments");
-
- // send a few bits down to the JVM:
- this.vmslots = parameterSlotCount();
-
- // short circuit some no-op canonicalizations:
- if (!hasPrimitives()) {
- primsAsBoxes = erasedType;
- primArgsAsBoxes = erasedType;
- primsAsInts = erasedType;
- primsAsLongs = erasedType;
- primsAtEnd = erasedType;
- }
- }
-
- /** Turn all primitive types to corresponding wrapper types.
- */
- public MethodType primsAsBoxes() {
- MethodType ct = primsAsBoxes;
- if (ct != null) return ct;
- MethodType t = erasedType;
- ct = canonicalize(erasedType, WRAP, WRAP);
- if (ct == null) ct = t; // no prims to box
- return primsAsBoxes = ct;
- }
-
- /** Turn all primitive argument types to corresponding wrapper types.
- * Subword and void return types are promoted to int.
- */
- public MethodType primArgsAsBoxes() {
- MethodType ct = primArgsAsBoxes;
- if (ct != null) return ct;
- MethodType t = erasedType;
- ct = canonicalize(erasedType, RAW_RETURN, WRAP);
- if (ct == null) ct = t; // no prims to box
- return primArgsAsBoxes = ct;
- }
-
- /** Turn all primitive types to either int or long.
- * Floating point return types are not changed, because
- * they may require special calling sequences.
- * A void return value is turned to int.
- */
- public MethodType primsAsInts() {
- MethodType ct = primsAsInts;
- if (ct != null) return ct;
- MethodType t = erasedType;
- ct = canonicalize(t, RAW_RETURN, INTS);
- if (ct == null) ct = t; // no prims to int-ify
- return primsAsInts = ct;
- }
-
- /** Turn all primitive types to either int or long.
- * Floating point return types are not changed, because
- * they may require special calling sequences.
- * A void return value is turned to int.
- */
- public MethodType primsAsLongs() {
- MethodType ct = primsAsLongs;
- if (ct != null) return ct;
- MethodType t = erasedType;
- ct = canonicalize(t, RAW_RETURN, LONGS);
- if (ct == null) ct = t; // no prims to int-ify
- return primsAsLongs = ct;
- }
-
- /** Stably sort parameters into 3 buckets: ref, int, long. */
- public MethodType primsAtEnd() {
- MethodType ct = primsAtEnd;
- if (ct != null) return ct;
- MethodType t = erasedType;
-
- int pac = primitiveParameterCount();
- if (pac == 0)
- return primsAtEnd = t;
-
- int argc = parameterCount();
- int lac = longPrimitiveParameterCount();
- if (pac == argc && (lac == 0 || lac == argc))
- return primsAtEnd = t;
-
- // known to have a mix of 2 or 3 of ref, int, long
- int[] reorder = primsAtEndOrder(t);
- ct = reorderParameters(t, reorder, null);
- //System.out.println("t="+t+" / reorder="+java.util.Arrays.toString(reorder)+" => "+ct);
- return primsAtEnd = ct;
- }
-
- /** Compute a new ordering of parameters so that all references
- * are before all ints or longs, and all ints are before all longs.
- * For this ordering, doubles count as longs, and all other primitive
- * values count as ints.
- * As a special case, if the parameters are already in the specified
- * order, this method returns a null reference, rather than an array
- * specifying a null permutation.
- * <p>
- * For example, the type {@code (int,boolean,int,Object,String)void}
- * produces the order {@code {3,4,0,1,2}}, the type
- * {@code (long,int,String)void} produces {@code {2,1,2}}, and
- * the type {@code (Object,int)Object} produces {@code null}.
- */
- public static int[] primsAtEndOrder(MethodType mt) {
- MethodTypeForm form = mt.form();
- if (form.primsAtEnd == form.erasedType)
- // quick check shows no reordering is necessary
- return null;
-
- int argc = form.parameterCount();
- int[] paramOrder = new int[argc];
-
- // 3-way bucket sort:
- int pac = form.primitiveParameterCount();
- int lac = form.longPrimitiveParameterCount();
- int rfill = 0, ifill = argc - pac, lfill = argc - lac;
-
- Class<?>[] ptypes = mt.ptypes();
- boolean changed = false;
- for (int i = 0; i < ptypes.length; i++) {
- Class<?> pt = ptypes[i];
- int ord;
- if (!pt.isPrimitive()) ord = rfill++;
- else if (!hasTwoArgSlots(pt)) ord = ifill++;
- else ord = lfill++;
- if (ord != i) changed = true;
- assert(paramOrder[ord] == 0);
- paramOrder[ord] = i;
- }
- assert(rfill == argc - pac && ifill == argc - lac && lfill == argc);
- if (!changed) {
- form.primsAtEnd = form.erasedType;
- return null;
- }
- return paramOrder;
- }
-
- /** Put the existing parameters of mt into a new order, given by newParamOrder.
- * The third argument is logically appended to mt.parameterArray,
- * so that elements of newParamOrder can index either pre-existing or
- * new parameter types.
- */
- public static MethodType reorderParameters(MethodType mt, int[] newParamOrder, Class<?>[] moreParams) {
- if (newParamOrder == null) return mt; // no-op reordering
- Class<?>[] ptypes = mt.ptypes();
- Class<?>[] ntypes = new Class<?>[newParamOrder.length];
- int maxParam = ptypes.length + (moreParams == null ? 0 : moreParams.length);
- boolean changed = (ntypes.length != ptypes.length);
- for (int i = 0; i < newParamOrder.length; i++) {
- int param = newParamOrder[i];
- if (param != i) changed = true;
- Class<?> nt;
- if (param < ptypes.length) nt = ptypes[param];
- else if (param == maxParam) nt = mt.returnType();
- else nt = moreParams[param - ptypes.length];
- ntypes[i] = nt;
- }
- if (!changed) return mt;
- return MethodType.makeImpl(mt.returnType(), ntypes, true);
- }
-
- private static boolean hasTwoArgSlots(Class<?> type) {
- return type == long.class || type == double.class;
- }
-
- private static long pack(int a, int b, int c, int d) {
- assert(((a|b|c|d) & ~0xFFFF) == 0);
- long hw = ((a << 16) | b), lw = ((c << 16) | d);
- return (hw << 32) | lw;
- }
- private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
- assert(word <= 3);
- return (char)(packed >> ((3-word) * 16));
- }
-
- public int parameterCount() { // # outgoing values
- return unpack(argCounts, 3);
- }
- public int parameterSlotCount() { // # outgoing interpreter slots
- return unpack(argCounts, 2);
- }
- public int returnCount() { // = 0 (V), or 1
- return unpack(argCounts, 1);
- }
- public int returnSlotCount() { // = 0 (V), 2 (J/D), or 1
- return unpack(argCounts, 0);
- }
- public int primitiveParameterCount() {
- return unpack(primCounts, 3);
- }
- public int longPrimitiveParameterCount() {
- return unpack(primCounts, 2);
- }
- public int primitiveReturnCount() { // = 0 (obj), or 1
- return unpack(primCounts, 1);
- }
- public int longPrimitiveReturnCount() { // = 1 (J/D), or 0
- return unpack(primCounts, 0);
- }
- public boolean hasPrimitives() {
- return primCounts != 0;
- }
-// public boolean hasNonVoidPrimitives() {
-// if (primCounts == 0) return false;
-// if (primitiveParameterCount() != 0) return true;
-// return (primitiveReturnCount() != 0 && returnCount() != 0);
-// }
- public boolean hasLongPrimitives() {
- return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
- }
- public int parameterToArgSlot(int i) {
- return argToSlotTable[1+i];
- }
- public int argSlotToParameter(int argSlot) {
- // Note: Empty slots are represented by zero in this table.
- // Valid arguments slots contain incremented entries, so as to be non-zero.
- // We return -1 the caller to mean an empty slot.
- return slotToArgTable[argSlot] - 1;
- }
-
- static MethodTypeForm findForm(MethodType mt) {
- MethodType erased = canonicalize(mt, ERASE, ERASE);
- if (erased == null) {
- // It is already erased. Make a new MethodTypeForm.
- return new MethodTypeForm(mt);
- } else {
- // Share the MethodTypeForm with the erased version.
- return erased.form();
- }
- }
-
- /** Codes for {@link #canonicalize(java.lang.Class, int)}.
- * ERASE means change every reference to {@code Object}.
- * WRAP means convert primitives (including {@code void} to their
- * corresponding wrapper types. UNWRAP means the reverse of WRAP.
- * INTS means convert all non-void primitive types to int or long,
- * according to size. LONGS means convert all non-void primitives
- * to long, regardless of size. RAW_RETURN means convert a type
- * (assumed to be a return type) to int if it is smaller than an int,
- * or if it is void.
- */
- public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
-
- /** Canonicalize the types in the given method type.
- * If any types change, intern the new type, and return it.
- * Otherwise return null.
- */
- public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
- Class<?>[] ptypes = mt.ptypes();
- Class<?>[] ptc = MethodTypeForm.canonicalizes(ptypes, howArgs);
- Class<?> rtype = mt.returnType();
- Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet);
- if (ptc == null && rtc == null) {
- // It is already canonical.
- return null;
- }
- // Find the erased version of the method type:
- if (rtc == null) rtc = rtype;
- if (ptc == null) ptc = ptypes;
- return MethodType.makeImpl(rtc, ptc, true);
- }
-
- /** Canonicalize the given return or param type.
- * Return null if the type is already canonicalized.
- */
- static Class<?> canonicalize(Class<?> t, int how) {
- Class<?> ct;
- if (t == Object.class) {
- // no change, ever
- } else if (!t.isPrimitive()) {
- switch (how) {
- case UNWRAP:
- ct = Wrapper.asPrimitiveType(t);
- if (ct != t) return ct;
- break;
- case RAW_RETURN:
- case ERASE:
- return Object.class;
- }
- } else if (t == void.class) {
- // no change, usually
- switch (how) {
- case RAW_RETURN:
- return int.class;
- case WRAP:
- return Void.class;
- }
- } else {
- // non-void primitive
- switch (how) {
- case WRAP:
- return Wrapper.asWrapperType(t);
- case INTS:
- if (t == int.class || t == long.class)
- return null; // no change
- if (t == double.class)
- return long.class;
- return int.class;
- case LONGS:
- if (t == long.class)
- return null; // no change
- return long.class;
- case RAW_RETURN:
- if (t == int.class || t == long.class ||
- t == float.class || t == double.class)
- return null; // no change
- // everything else returns as an int
- return int.class;
- }
- }
- // no change; return null to signify
- return null;
- }
-
- /** Canonicalize each param type in the given array.
- * Return null if all types are already canonicalized.
- */
- static Class<?>[] canonicalizes(Class<?>[] ts, int how) {
- Class<?>[] cs = null;
- for (int imax = ts.length, i = 0; i < imax; i++) {
- Class<?> c = canonicalize(ts[i], how);
- if (c != null) {
- if (cs == null)
- cs = ts.clone();
- cs[i] = c;
- }
- }
- return cs;
- }
-
- /*non-public*/ void notifyGenericMethodType() {
- if (genericInvoker != null) return;
- try {
- // Trigger adapter creation.
- genericInvoker = InvokeGeneric.genericInvokerOf(erasedType);
- } catch (Exception ex) {
- Error err = new InternalError("Exception while resolving invokeGeneric");
- err.initCause(ex);
- throw err;
- }
- }
-
- @Override
- public String toString() {
- return "Form"+erasedType;
- }
-
-}
--- a/jdk/src/share/classes/java/dyn/MutableCallSite.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,280 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * A {@code MutableCallSite} is a {@link CallSite} whose target variable
- * behaves like an ordinary field.
- * An {@code invokedynamic} instruction linked to a {@code MutableCallSite} delegates
- * all calls to the site's current target.
- * The {@linkplain CallSite#dynamicInvoker dynamic invoker} of a mutable call site
- * also delegates each call to the site's current target.
- * <p>
- * Here is an example of a mutable call site which introduces a
- * state variable into a method handle chain.
- * <blockquote><pre>
-MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
-MethodHandle MH_name = name.dynamicInvoker();
-MethodType MT_str2 = MethodType.methodType(String.class, String.class);
-MethodHandle MH_upcase = MethodHandles.lookup()
- .findVirtual(String.class, "toUpperCase", MT_str2);
-MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
-name.setTarget(MethodHandles.constant(String.class, "Rocky"));
-assertEquals("ROCKY", (String) worker1.invokeExact());
-name.setTarget(MethodHandles.constant(String.class, "Fred"));
-assertEquals("FRED", (String) worker1.invokeExact());
-// (mutation can be continued indefinitely)
- * </pre></blockquote>
- * <p>
- * The same call site may be used in several places at once.
- * <blockquote><pre>
-MethodHandle MH_dear = MethodHandles.lookup()
- .findVirtual(String.class, "concat", MT_str2).bindTo(", dear?");
-MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear);
-assertEquals("Fred, dear?", (String) worker2.invokeExact());
-name.setTarget(MethodHandles.constant(String.class, "Wilma"));
-assertEquals("WILMA", (String) worker1.invokeExact());
-assertEquals("Wilma, dear?", (String) worker2.invokeExact());
- * </pre></blockquote>
- * <p>
- * <em>Non-synchronization of target values:</em>
- * A write to a mutable call site's target does not force other threads
- * to become aware of the updated value. Threads which do not perform
- * suitable synchronization actions relative to the updated call site
- * may cache the old target value and delay their use of the new target
- * value indefinitely.
- * (This is a normal consequence of the Java Memory Model as applied
- * to object fields.)
- * <p>
- * The {@link #syncAll syncAll} operation provides a way to force threads
- * to accept a new target value, even if there is no other synchronization.
- * <p>
- * For target values which will be frequently updated, consider using
- * a {@linkplain VolatileCallSite volatile call site} instead.
- * @author John Rose, JSR 292 EG
- */
-public class MutableCallSite extends CallSite {
- /**
- * Creates a blank call site object with the given method type.
- * The initial target is set to a method handle of the given type
- * which will throw an {@link IllegalStateException} if called.
- * <p>
- * The type of the call site is permanently set to the given type.
- * <p>
- * Before this {@code CallSite} object is returned from a bootstrap method,
- * or invoked in some other manner,
- * it is usually provided with a more useful target method,
- * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
- * @param type the method type that this call site will have
- * @throws NullPointerException if the proposed type is null
- */
- public MutableCallSite(MethodType type) {
- super(type);
- }
-
- /**
- * Creates a call site object with an initial target method handle.
- * The type of the call site is permanently set to the initial target's type.
- * @param target the method handle that will be the initial target of the call site
- * @throws NullPointerException if the proposed target is null
- */
- public MutableCallSite(MethodHandle target) {
- super(target);
- }
-
- /**
- * Returns the target method of the call site, which behaves
- * like a normal field of the {@code MutableCallSite}.
- * <p>
- * The interactions of {@code getTarget} with memory are the same
- * as of a read from an ordinary variable, such as an array element or a
- * non-volatile, non-final field.
- * <p>
- * In particular, the current thread may choose to reuse the result
- * of a previous read of the target from memory, and may fail to see
- * a recent update to the target by another thread.
- *
- * @return the linkage state of this call site, a method handle which can change over time
- * @see #setTarget
- */
- @Override public final MethodHandle getTarget() {
- return target;
- }
-
- /**
- * Updates the target method of this call site, as a normal variable.
- * The type of the new target must agree with the type of the old target.
- * <p>
- * The interactions with memory are the same
- * as of a write to an ordinary variable, such as an array element or a
- * non-volatile, non-final field.
- * <p>
- * In particular, unrelated threads may fail to see the updated target
- * until they perform a read from memory.
- * Stronger guarantees can be created by putting appropriate operations
- * into the bootstrap method and/or the target methods used
- * at any given call site.
- *
- * @param newTarget the new target
- * @throws NullPointerException if the proposed new target is null
- * @throws WrongMethodTypeException if the proposed new target
- * has a method type that differs from the previous target
- * @see #getTarget
- */
- @Override public void setTarget(MethodHandle newTarget) {
- checkTargetChange(this.target, newTarget);
- setTargetNormal(newTarget);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final MethodHandle dynamicInvoker() {
- return makeDynamicInvoker();
- }
-
- /**
- * Performs a synchronization operation on each call site in the given array,
- * forcing all other threads to throw away any cached values previously
- * loaded from the target of any of the call sites.
- * <p>
- * This operation does not reverse any calls that have already started
- * on an old target value.
- * (Java supports {@linkplain java.lang.Object#wait() forward time travel} only.)
- * <p>
- * The overall effect is to force all future readers of each call site's target
- * to accept the most recently stored value.
- * ("Most recently" is reckoned relative to the {@code syncAll} itself.)
- * Conversely, the {@code syncAll} call may block until all readers have
- * (somehow) decached all previous versions of each call site's target.
- * <p>
- * To avoid race conditions, calls to {@code setTarget} and {@code syncAll}
- * should generally be performed under some sort of mutual exclusion.
- * Note that reader threads may observe an updated target as early
- * as the {@code setTarget} call that install the value
- * (and before the {@code syncAll} that confirms the value).
- * On the other hand, reader threads may observe previous versions of
- * the target until the {@code syncAll} call returns
- * (and after the {@code setTarget} that attempts to convey the updated version).
- * <p>
- * This operation is likely to be expensive and should be used sparingly.
- * If possible, it should be buffered for batch processing on sets of call sites.
- * <p>
- * If {@code sites} contains a null element,
- * a {@code NullPointerException} will be raised.
- * In this case, some non-null elements in the array may be
- * processed before the method returns abnormally.
- * Which elements these are (if any) is implementation-dependent.
- *
- * <h3>Java Memory Model details</h3>
- * In terms of the Java Memory Model, this operation performs a synchronization
- * action which is comparable in effect to the writing of a volatile variable
- * by the current thread, and an eventual volatile read by every other thread
- * that may access one of the affected call sites.
- * <p>
- * The following effects are apparent, for each individual call site {@code S}:
- * <ul>
- * <li>A new volatile variable {@code V} is created, and written by the current thread.
- * As defined by the JMM, this write is a global synchronization event.
- * <li>As is normal with thread-local ordering of write events,
- * every action already performed by the current thread is
- * taken to happen before the volatile write to {@code V}.
- * (In some implementations, this means that the current thread
- * performs a global release operation.)
- * <li>Specifically, the write to the current target of {@code S} is
- * taken to happen before the volatile write to {@code V}.
- * <li>The volatile write to {@code V} is placed
- * (in an implementation specific manner)
- * in the global synchronization order.
- * <li>Consider an arbitrary thread {@code T} (other than the current thread).
- * If {@code T} executes a synchronization action {@code A}
- * after the volatile write to {@code V} (in the global synchronization order),
- * it is therefore required to see either the current target
- * of {@code S}, or a later write to that target,
- * if it executes a read on the target of {@code S}.
- * (This constraint is called "synchronization-order consistency".)
- * <li>The JMM specifically allows optimizing compilers to elide
- * reads or writes of variables that are known to be useless.
- * Such elided reads and writes have no effect on the happens-before
- * relation. Regardless of this fact, the volatile {@code V}
- * will not be elided, even though its written value is
- * indeterminate and its read value is not used.
- * </ul>
- * Because of the last point, the implementation behaves as if a
- * volatile read of {@code V} were performed by {@code T}
- * immediately after its action {@code A}. In the local ordering
- * of actions in {@code T}, this read happens before any future
- * read of the target of {@code S}. It is as if the
- * implementation arbitrarily picked a read of {@code S}'s target
- * by {@code T}, and forced a read of {@code V} to precede it,
- * thereby ensuring communication of the new target value.
- * <p>
- * As long as the constraints of the Java Memory Model are obeyed,
- * implementations may delay the completion of a {@code syncAll}
- * operation while other threads ({@code T} above) continue to
- * use previous values of {@code S}'s target.
- * However, implementations are (as always) encouraged to avoid
- * livelock, and to eventually require all threads to take account
- * of the updated target.
- *
- * <p style="font-size:smaller;">
- * <em>Discussion:</em>
- * For performance reasons, {@code syncAll} is not a virtual method
- * on a single call site, but rather applies to a set of call sites.
- * Some implementations may incur a large fixed overhead cost
- * for processing one or more synchronization operations,
- * but a small incremental cost for each additional call site.
- * In any case, this operation is likely to be costly, since
- * other threads may have to be somehow interrupted
- * in order to make them notice the updated target value.
- * However, it may be observed that a single call to synchronize
- * several sites has the same formal effect as many calls,
- * each on just one of the sites.
- *
- * <p style="font-size:smaller;">
- * <em>Implementation Note:</em>
- * Simple implementations of {@code MutableCallSite} may use
- * a volatile variable for the target of a mutable call site.
- * In such an implementation, the {@code syncAll} method can be a no-op,
- * and yet it will conform to the JMM behavior documented above.
- *
- * @param sites an array of call sites to be synchronized
- * @throws NullPointerException if the {@code sites} array reference is null
- * or the array contains a null
- */
- public static void syncAll(MutableCallSite[] sites) {
- if (sites.length == 0) return;
- STORE_BARRIER.lazySet(0);
- for (int i = 0; i < sites.length; i++) {
- sites[i].getClass(); // trigger NPE on first null
- }
- // FIXME: NYI
- }
- private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
-}
--- a/jdk/src/share/classes/java/dyn/SpreadGeneric.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,678 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import sun.dyn.util.ValueConversions;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import static java.dyn.MethodHandleStatics.*;
-import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
-
-/**
- * Generic spread adapter.
- * Expands a final argument into multiple (zero or more) arguments, keeping the others the same.
- * @author jrose
- */
-class SpreadGeneric {
- // type for the outgoing call
- private final MethodType targetType;
- // number of arguments to spread
- private final int spreadCount;
- // prototype adapter (clone and customize for each new target!)
- private final Adapter adapter;
- // entry point for adapter (Adapter mh, a...) => ...
- private final MethodHandle entryPoint;
-
- /** Compute and cache information common to all spreading adapters
- * that accept calls of the given (generic) type.
- */
- private SpreadGeneric(MethodType targetType, int spreadCount) {
- assert(targetType == targetType.generic());
- this.targetType = targetType;
- this.spreadCount = spreadCount;
- // the target invoker will generally need casts on reference arguments
- MethodHandle[] ep = { null };
- Adapter ad = findAdapter(this, ep);
- if (ad != null) {
- this.adapter = ad;
- this.entryPoint = ep[0];
- return;
- }
- this.adapter = buildAdapterFromBytecodes(targetType, spreadCount, ep);
- this.entryPoint = ep[0];
- }
-
- /** From targetType remove the last spreadCount arguments, and instead
- * append a simple Object argument.
- */
- static MethodType preSpreadType(MethodType targetType, int spreadCount) {
- @SuppressWarnings("unchecked")
- ArrayList<Class<?>> params = new ArrayList(targetType.parameterList());
- int outargs = params.size();
- params.subList(outargs - spreadCount, outargs).clear();
- params.add(Object.class);
- return MethodType.methodType(targetType.returnType(), params);
- }
-
- MethodHandle makeInstance(MethodHandle target) {
- MethodType type = target.type();
- if (type != targetType) {
- throw new UnsupportedOperationException("NYI type="+type);
- }
- return adapter.makeInstance(this, target);
- }
-
- /** Build an adapter of the given generic type, which invokes typedTarget
- * on the incoming arguments, after unboxing as necessary.
- * The return value is boxed if necessary.
- * @param genericType the required type of the result
- * @param typedTarget the target
- * @return an adapter method handle
- */
- public static MethodHandle make(MethodHandle target, int spreadCount) {
- MethodType type = target.type();
- MethodType gtype = type.generic();
- if (type == gtype) {
- return SpreadGeneric.of(type, spreadCount).makeInstance(target);
- } else {
- MethodHandle gtarget = FromGeneric.make(target);
- assert(gtarget.type() == gtype);
- MethodHandle gspread = SpreadGeneric.of(gtype, spreadCount).makeInstance(gtarget);
- return ToGeneric.make(preSpreadType(type, spreadCount), gspread);
- }
- }
-
- /** Return the adapter information for this type's erasure. */
- static SpreadGeneric of(MethodType targetType, int spreadCount) {
- if (targetType != targetType.generic())
- throw new UnsupportedOperationException("NYI type="+targetType);
- MethodTypeForm form = targetType.form();
- int outcount = form.parameterCount();
- assert(spreadCount <= outcount);
- SpreadGeneric[] spreadGens = form.spreadGeneric;
- if (spreadGens == null)
- form.spreadGeneric = spreadGens = new SpreadGeneric[outcount+1];
- SpreadGeneric spreadGen = spreadGens[spreadCount];
- if (spreadGen == null)
- spreadGens[spreadCount] = spreadGen = new SpreadGeneric(form.erasedType(), spreadCount);
- return spreadGen;
- }
-
- public String toString() {
- return getClass().getSimpleName()+targetType+"["+spreadCount+"]";
- }
-
- // This mini-api is called from an Adapter to manage the spread.
- /** A check/coercion that happens once before any selections. */
- protected Object check(Object av, int n) {
- checkSpreadArgument(av, n);
- return av;
- }
-
- /** The selection operator for spreading; note that it takes Object not Object[]. */
- protected Object select(Object av, int n) {
- return ((Object[])av)[n];
- }
- /*
- protected int select_I(Object av, int n) {
- // maybe return ((int[])select)[n]
- throw new UnsupportedOperationException("subclass resp.");
- }
- protected int select_J(Object av, int n) {
- // maybe return ((long[])select)[n]
- throw new UnsupportedOperationException("subclass resp.");
- }
- // */
-
- /* Create an adapter that handles spreading calls for the given type. */
- static Adapter findAdapter(SpreadGeneric outer, MethodHandle[] ep) {
- MethodType targetType = outer.targetType;
- int spreadCount = outer.spreadCount;
- int outargs = targetType.parameterCount();
- int inargs = outargs - spreadCount;
- if (inargs < 0) return null;
- MethodType entryType = MethodType.genericMethodType(inargs + 1); // 1 for av
- String cname1 = "S" + outargs;
- String[] cnames = { cname1 };
- String iname = "invoke_S"+spreadCount;
- // e.g., D5I2, D5, L5I2, L5; invoke_D5
- for (String cname : cnames) {
- Class<? extends Adapter> acls = Adapter.findSubClass(cname);
- if (acls == null) continue;
- // see if it has the required invoke method
- MethodHandle entryPoint = null;
- try {
- entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
- } catch (ReflectiveOperationException ex) {
- }
- if (entryPoint == null) continue;
- Constructor<? extends Adapter> ctor = null;
- try {
- ctor = acls.getDeclaredConstructor(SpreadGeneric.class);
- } catch (NoSuchMethodException ex) {
- } catch (SecurityException ex) {
- }
- if (ctor == null) continue;
- try {
- // Produce an instance configured as a prototype.
- Adapter ad = ctor.newInstance(outer);
- ep[0] = entryPoint;
- return ad;
- } catch (IllegalArgumentException ex) {
- } catch (InvocationTargetException wex) {
- Throwable ex = wex.getTargetException();
- if (ex instanceof Error) throw (Error)ex;
- if (ex instanceof RuntimeException) throw (RuntimeException)ex;
- } catch (InstantiationException ex) {
- } catch (IllegalAccessException ex) {
- }
- }
- return null;
- }
-
- static Adapter buildAdapterFromBytecodes(MethodType targetType,
- int spreadCount, MethodHandle[] ep) {
- throw new UnsupportedOperationException("NYI");
- }
-
- /**
- * This adapter takes some untyped arguments, and returns an untyped result.
- * Internally, it applies the invoker to the target, which causes the
- * objects to be unboxed; the result is a raw type in L/I/J/F/D.
- * This result is passed to convert, which is responsible for
- * converting the raw result into a boxed object.
- * The invoker is kept separate from the target because it can be
- * generated once per type erasure family, and reused across adapters.
- */
- static abstract class Adapter extends BoundMethodHandle {
- /*
- * class X<<R,int M,int N>> extends Adapter {
- * (Object**N)=>R target;
- * static int S = N-M;
- * Object invoke(Object**M a, Object v) = target(a..., v[0]...v[S-1]);
- * }
- */
- protected final SpreadGeneric outer;
- protected final MethodHandle target; // (any**N) => R
-
- @Override
- public String toString() {
- return addTypeString(target, this);
- }
-
- static final MethodHandle NO_ENTRY = ValueConversions.identity();
-
- protected boolean isPrototype() { return target == null; }
- protected Adapter(SpreadGeneric outer) {
- super(NO_ENTRY);
- this.outer = outer;
- this.target = null;
- assert(isPrototype());
- }
-
- protected Adapter(SpreadGeneric outer, MethodHandle target) {
- super(outer.entryPoint);
- this.outer = outer;
- this.target = target;
- }
-
- /** Make a copy of self, with new fields. */
- protected abstract Adapter makeInstance(SpreadGeneric outer, MethodHandle target);
- // { return new ThisType(outer, target); }
-
- protected Object check(Object av, int n) {
- return outer.check(av, n);
- }
- protected Object select(Object av, int n) {
- return outer.select(av, n);
- }
-
- static private final String CLASS_PREFIX; // "java.dyn.SpreadGeneric$"
- static {
- String aname = Adapter.class.getName();
- String sname = Adapter.class.getSimpleName();
- if (!aname.endsWith(sname)) throw new InternalError();
- CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
- }
- /** Find a sibing class of Adapter. */
- static Class<? extends Adapter> findSubClass(String name) {
- String cname = Adapter.CLASS_PREFIX + name;
- try {
- return Class.forName(cname).asSubclass(Adapter.class);
- } catch (ClassNotFoundException ex) {
- return null;
- } catch (ClassCastException ex) {
- return null;
- }
- }
- }
-
- /* generated classes follow this pattern:
- static class xS2 extends Adapter {
- protected xS2(SpreadGeneric outer) { super(outer); } // to build prototype
- protected xS2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected xS2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new xS2(outer, t); }
- protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av,0);
- return target.invokeExact(a0, a1)); }
- protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av,1);
- return target.invokeExact(a0,
- super.select(av,0)); }
- protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av,1);
- return target.invokeExact(
- super.select(av,0), super.select(av,1)); }
- }
- // */
-
-/*
-: SHELL; n=SpreadGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
-//{{{
-import java.util.*;
-class genclasses {
- static String[][] TEMPLATES = { {
- "@for@ N=0..10",
- " //@each-cat@",
- " static class @cat@ extends Adapter {",
- " protected @cat@(SpreadGeneric outer) { super(outer); } // to build prototype",
- " protected @cat@(SpreadGeneric outer, MethodHandle t) { super(outer, t); }",
- " protected @cat@ makeInstance(SpreadGeneric outer, MethodHandle t) { return new @cat@(outer, t); }",
- " protected Object invoke_S0(@Tvav,@Object av) throws Throwable { av = super.check(av, 0);",
- " return target.invokeExact(@av@); }",
- " //@each-S@",
- " protected Object invoke_S@S@(@Tvav,@Object av) throws Throwable { av = super.check(av, @S@);",
- " return target.invokeExact(@av,@@sv@); }",
- " //@end-S@",
- " }",
- } };
- static final String NEWLINE_INDENT = "\n ";
- enum VAR {
- cat, N, S, av, av_, Tvav_, sv;
- public final String pattern = "@"+toString().replace('_','.')+"@";
- public String binding = toString();
- static void makeBindings(boolean topLevel, int outargs, int spread) {
- int inargs = outargs - spread;
- VAR.cat.binding = "S"+outargs;
- VAR.N.binding = String.valueOf(outargs); // outgoing arg count
- VAR.S.binding = String.valueOf(spread); // spread count
- String[] av = new String[inargs];
- String[] Tvav = new String[inargs];
- for (int i = 0; i < inargs; i++) {
- av[i] = arg(i);
- Tvav[i] = param("Object", av[i]);
- }
- VAR.av.binding = comma(av);
- VAR.av_.binding = comma(av, ", ");
- VAR.Tvav_.binding = comma(Tvav, ", ");
- String[] sv = new String[spread];
- for (int i = 0; i < spread; i++) {
- String spc = "";
- if (i % 4 == 0) spc = NEWLINE_INDENT;
- sv[i] = spc+"super.select(av,"+i+")";
- }
- VAR.sv.binding = comma(sv);
- }
- static String arg(int i) { return "a"+i; }
- static String param(String t, String a) { return t+" "+a; }
- static String comma(String[] v) { return comma(v, ""); }
- static String comma(String[] v, String sep) {
- if (v.length == 0) return "";
- String res = v[0];
- for (int i = 1; i < v.length; i++) res += ", "+v[i];
- return res + sep;
- }
- static String transform(String string) {
- for (VAR var : values())
- string = string.replaceAll(var.pattern, var.binding);
- return string;
- }
- }
- static String[] stringsIn(String[] strings, int beg, int end) {
- return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
- }
- static String[] stringsBefore(String[] strings, int pos) {
- return stringsIn(strings, 0, pos);
- }
- static String[] stringsAfter(String[] strings, int pos) {
- return stringsIn(strings, pos, strings.length);
- }
- static int indexAfter(String[] strings, int pos, String tag) {
- return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
- }
- static int indexBefore(String[] strings, int pos, String tag) {
- for (int i = pos, end = strings.length; ; i++) {
- if (i == end || strings[i].endsWith(tag)) return i;
- }
- }
- static int MIN_ARITY, MAX_ARITY;
- public static void main(String... av) {
- for (String[] template : TEMPLATES) {
- int forLinesLimit = indexBefore(template, 0, "@each-cat@");
- String[] forLines = stringsBefore(template, forLinesLimit);
- template = stringsAfter(template, forLinesLimit);
- for (String forLine : forLines)
- expandTemplate(forLine, template);
- }
- }
- static void expandTemplate(String forLine, String[] template) {
- String[] params = forLine.split("[^0-9]+");
- if (params[0].length() == 0) params = stringsAfter(params, 1);
- System.out.println("//params="+Arrays.asList(params));
- int pcur = 0;
- MIN_ARITY = Integer.valueOf(params[pcur++]);
- MAX_ARITY = Integer.valueOf(params[pcur++]);
- if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
- for (int outargs = MIN_ARITY; outargs <= MAX_ARITY; outargs++) {
- expandTemplate(template, true, outargs, 0);
- }
- }
- static void expandTemplate(String[] template, boolean topLevel, int outargs, int spread) {
- VAR.makeBindings(topLevel, outargs, spread);
- for (int i = 0; i < template.length; i++) {
- String line = template[i];
- if (line.endsWith("@each-cat@")) {
- // ignore
- } else if (line.endsWith("@each-S@")) {
- int blockEnd = indexAfter(template, i, "@end-S@");
- String[] block = stringsIn(template, i+1, blockEnd-1);
- for (int spread1 = spread+1; spread1 <= outargs; spread1++)
- expandTemplate(block, false, outargs, spread1);
- VAR.makeBindings(topLevel, outargs, spread);
- i = blockEnd-1; continue;
- } else {
- System.out.println(VAR.transform(line));
- }
- }
- }
-}
-//}}} */
-//params=[0, 10]
- static class S0 extends Adapter {
- protected S0(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S0(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S0 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S0(outer, t); }
- protected Object invoke_S0(Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(); }
- }
- static class S1 extends Adapter {
- protected S1(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S1(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S1 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S1(outer, t); }
- protected Object invoke_S0(Object a0, Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(a0); }
- protected Object invoke_S1(Object av) throws Throwable { av = super.check(av, 1);
- return target.invokeExact(
- super.select(av,0)); }
- }
- static class S2 extends Adapter {
- protected S2(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S2(outer, t); }
- protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(a0, a1); }
- protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av, 1);
- return target.invokeExact(a0,
- super.select(av,0)); }
- protected Object invoke_S2(Object av) throws Throwable { av = super.check(av, 2);
- return target.invokeExact(
- super.select(av,0), super.select(av,1)); }
- }
- static class S3 extends Adapter {
- protected S3(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S3(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S3 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S3(outer, t); }
- protected Object invoke_S0(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(a0, a1, a2); }
- protected Object invoke_S1(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 1);
- return target.invokeExact(a0, a1,
- super.select(av,0)); }
- protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av, 2);
- return target.invokeExact(a0,
- super.select(av,0), super.select(av,1)); }
- protected Object invoke_S3(Object av) throws Throwable { av = super.check(av, 3);
- return target.invokeExact(
- super.select(av,0), super.select(av,1), super.select(av,2)); }
- }
- static class S4 extends Adapter {
- protected S4(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S4(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S4 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S4(outer, t); }
- protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(a0, a1, a2, a3); }
- protected Object invoke_S1(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 1);
- return target.invokeExact(a0, a1, a2,
- super.select(av,0)); }
- protected Object invoke_S2(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 2);
- return target.invokeExact(a0, a1,
- super.select(av,0), super.select(av,1)); }
- protected Object invoke_S3(Object a0, Object av) throws Throwable { av = super.check(av, 3);
- return target.invokeExact(a0,
- super.select(av,0), super.select(av,1), super.select(av,2)); }
- protected Object invoke_S4(Object av) throws Throwable { av = super.check(av, 4);
- return target.invokeExact(
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
- }
- static class S5 extends Adapter {
- protected S5(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S5(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S5 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S5(outer, t); }
- protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(a0, a1, a2, a3, a4); }
- protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 1);
- return target.invokeExact(a0, a1, a2, a3,
- super.select(av,0)); }
- protected Object invoke_S2(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 2);
- return target.invokeExact(a0, a1, a2,
- super.select(av,0), super.select(av,1)); }
- protected Object invoke_S3(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 3);
- return target.invokeExact(a0, a1,
- super.select(av,0), super.select(av,1), super.select(av,2)); }
- protected Object invoke_S4(Object a0, Object av) throws Throwable { av = super.check(av, 4);
- return target.invokeExact(a0,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
- protected Object invoke_S5(Object av) throws Throwable { av = super.check(av, 5);
- return target.invokeExact(
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4)); }
- }
- static class S6 extends Adapter {
- protected S6(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S6(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S6 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S6(outer, t); }
- protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(a0, a1, a2, a3, a4, a5); }
- protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 1);
- return target.invokeExact(a0, a1, a2, a3, a4,
- super.select(av,0)); }
- protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 2);
- return target.invokeExact(a0, a1, a2, a3,
- super.select(av,0), super.select(av,1)); }
- protected Object invoke_S3(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 3);
- return target.invokeExact(a0, a1, a2,
- super.select(av,0), super.select(av,1), super.select(av,2)); }
- protected Object invoke_S4(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 4);
- return target.invokeExact(a0, a1,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
- protected Object invoke_S5(Object a0, Object av) throws Throwable { av = super.check(av, 5);
- return target.invokeExact(a0,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4)); }
- protected Object invoke_S6(Object av) throws Throwable { av = super.check(av, 6);
- return target.invokeExact(
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5)); }
- }
- static class S7 extends Adapter {
- protected S7(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S7(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S7 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S7(outer, t); }
- protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); }
- protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 1);
- return target.invokeExact(a0, a1, a2, a3, a4, a5,
- super.select(av,0)); }
- protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 2);
- return target.invokeExact(a0, a1, a2, a3, a4,
- super.select(av,0), super.select(av,1)); }
- protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 3);
- return target.invokeExact(a0, a1, a2, a3,
- super.select(av,0), super.select(av,1), super.select(av,2)); }
- protected Object invoke_S4(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 4);
- return target.invokeExact(a0, a1, a2,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
- protected Object invoke_S5(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 5);
- return target.invokeExact(a0, a1,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4)); }
- protected Object invoke_S6(Object a0, Object av) throws Throwable { av = super.check(av, 6);
- return target.invokeExact(a0,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5)); }
- protected Object invoke_S7(Object av) throws Throwable { av = super.check(av, 7);
- return target.invokeExact(
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5), super.select(av,6)); }
- }
- static class S8 extends Adapter {
- protected S8(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S8(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S8 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S8(outer, t); }
- protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 1);
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
- super.select(av,0)); }
- protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 2);
- return target.invokeExact(a0, a1, a2, a3, a4, a5,
- super.select(av,0), super.select(av,1)); }
- protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 3);
- return target.invokeExact(a0, a1, a2, a3, a4,
- super.select(av,0), super.select(av,1), super.select(av,2)); }
- protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 4);
- return target.invokeExact(a0, a1, a2, a3,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
- protected Object invoke_S5(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 5);
- return target.invokeExact(a0, a1, a2,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4)); }
- protected Object invoke_S6(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 6);
- return target.invokeExact(a0, a1,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5)); }
- protected Object invoke_S7(Object a0, Object av) throws Throwable { av = super.check(av, 7);
- return target.invokeExact(a0,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5), super.select(av,6)); }
- protected Object invoke_S8(Object av) throws Throwable { av = super.check(av, 8);
- return target.invokeExact(
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
- }
- static class S9 extends Adapter {
- protected S9(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S9(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S9 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S9(outer, t); }
- protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 1);
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7,
- super.select(av,0)); }
- protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 2);
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
- super.select(av,0), super.select(av,1)); }
- protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 3);
- return target.invokeExact(a0, a1, a2, a3, a4, a5,
- super.select(av,0), super.select(av,1), super.select(av,2)); }
- protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 4);
- return target.invokeExact(a0, a1, a2, a3, a4,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
- protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 5);
- return target.invokeExact(a0, a1, a2, a3,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4)); }
- protected Object invoke_S6(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 6);
- return target.invokeExact(a0, a1, a2,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5)); }
- protected Object invoke_S7(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 7);
- return target.invokeExact(a0, a1,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5), super.select(av,6)); }
- protected Object invoke_S8(Object a0, Object av) throws Throwable { av = super.check(av, 8);
- return target.invokeExact(a0,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
- protected Object invoke_S9(Object av) throws Throwable { av = super.check(av, 9);
- return target.invokeExact(
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
- super.select(av,8)); }
- }
- static class S10 extends Adapter {
- protected S10(SpreadGeneric outer) { super(outer); } // to build prototype
- protected S10(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
- protected S10 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S10(outer, t); }
- protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object av) throws Throwable { av = super.check(av, 0);
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 1);
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8,
- super.select(av,0)); }
- protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 2);
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7,
- super.select(av,0), super.select(av,1)); }
- protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 3);
- return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
- super.select(av,0), super.select(av,1), super.select(av,2)); }
- protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 4);
- return target.invokeExact(a0, a1, a2, a3, a4, a5,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
- protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 5);
- return target.invokeExact(a0, a1, a2, a3, a4,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4)); }
- protected Object invoke_S6(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 6);
- return target.invokeExact(a0, a1, a2, a3,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5)); }
- protected Object invoke_S7(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 7);
- return target.invokeExact(a0, a1, a2,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5), super.select(av,6)); }
- protected Object invoke_S8(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 8);
- return target.invokeExact(a0, a1,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
- protected Object invoke_S9(Object a0, Object av) throws Throwable { av = super.check(av, 9);
- return target.invokeExact(a0,
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
- super.select(av,8)); }
- protected Object invoke_S10(Object av) throws Throwable { av = super.check(av, 10);
- return target.invokeExact(
- super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
- super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
- super.select(av,8), super.select(av,9)); }
- }
-}
--- a/jdk/src/share/classes/java/dyn/SwitchPoint.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * <p>
- * A {@code SwitchPoint} is an object which can publish state transitions to other threads.
- * A switch point is initially in the <em>valid</em> state, but may at any time be
- * changed to the <em>invalid</em> state. Invalidation cannot be reversed.
- * A switch point can combine a <em>guarded pair</em> of method handles into a
- * <em>guarded delegator</em>.
- * The guarded delegator is a method handle which delegates to one of the old method handles.
- * The state of the switch point determines which of the two gets the delegation.
- * <p>
- * A single switch point may be used to control any number of method handles.
- * (Indirectly, therefore, it can control any number of call sites.)
- * This is done by using the single switch point as a factory for combining
- * any number of guarded method handle pairs into guarded delegators.
- * <p>
- * When a guarded delegator is created from a guarded pair, the pair
- * is wrapped in a new method handle {@code M},
- * which is permanently associated with the switch point that created it.
- * Each pair consists of a target {@code T} and a fallback {@code F}.
- * While the switch point is valid, invocations to {@code M} are delegated to {@code T}.
- * After it is invalidated, invocations are delegated to {@code F}.
- * <p>
- * Invalidation is global and immediate, as if the switch point contained a
- * volatile boolean variable consulted on every call to {@code M}.
- * The invalidation is also permanent, which means the switch point
- * can change state only once.
- * The switch point will always delegate to {@code F} after being invalidated.
- * At that point {@code guardWithTest} may ignore {@code T} and return {@code F}.
- * <p>
- * Here is an example of a switch point in action:
- * <blockquote><pre>
-MethodType MT_str2 = MethodType.methodType(String.class, String.class);
-MethodHandle MH_strcat = MethodHandles.lookup()
- .findVirtual(String.class, "concat", MT_str2);
-SwitchPoint spt = new SwitchPoint();
-// the following steps may be repeated to re-use the same switch point:
-MethodHandle worker1 = strcat;
-MethodHandle worker2 = MethodHandles.permuteArguments(strcat, MT_str2, 1, 0);
-MethodHandle worker = spt.guardWithTest(worker1, worker2);
-assertEquals("method", (String) worker.invokeExact("met", "hod"));
-SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
-assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
- * </pre></blockquote>
- * <p style="font-size:smaller;">
- * <em>Discussion:</em>
- * Switch points are useful without subclassing. They may also be subclassed.
- * This may be useful in order to associate application-specific invalidation logic
- * with the switch point.
- * <p style="font-size:smaller;">
- * <em>Implementation Note:</em>
- * A switch point behaves as if implemented on top of {@link MutableCallSite},
- * approximately as follows:
- * <blockquote><pre>
-public class SwitchPoint {
- private static final MethodHandle
- K_true = MethodHandles.constant(boolean.class, true),
- K_false = MethodHandles.constant(boolean.class, false);
- private final MutableCallSite mcs;
- private final MethodHandle mcsInvoker;
- public SwitchPoint() {
- this.mcs = new MutableCallSite(K_true);
- this.mcsInvoker = mcs.dynamicInvoker();
- }
- public MethodHandle guardWithTest(
- MethodHandle target, MethodHandle fallback) {
- // Note: mcsInvoker is of type ()boolean.
- // Target and fallback may take any arguments, but must have the same type.
- return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
- }
- public static void invalidateAll(SwitchPoint[] spts) {
- List<MutableCallSite> mcss = new ArrayList<>();
- for (SwitchPoint spt : spts) mcss.add(spt.mcs);
- for (MutableCallSite mcs : mcss) mcs.setTarget(K_false);
- MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
- }
-}
- * </pre></blockquote>
- * @author Remi Forax, JSR 292 EG
- */
-public class SwitchPoint {
- private static final MethodHandle
- K_true = MethodHandles.constant(boolean.class, true),
- K_false = MethodHandles.constant(boolean.class, false);
-
- private final MutableCallSite mcs;
- private final MethodHandle mcsInvoker;
-
- /**
- * Creates a new switch point.
- */
- public SwitchPoint() {
- this.mcs = new MutableCallSite(K_true);
- this.mcsInvoker = mcs.dynamicInvoker();
- }
-
- /**
- * Returns a method handle which always delegates either to the target or the fallback.
- * The method handle will delegate to the target exactly as long as the switch point is valid.
- * After that, it will permanently delegate to the fallback.
- * <p>
- * The target and fallback must be of exactly the same method type,
- * and the resulting combined method handle will also be of this type.
- *
- * @param target the method handle selected by the switch point as long as it is valid
- * @param fallback the method handle selected by the switch point after it is invalidated
- * @return a combined method handle which always calls either the target or fallback
- * @throws NullPointerException if either argument is null
- * @see MethodHandles#guardWithTest
- */
- public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback) {
- if (mcs.getTarget() == K_false)
- return fallback; // already invalid
- return MethodHandles.guardWithTest(mcsInvoker, target, fallback);
- }
-
- /**
- * Sets all of the given switch points into the invalid state.
- * After this call executes, no thread will observe any of the
- * switch points to be in a valid state.
- * <p>
- * This operation is likely to be expensive and should be used sparingly.
- * If possible, it should be buffered for batch processing on sets of switch points.
- * <p>
- * If {@code switchPoints} contains a null element,
- * a {@code NullPointerException} will be raised.
- * In this case, some non-null elements in the array may be
- * processed before the method returns abnormally.
- * Which elements these are (if any) is implementation-dependent.
- *
- * <p style="font-size:smaller;">
- * <em>Discussion:</em>
- * For performance reasons, {@code invalidateAll} is not a virtual method
- * on a single switch point, but rather applies to a set of switch points.
- * Some implementations may incur a large fixed overhead cost
- * for processing one or more invalidation operations,
- * but a small incremental cost for each additional invalidation.
- * In any case, this operation is likely to be costly, since
- * other threads may have to be somehow interrupted
- * in order to make them notice the updated switch point state.
- * However, it may be observed that a single call to invalidate
- * several switch points has the same formal effect as many calls,
- * each on just one of the switch points.
- *
- * <p style="font-size:smaller;">
- * <em>Implementation Note:</em>
- * Simple implementations of {@code SwitchPoint} may use
- * a private {@link MutableCallSite} to publish the state of a switch point.
- * In such an implementation, the {@code invalidateAll} method can
- * simply change the call site's target, and issue one call to
- * {@linkplain MutableCallSite#syncAll synchronize} all the
- * private call sites.
- *
- * @param switchPoints an array of call sites to be synchronized
- * @throws NullPointerException if the {@code switchPoints} array reference is null
- * or the array contains a null
- */
- public static void invalidateAll(SwitchPoint[] switchPoints) {
- if (switchPoints.length == 0) return;
- MutableCallSite[] sites = new MutableCallSite[switchPoints.length];
- for (int i = 0; i < switchPoints.length; i++) {
- SwitchPoint spt = switchPoints[i];
- if (spt == null) break; // MSC.syncAll will trigger a NPE
- sites[i] = spt.mcs;
- spt.mcs.setTarget(K_false);
- }
- MutableCallSite.syncAll(sites);
- }
-}
--- a/jdk/src/share/classes/java/dyn/ToGeneric.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1041 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import sun.dyn.util.ValueConversions;
-import sun.dyn.util.Wrapper;
-import static java.dyn.MethodHandleStatics.*;
-import static java.dyn.MethodHandles.Lookup.IMPL_LOOKUP;
-
-/**
- * Adapters which mediate between incoming calls which are not generic
- * and outgoing calls which are. Any call can be represented generically
- * boxing up its arguments, and (on return) unboxing the return value.
- * <p>
- * A call is "generic" (in MethodHandle terms) if its MethodType features
- * only Object arguments. A non-generic call therefore features
- * primitives and/or reference types other than Object.
- * An adapter has types for its incoming and outgoing calls.
- * The incoming call type is simply determined by the adapter's type
- * (the MethodType it presents to callers). The outgoing call type
- * is determined by the adapter's target (a MethodHandle that the adapter
- * either binds internally or else takes as a leading argument).
- * (To stretch the term, adapter-like method handles may have multiple
- * targets or be polymorphic across multiple call types.)
- * @author jrose
- */
-class ToGeneric {
- // type for the incoming call (may be erased)
- private final MethodType entryType;
- // incoming type with primitives moved to the end and turned to int/long
- private final MethodType rawEntryType;
- // adapter for the erased type
- private final Adapter adapter;
- // entry point for adapter (Adapter mh, a...) => ...
- private final MethodHandle entryPoint;
- // permutation of arguments for primsAtEndType
- private final int[] primsAtEndOrder;
- // optional final argument list conversions (at least, invokes the target)
- private final MethodHandle invoker;
- // conversion which unboxes a primitive return value
- private final MethodHandle returnConversion;
-
- /** Compute and cache information common to all generifying (boxing) adapters
- * that implement members of the erasure-family of the given erased type.
- */
- private ToGeneric(MethodType entryType) {
- assert(entryType.erase() == entryType); // for now
- // incoming call will first "forget" all reference types except Object
- this.entryType = entryType;
- MethodHandle invoker0 = entryType.generic().invokers().exactInvoker();
- MethodType rawEntryTypeInit;
- Adapter ad = findAdapter(rawEntryTypeInit = entryType);
- if (ad != null) {
- // Immediate hit to exactly the adapter we want,
- // with no monkeying around with primitive types.
- this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
- this.rawEntryType = rawEntryTypeInit;
- this.adapter = ad;
- this.entryPoint = ad.prototypeEntryPoint();
- this.primsAtEndOrder = null;
- this.invoker = invoker0;
- return;
- }
-
- // next, it will reorder primitives after references
- MethodType primsAtEnd = entryType.form().primsAtEnd();
- // at the same time, it will "forget" all primitive types except int/long
- this.primsAtEndOrder = MethodTypeForm.primsAtEndOrder(entryType);
- if (primsAtEndOrder != null) {
- // reordering is required; build on top of a simpler ToGeneric
- ToGeneric va2 = ToGeneric.of(primsAtEnd);
- this.adapter = va2.adapter;
- if (true) throw new UnsupportedOperationException("NYI: primitive parameters must follow references; entryType = "+entryType);
- this.entryPoint = MethodHandleImpl.convertArguments(
- va2.entryPoint, primsAtEnd, entryType, primsAtEndOrder);
- // example: for entryType of (int,Object,Object), the reordered
- // type is (Object,Object,int) and the order is {1,2,0},
- // and putPAE is (mh,int0,obj1,obj2) => mh.invokeExact(obj1,obj2,int0)
- return;
- }
-
- // after any needed argument reordering, it will reinterpret
- // primitive arguments according to their "raw" types int/long
- MethodType intsAtEnd = primsAtEnd.form().primsAsInts();
- ad = findAdapter(rawEntryTypeInit = intsAtEnd);
- MethodHandle rawEntryPoint;
- if (ad != null) {
- rawEntryPoint = ad.prototypeEntryPoint();
- } else {
- // Perhaps the adapter is available only for longs.
- // If so, we can use it, but there will have to be a little
- // more stack motion on each call.
- MethodType longsAtEnd = primsAtEnd.form().primsAsLongs();
- ad = findAdapter(rawEntryTypeInit = longsAtEnd);
- if (ad != null) {
- MethodType eptWithLongs = longsAtEnd.insertParameterTypes(0, ad.getClass());
- MethodType eptWithInts = intsAtEnd.insertParameterTypes(0, ad.getClass());
- rawEntryPoint = ad.prototypeEntryPoint();
- MethodType midType = eptWithLongs; // will change longs to ints
- for (int i = 0, nargs = midType.parameterCount(); i < nargs; i++) {
- if (midType.parameterType(i) != eptWithInts.parameterType(i)) {
- assert(midType.parameterType(i) == long.class);
- assert(eptWithInts.parameterType(i) == int.class);
- MethodType nextType = midType.changeParameterType(i, int.class);
- rawEntryPoint = MethodHandleImpl.convertArguments(
- rawEntryPoint, nextType, midType, null);
- midType = nextType;
- }
- }
- assert(midType == eptWithInts);
- } else {
- // If there is no statically compiled adapter,
- // build one by means of dynamic bytecode generation.
- ad = buildAdapterFromBytecodes(rawEntryTypeInit = intsAtEnd);
- rawEntryPoint = ad.prototypeEntryPoint();
- }
- }
- MethodType tepType = entryType.insertParameterTypes(0, ad.getClass());
- this.entryPoint =
- AdapterMethodHandle.makeRetypeRaw(tepType, rawEntryPoint);
- if (this.entryPoint == null)
- throw new UnsupportedOperationException("cannot retype to "+entryType
- +" from "+rawEntryPoint.type().dropParameterTypes(0, 1));
- this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
- this.rawEntryType = rawEntryTypeInit;
- this.adapter = ad;
- this.invoker = makeRawArgumentFilter(invoker0, rawEntryTypeInit, entryType);
- }
-
- /** A generic argument list will be created by a call of type 'raw'.
- * The values need to be reboxed for to match 'cooked'.
- * Do this on the fly.
- */
- // TO DO: Use a generic argument converter in a different file
- static MethodHandle makeRawArgumentFilter(MethodHandle invoker,
- MethodType raw, MethodType cooked) {
- MethodHandle filteredInvoker = null;
- for (int i = 0, nargs = raw.parameterCount(); i < nargs; i++) {
- Class<?> src = raw.parameterType(i);
- Class<?> dst = cooked.parameterType(i);
- if (src == dst) continue;
- assert(src.isPrimitive() && dst.isPrimitive());
- if (filteredInvoker == null) {
- filteredInvoker =
- AdapterMethodHandle.makeCheckCast(
- invoker.type().generic(), invoker, 0, MethodHandle.class);
- if (filteredInvoker == null) throw new UnsupportedOperationException("NYI");
- }
- MethodHandle reboxer = ValueConversions.rebox(dst, false);
- filteredInvoker = FilterGeneric.makeArgumentFilter(1+i, reboxer, filteredInvoker);
- if (filteredInvoker == null) throw new InternalError();
- }
- if (filteredInvoker == null) return invoker;
- return AdapterMethodHandle.makeRetypeOnly(invoker.type(), filteredInvoker);
- }
-
- /**
- * Caller will be expecting a result from a call to {@code type},
- * while the internal adapter entry point is rawEntryType.
- * Also, the internal target method will be returning a boxed value,
- * as an untyped object.
- * <p>
- * Produce a value converter which will be typed to convert from
- * {@code Object} to the return value of {@code rawEntryType}, and will
- * in fact ensure that the value is compatible with the return type of
- * {@code type}.
- */
- private static MethodHandle computeReturnConversion(
- MethodType type, MethodType rawEntryType, boolean mustCast) {
- Class<?> tret = type.returnType();
- Class<?> rret = rawEntryType.returnType();
- if (mustCast || !tret.isPrimitive()) {
- assert(!tret.isPrimitive());
- assert(!rret.isPrimitive());
- if (rret == Object.class && !mustCast)
- return null;
- return ValueConversions.cast(tret, false);
- } else if (tret == rret) {
- return ValueConversions.unbox(tret, false);
- } else {
- assert(rret.isPrimitive());
- assert(tret == double.class ? rret == long.class : rret == int.class);
- return ValueConversions.unboxRaw(tret, false);
- }
- }
-
- Adapter makeInstance(MethodType type, MethodHandle genericTarget) {
- genericTarget.getClass(); // check for NPE
- MethodHandle convert = returnConversion;
- if (primsAtEndOrder != null)
- // reorder arguments passed to genericTarget, if primsAtEndOrder
- throw new UnsupportedOperationException("NYI");
- if (type == entryType) {
- if (convert == null) convert = ValueConversions.identity();
- return adapter.makeInstance(entryPoint, invoker, convert, genericTarget);
- }
- // my erased-type is not exactly the same as the desired type
- assert(type.erase() == entryType); // else we are busted
- if (convert == null)
- convert = computeReturnConversion(type, rawEntryType, true);
- // retype erased reference arguments (the cast makes it safe to do this)
- MethodType tepType = type.insertParameterTypes(0, adapter.getClass());
- MethodHandle typedEntryPoint =
- AdapterMethodHandle.makeRetypeRaw(tepType, entryPoint);
- return adapter.makeInstance(typedEntryPoint, invoker, convert, genericTarget);
- }
-
- /** Build an adapter of the given type, which invokes genericTarget
- * on the incoming arguments, after boxing as necessary.
- * The return value is unboxed if necessary.
- * @param type the required type of the
- * @param genericTarget the target, which must accept and return only Object values
- * @return an adapter method handle
- */
- public static MethodHandle make(MethodType type, MethodHandle genericTarget) {
- MethodType gtype = genericTarget.type();
- if (type.generic() != gtype)
- throw newIllegalArgumentException("type must be generic");
- if (type == gtype) return genericTarget;
- return ToGeneric.of(type).makeInstance(type, genericTarget);
- }
-
- /** Return the adapter information for this type's erasure. */
- static ToGeneric of(MethodType type) {
- MethodTypeForm form = type.form();
- ToGeneric toGen = form.toGeneric;
- if (toGen == null)
- form.toGeneric = toGen = new ToGeneric(form.erasedType());
- return toGen;
- }
-
- public String toString() {
- return "ToGeneric"+entryType
- +(primsAtEndOrder!=null?"[reorder]":"");
- }
-
- /* Create an adapter for the given incoming call type. */
- static Adapter findAdapter(MethodType entryPointType) {
- MethodTypeForm form = entryPointType.form();
- Class<?> rtype = entryPointType.returnType();
- int argc = form.parameterCount();
- int lac = form.longPrimitiveParameterCount();
- int iac = form.primitiveParameterCount() - lac;
- String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
- String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
- String iname0 = "invoke_"+rawReturn;
- String iname1 = "invoke";
- String[] inames = { iname0, iname1 };
- String cname0 = rawReturn + argc;
- String cname1 = "A" + argc;
- String[] cnames = { cname1, cname1+intsAndLongs, cname0, cname0+intsAndLongs };
- // e.g., D5I2, D5, L5I2, L5
- for (String cname : cnames) {
- Class<? extends Adapter> acls = Adapter.findSubClass(cname);
- if (acls == null) continue;
- // see if it has the required invoke method
- for (String iname : inames) {
- MethodHandle entryPoint = null;
- try {
- entryPoint = IMPL_LOOKUP.
- findSpecial(acls, iname, entryPointType, acls);
- } catch (ReflectiveOperationException ex) {
- }
- if (entryPoint == null) continue;
- Constructor<? extends Adapter> ctor = null;
- try {
- // Prototype builder:
- ctor = acls.getDeclaredConstructor(MethodHandle.class);
- } catch (NoSuchMethodException ex) {
- } catch (SecurityException ex) {
- }
- if (ctor == null) continue;
- try {
- return ctor.newInstance(entryPoint);
- } catch (IllegalArgumentException ex) {
- } catch (InvocationTargetException wex) {
- Throwable ex = wex.getTargetException();
- if (ex instanceof Error) throw (Error)ex;
- if (ex instanceof RuntimeException) throw (RuntimeException)ex;
- } catch (InstantiationException ex) {
- } catch (IllegalAccessException ex) {
- }
- }
- }
- return null;
- }
-
- static Adapter buildAdapterFromBytecodes(MethodType entryPointType) {
- throw new UnsupportedOperationException("NYI");
- }
-
- /**
- * The invoke method takes some particular but unconstrained spread
- * of raw argument types, and returns a raw return type (in L/I/J/F/D).
- * Internally, it converts the incoming arguments uniformly into objects.
- * This series of objects is then passed to the {@code target} method,
- * which returns a result object. This result is finally converted,
- * via another method handle {@code convert}, which is responsible for
- * converting the object result into the raw return value.
- */
- static abstract class Adapter extends BoundMethodHandle {
- /*
- * class X<<R,A...>> extends Adapter {
- * Object...=>Object target;
- * Object=>R convert;
- * R invoke(A... a...) = convert(invoker(target, a...)))
- * }
- */
- protected final MethodHandle invoker; // (MH, Object...) -> Object
- protected final MethodHandle target; // Object... -> Object
- protected final MethodHandle convert; // Object -> R
-
- @Override
- public String toString() {
- return target == null ? "prototype:"+convert : addTypeString(target, this);
- }
-
- protected boolean isPrototype() { return target == null; }
- /* Prototype constructor. */
- protected Adapter(MethodHandle entryPoint) {
- super(entryPoint);
- this.invoker = null;
- this.convert = entryPoint;
- this.target = null;
- assert(isPrototype());
- }
- protected MethodHandle prototypeEntryPoint() {
- if (!isPrototype()) throw new InternalError();
- return convert;
- }
-
- protected Adapter(MethodHandle entryPoint, MethodHandle invoker, MethodHandle convert, MethodHandle target) {
- super(entryPoint);
- this.invoker = invoker;
- this.convert = convert;
- this.target = target;
- }
-
- /** Make a copy of self, with new fields. */
- protected abstract Adapter makeInstance(MethodHandle entryPoint,
- MethodHandle invoker, MethodHandle convert, MethodHandle target);
- // { return new ThisType(entryPoint, convert, target); }
-
- // Code to run when the arguments (<= 4) have all been boxed.
- protected Object target() throws Throwable { return invoker.invokeExact(target); }
- protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); }
- protected Object target(Object a0, Object a1)
- throws Throwable { return invoker.invokeExact(target, a0, a1); }
- protected Object target(Object a0, Object a1, Object a2)
- throws Throwable { return invoker.invokeExact(target, a0, a1, a2); }
- protected Object target(Object a0, Object a1, Object a2, Object a3)
- throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); }
- /*
- protected Object target_0(Object... av) throws Throwable { return invoker.invokeExact(target, av); }
- protected Object target_1(Object a0, Object... av)
- throws Throwable { return invoker.invokeExact(target, a0, (Object)av); }
- protected Object target_2(Object a0, Object a1, Object... av)
- throws Throwable { return invoker.invokeExact(target, a0, a1, (Object)av); }
- protected Object target_3(Object a0, Object a1, Object a2, Object... av)
- throws Throwable { return invoker.invokeExact(target, a0, a1, a2, (Object)av); }
- protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av)
- throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, (Object)av); }
- // */
- // (For more than 4 arguments, generate the code in the adapter itself.)
-
- // Code to run when the generic target has finished and produced a value.
- protected Object return_L(Object res) throws Throwable { return (Object)convert.invokeExact(res); }
- protected int return_I(Object res) throws Throwable { return (int) convert.invokeExact(res); }
- protected long return_J(Object res) throws Throwable { return (long) convert.invokeExact(res); }
- protected float return_F(Object res) throws Throwable { return (float) convert.invokeExact(res); }
- protected double return_D(Object res) throws Throwable { return (double)convert.invokeExact(res); }
-
- static private final String CLASS_PREFIX; // "java.dyn.ToGeneric$"
- static {
- String aname = Adapter.class.getName();
- String sname = Adapter.class.getSimpleName();
- if (!aname.endsWith(sname)) throw new InternalError();
- CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
- }
- /** Find a sibing class of Adapter. */
- static Class<? extends Adapter> findSubClass(String name) {
- String cname = Adapter.CLASS_PREFIX + name;
- try {
- return Class.forName(cname).asSubclass(Adapter.class);
- } catch (ClassNotFoundException ex) {
- return null;
- } catch (ClassCastException ex) {
- return null;
- }
- }
- }
-
- /* generated classes follow this pattern:
- static class A1 extends Adapter {
- protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
- protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); }
- protected Object targetA1(Object a0) throws Throwable { return target(a0); }
- protected Object targetA1(int a0) throws Throwable { return target(a0); }
- protected Object targetA1(long a0) throws Throwable { return target(a0); }
- protected Object invoke_L(Object a0) throws Throwable { return return_L(targetA1(a0)); }
- protected int invoke_I(Object a0) throws Throwable { return return_I(targetA1(a0)); }
- protected long invoke_J(Object a0) throws Throwable { return return_J(targetA1(a0)); }
- protected float invoke_F(Object a0) throws Throwable { return return_F(targetA1(a0)); }
- protected double invoke_D(Object a0) throws Throwable { return return_D(targetA1(a0)); }
- protected Object invoke_L(int a0) throws Throwable { return return_L(targetA1(a0)); }
- protected int invoke_I(int a0) throws Throwable { return return_I(targetA1(a0)); }
- protected long invoke_J(int a0) throws Throwable { return return_J(targetA1(a0)); }
- protected float invoke_F(int a0) throws Throwable { return return_F(targetA1(a0)); }
- protected double invoke_D(int a0) throws Throwable { return return_D(targetA1(a0)); }
- protected Object invoke_L(long a0) throws Throwable { return return_L(targetA1(a0)); }
- protected int invoke_I(long a0) throws Throwable { return return_I(targetA1(a0)); }
- protected long invoke_J(long a0) throws Throwable { return return_J(targetA1(a0)); }
- protected float invoke_F(long a0) throws Throwable { return return_F(targetA1(a0)); }
- protected double invoke_D(long a0) throws Throwable { return return_D(targetA1(a0)); }
- }
- // */
-
-/*
-: SHELL; n=ToGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
-//{{{
-import java.util.*;
-class genclasses {
- static String[] TYPES = { "Object", "int ", "long ", "float ", "double" };
- static String[] TCHARS = { "L", "I", "J", "F", "D", "A" };
- static String[][] TEMPLATES = { {
- "@for@ arity=0..3 rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
- "@for@ arity=4..5 rcat<=2 nrefs<=99 nints<=99 nlongs<=99",
- "@for@ arity=6..10 rcat<=2 nrefs<=99 nints=0 nlongs<=99",
- " //@each-cat@",
- " static class @cat@ extends Adapter {",
- " protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
- " protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }",
- " protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }",
- " protected Object target(@Ovav@) throws Throwable { return invoker.invokeExact(target, @av@); }",
- " //@each-Tv@",
- " protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }",
- " //@end-Tv@",
- " //@each-Tv@",
- " //@each-R@",
- " protected @R@ invoke_@Rc@(@Tvav@) throws Throwable { return return_@Rc@(target@cat@(@av@)); }",
- " //@end-R@",
- " //@end-Tv@",
- " }",
- } };
- enum VAR {
- cat, R, Rc, Tv, av, Tvav, Ovav;
- public final String pattern = "@"+toString().replace('_','.')+"@";
- public String binding;
- static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
- int nargs = nrefs + nints + nlongs;
- if (topLevel)
- VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
- VAR.R.binding = TYPES[rcat];
- VAR.Rc.binding = TCHARS[rcat];
- String[] Tv = new String[nargs];
- String[] av = new String[nargs];
- String[] Tvav = new String[nargs];
- String[] Ovav = new String[nargs];
- for (int i = 0; i < nargs; i++) {
- int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
- Tv[i] = TYPES[tcat];
- av[i] = arg(i);
- Tvav[i] = param(Tv[i], av[i]);
- Ovav[i] = param("Object", av[i]);
- }
- VAR.Tv.binding = comma(Tv);
- VAR.av.binding = comma(av);
- VAR.Tvav.binding = comma(Tvav);
- VAR.Ovav.binding = comma(Ovav);
- }
- static String arg(int i) { return "a"+i; }
- static String param(String t, String a) { return t+" "+a; }
- static String comma(String[] v) { return comma(v, ""); }
- static String comma(String sep, String[] v) {
- if (v.length == 0) return "";
- String res = sep+v[0];
- for (int i = 1; i < v.length; i++) res += ", "+v[i];
- return res;
- }
- static String transform(String string) {
- for (VAR var : values())
- string = string.replaceAll(var.pattern, var.binding);
- return string;
- }
- }
- static String[] stringsIn(String[] strings, int beg, int end) {
- return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
- }
- static String[] stringsBefore(String[] strings, int pos) {
- return stringsIn(strings, 0, pos);
- }
- static String[] stringsAfter(String[] strings, int pos) {
- return stringsIn(strings, pos, strings.length);
- }
- static int indexAfter(String[] strings, int pos, String tag) {
- return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
- }
- static int indexBefore(String[] strings, int pos, String tag) {
- for (int i = pos, end = strings.length; ; i++) {
- if (i == end || strings[i].endsWith(tag)) return i;
- }
- }
- static int MIN_ARITY, MAX_ARITY, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
- static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
- static HashSet<String> done = new HashSet<String>();
- public static void main(String... av) {
- for (String[] template : TEMPLATES) {
- int forLinesLimit = indexBefore(template, 0, "@each-cat@");
- String[] forLines = stringsBefore(template, forLinesLimit);
- template = stringsAfter(template, forLinesLimit);
- for (String forLine : forLines)
- expandTemplate(forLine, template);
- }
- }
- static void expandTemplate(String forLine, String[] template) {
- String[] params = forLine.split("[^0-9]+");
- if (params[0].length() == 0) params = stringsAfter(params, 1);
- System.out.println("//params="+Arrays.asList(params));
- int pcur = 0;
- MIN_ARITY = Integer.valueOf(params[pcur++]);
- MAX_ARITY = Integer.valueOf(params[pcur++]);
- MAX_RCAT = Integer.valueOf(params[pcur++]);
- MAX_REFS = Integer.valueOf(params[pcur++]);
- MAX_INTS = Integer.valueOf(params[pcur++]);
- MAX_LONGS = Integer.valueOf(params[pcur++]);
- if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
- if (MAX_RCAT >= TYPES.length) MAX_RCAT = TYPES.length - 1;
- ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
- ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
- for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
- for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
- expandTemplate(template, true, rcat, nargs, 0, 0);
- if (ALL_ARG_TYPES) break;
- expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
- if (ALL_RETURN_TYPES) break;
- }
- }
- }
- static String catstr(int rcat, int nrefs, int nints, int nlongs) {
- int nargs = nrefs + nints + nlongs;
- String cat = TCHARS[rcat] + nargs;
- if (!ALL_ARG_TYPES) cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
- return cat;
- }
- static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
- for (int isLong = 0; isLong <= 1; isLong++) {
- for (int nprims = 1; nprims <= nargs; nprims++) {
- int nrefs = nargs - nprims;
- int nints = ((1-isLong) * nprims);
- int nlongs = (isLong * nprims);
- expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
- }
- }
- }
- static void expandTemplate(String[] template, boolean topLevel,
- int rcat, int nrefs, int nints, int nlongs) {
- int nargs = nrefs + nints + nlongs;
- if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS) return;
- VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
- if (topLevel && !done.add(VAR.cat.binding)) {
- System.out.println(" //repeat "+VAR.cat.binding);
- return;
- }
- for (int i = 0; i < template.length; i++) {
- String line = template[i];
- if (line.endsWith("@each-cat@")) {
- // ignore
- } else if (line.endsWith("@each-R@")) {
- int blockEnd = indexAfter(template, i, "@end-R@");
- String[] block = stringsIn(template, i+1, blockEnd-1);
- for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
- expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
- VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
- i = blockEnd-1; continue;
- } else if (line.endsWith("@each-Tv@")) {
- int blockEnd = indexAfter(template, i, "@end-Tv@");
- String[] block = stringsIn(template, i+1, blockEnd-1);
- expandTemplate(block, false, rcat, nrefs, nints, nlongs);
- expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
- VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
- i = blockEnd-1; continue;
- } else {
- System.out.println(VAR.transform(line));
- }
- }
- }
-}
-//}}} */
-//params=[0, 3, 4, 99, 99, 99]
- static class A0 extends Adapter {
- protected A0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); }
- protected Object target() throws Throwable { return invoker.invokeExact(target); }
- protected Object targetA0() throws Throwable { return target(); }
- protected Object invoke_L() throws Throwable { return return_L(targetA0()); }
- protected int invoke_I() throws Throwable { return return_I(targetA0()); }
- protected long invoke_J() throws Throwable { return return_J(targetA0()); }
- protected float invoke_F() throws Throwable { return return_F(targetA0()); }
- protected double invoke_D() throws Throwable { return return_D(targetA0()); }
- }
- static class A1 extends Adapter {
- protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
- protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); }
- protected Object targetA1(Object a0) throws Throwable { return target(a0); }
- protected Object targetA1(int a0) throws Throwable { return target(a0); }
- protected Object targetA1(long a0) throws Throwable { return target(a0); }
- protected Object invoke_L(Object a0) throws Throwable { return return_L(targetA1(a0)); }
- protected int invoke_I(Object a0) throws Throwable { return return_I(targetA1(a0)); }
- protected long invoke_J(Object a0) throws Throwable { return return_J(targetA1(a0)); }
- protected float invoke_F(Object a0) throws Throwable { return return_F(targetA1(a0)); }
- protected double invoke_D(Object a0) throws Throwable { return return_D(targetA1(a0)); }
- protected Object invoke_L(int a0) throws Throwable { return return_L(targetA1(a0)); }
- protected int invoke_I(int a0) throws Throwable { return return_I(targetA1(a0)); }
- protected long invoke_J(int a0) throws Throwable { return return_J(targetA1(a0)); }
- protected float invoke_F(int a0) throws Throwable { return return_F(targetA1(a0)); }
- protected double invoke_D(int a0) throws Throwable { return return_D(targetA1(a0)); }
- protected Object invoke_L(long a0) throws Throwable { return return_L(targetA1(a0)); }
- protected int invoke_I(long a0) throws Throwable { return return_I(targetA1(a0)); }
- protected long invoke_J(long a0) throws Throwable { return return_J(targetA1(a0)); }
- protected float invoke_F(long a0) throws Throwable { return return_F(targetA1(a0)); }
- protected double invoke_D(long a0) throws Throwable { return return_D(targetA1(a0)); }
- }
- static class A2 extends Adapter {
- protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); }
- protected Object target(Object a0, Object a1) throws Throwable { return invoker.invokeExact(target, a0, a1); }
- protected Object targetA2(Object a0, Object a1) throws Throwable { return target(a0, a1); }
- protected Object targetA2(Object a0, int a1) throws Throwable { return target(a0, a1); }
- protected Object targetA2(int a0, int a1) throws Throwable { return target(a0, a1); }
- protected Object targetA2(Object a0, long a1) throws Throwable { return target(a0, a1); }
- protected Object targetA2(long a0, long a1) throws Throwable { return target(a0, a1); }
- protected Object invoke_L(Object a0, Object a1) throws Throwable { return return_L(targetA2(a0, a1)); }
- protected int invoke_I(Object a0, Object a1) throws Throwable { return return_I(targetA2(a0, a1)); }
- protected long invoke_J(Object a0, Object a1) throws Throwable { return return_J(targetA2(a0, a1)); }
- protected float invoke_F(Object a0, Object a1) throws Throwable { return return_F(targetA2(a0, a1)); }
- protected double invoke_D(Object a0, Object a1) throws Throwable { return return_D(targetA2(a0, a1)); }
- protected Object invoke_L(Object a0, int a1) throws Throwable { return return_L(targetA2(a0, a1)); }
- protected int invoke_I(Object a0, int a1) throws Throwable { return return_I(targetA2(a0, a1)); }
- protected long invoke_J(Object a0, int a1) throws Throwable { return return_J(targetA2(a0, a1)); }
- protected float invoke_F(Object a0, int a1) throws Throwable { return return_F(targetA2(a0, a1)); }
- protected double invoke_D(Object a0, int a1) throws Throwable { return return_D(targetA2(a0, a1)); }
- protected Object invoke_L(int a0, int a1) throws Throwable { return return_L(targetA2(a0, a1)); }
- protected int invoke_I(int a0, int a1) throws Throwable { return return_I(targetA2(a0, a1)); }
- protected long invoke_J(int a0, int a1) throws Throwable { return return_J(targetA2(a0, a1)); }
- protected float invoke_F(int a0, int a1) throws Throwable { return return_F(targetA2(a0, a1)); }
- protected double invoke_D(int a0, int a1) throws Throwable { return return_D(targetA2(a0, a1)); }
- protected Object invoke_L(Object a0, long a1) throws Throwable { return return_L(targetA2(a0, a1)); }
- protected int invoke_I(Object a0, long a1) throws Throwable { return return_I(targetA2(a0, a1)); }
- protected long invoke_J(Object a0, long a1) throws Throwable { return return_J(targetA2(a0, a1)); }
- protected float invoke_F(Object a0, long a1) throws Throwable { return return_F(targetA2(a0, a1)); }
- protected double invoke_D(Object a0, long a1) throws Throwable { return return_D(targetA2(a0, a1)); }
- protected Object invoke_L(long a0, long a1) throws Throwable { return return_L(targetA2(a0, a1)); }
- protected int invoke_I(long a0, long a1) throws Throwable { return return_I(targetA2(a0, a1)); }
- protected long invoke_J(long a0, long a1) throws Throwable { return return_J(targetA2(a0, a1)); }
- protected float invoke_F(long a0, long a1) throws Throwable { return return_F(targetA2(a0, a1)); }
- protected double invoke_D(long a0, long a1) throws Throwable { return return_D(targetA2(a0, a1)); }
- }
- static class A3 extends Adapter {
- protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); }
- protected Object target(Object a0, Object a1, Object a2) throws Throwable { return invoker.invokeExact(target, a0, a1, a2); }
- protected Object targetA3(Object a0, Object a1, Object a2) throws Throwable { return target(a0, a1, a2); }
- protected Object targetA3(Object a0, Object a1, int a2) throws Throwable { return target(a0, a1, a2); }
- protected Object targetA3(Object a0, int a1, int a2) throws Throwable { return target(a0, a1, a2); }
- protected Object targetA3(int a0, int a1, int a2) throws Throwable { return target(a0, a1, a2); }
- protected Object targetA3(Object a0, Object a1, long a2) throws Throwable { return target(a0, a1, a2); }
- protected Object targetA3(Object a0, long a1, long a2) throws Throwable { return target(a0, a1, a2); }
- protected Object targetA3(long a0, long a1, long a2) throws Throwable { return target(a0, a1, a2); }
- protected Object invoke_L(Object a0, Object a1, Object a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
- protected int invoke_I(Object a0, Object a1, Object a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
- protected long invoke_J(Object a0, Object a1, Object a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
- protected float invoke_F(Object a0, Object a1, Object a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
- protected double invoke_D(Object a0, Object a1, Object a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
- protected Object invoke_L(Object a0, Object a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
- protected int invoke_I(Object a0, Object a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
- protected long invoke_J(Object a0, Object a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
- protected float invoke_F(Object a0, Object a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
- protected double invoke_D(Object a0, Object a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
- protected Object invoke_L(Object a0, int a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
- protected int invoke_I(Object a0, int a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
- protected long invoke_J(Object a0, int a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
- protected float invoke_F(Object a0, int a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
- protected double invoke_D(Object a0, int a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
- protected Object invoke_L(int a0, int a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
- protected int invoke_I(int a0, int a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
- protected long invoke_J(int a0, int a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
- protected float invoke_F(int a0, int a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
- protected double invoke_D(int a0, int a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
- protected Object invoke_L(Object a0, Object a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
- protected int invoke_I(Object a0, Object a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
- protected long invoke_J(Object a0, Object a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
- protected float invoke_F(Object a0, Object a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
- protected double invoke_D(Object a0, Object a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
- protected Object invoke_L(Object a0, long a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
- protected int invoke_I(Object a0, long a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
- protected long invoke_J(Object a0, long a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
- protected float invoke_F(Object a0, long a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
- protected double invoke_D(Object a0, long a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
- protected Object invoke_L(long a0, long a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
- protected int invoke_I(long a0, long a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
- protected long invoke_J(long a0, long a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
- protected float invoke_F(long a0, long a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
- protected double invoke_D(long a0, long a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
- }
-//params=[4, 5, 2, 99, 99, 99]
- static class A4 extends Adapter {
- protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); }
- protected Object target(Object a0, Object a1, Object a2, Object a3) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); }
- protected Object targetA4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return target(a0, a1, a2, a3); }
- protected Object targetA4(Object a0, Object a1, Object a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
- protected Object targetA4(Object a0, Object a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
- protected Object targetA4(Object a0, int a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
- protected Object targetA4(int a0, int a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
- protected Object targetA4(Object a0, Object a1, Object a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
- protected Object targetA4(Object a0, Object a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
- protected Object targetA4(Object a0, long a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
- protected Object targetA4(long a0, long a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
- protected int invoke_I(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
- protected long invoke_J(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
- protected Object invoke_L(Object a0, Object a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
- protected int invoke_I(Object a0, Object a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
- protected long invoke_J(Object a0, Object a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
- protected Object invoke_L(Object a0, int a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
- protected int invoke_I(Object a0, int a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
- protected long invoke_J(Object a0, int a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
- protected Object invoke_L(int a0, int a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
- protected int invoke_I(int a0, int a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
- protected long invoke_J(int a0, int a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
- protected int invoke_I(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
- protected long invoke_J(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
- protected Object invoke_L(Object a0, Object a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
- protected int invoke_I(Object a0, Object a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
- protected long invoke_J(Object a0, Object a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
- protected Object invoke_L(Object a0, long a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
- protected int invoke_I(Object a0, long a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
- protected long invoke_J(Object a0, long a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
- protected Object invoke_L(long a0, long a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
- protected int invoke_I(long a0, long a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
- protected long invoke_J(long a0, long a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
- }
- static class A5 extends Adapter {
- protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); }
- protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4); }
- protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object targetA5(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object targetA5(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object targetA5(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object targetA5(int a0, int a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object targetA5(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object targetA5(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object targetA5(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object targetA5(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object targetA5(long a0, long a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- protected Object invoke_L(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- protected Object invoke_L(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- protected Object invoke_L(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- protected Object invoke_L(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
- protected int invoke_I(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
- protected long invoke_J(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
- }
-//params=[6, 10, 2, 99, 0, 99]
- static class A6 extends Adapter {
- protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); }
- protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5); }
- protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
- protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
- protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
- protected Object targetA6(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
- protected Object targetA6(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
- protected Object targetA6(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
- protected Object targetA6(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
- protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
- }
- static class A7 extends Adapter {
- protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); }
- protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6); }
- protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
- protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
- protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
- protected Object targetA7(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
- protected Object targetA7(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
- protected Object targetA7(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
- protected Object targetA7(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
- protected Object targetA7(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
- }
- static class A8 extends Adapter {
- protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); }
- protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object targetA8(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object targetA8(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object targetA8(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object targetA8(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object targetA8(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
- }
- static class A9 extends Adapter {
- protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); }
- protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object targetA9(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object targetA9(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object targetA9(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object targetA9(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object targetA9(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
- }
- static class A10 extends Adapter {
- protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
- protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
- protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); }
- protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object targetA10(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
- }
-}
--- a/jdk/src/share/classes/java/dyn/VolatileCallSite.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
- * An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates
- * to its call site target immediately, even if the update occurs in another thread.
- * There may be a performance penalty for such tight coupling between threads.
- * <p>
- * Unlike {@code MutableCallSite}, there is no
- * {@linkplain MutableCallSite#syncAll syncAll operation} on volatile
- * call sites, since every write to a volatile variable is implicitly
- * synchronized with reader threads.
- * <p>
- * In other respects, a {@code VolatileCallSite} is interchangeable
- * with {@code MutableCallSite}.
- * @see MutableCallSite
- * @author John Rose, JSR 292 EG
- */
-public class VolatileCallSite extends CallSite {
- /**
- * Creates a call site with a volatile binding to its target.
- * The initial target is set to a method handle
- * of the given type which will throw an {@code IllegalStateException} if called.
- * @param type the method type that this call site will have
- * @throws NullPointerException if the proposed type is null
- */
- public VolatileCallSite(MethodType type) {
- super(type);
- }
-
- /**
- * Creates a call site with a volatile binding to its target.
- * The target is set to the given value.
- * @param target the method handle that will be the initial target of the call site
- * @throws NullPointerException if the proposed target is null
- */
- public VolatileCallSite(MethodHandle target) {
- super(target);
- }
-
- /**
- * Returns the target method of the call site, which behaves
- * like a {@code volatile} field of the {@code VolatileCallSite}.
- * <p>
- * The interactions of {@code getTarget} with memory are the same
- * as of a read from a {@code volatile} field.
- * <p>
- * In particular, the current thread is required to issue a fresh
- * read of the target from memory, and must not fail to see
- * a recent update to the target by another thread.
- *
- * @return the linkage state of this call site, a method handle which can change over time
- * @see #setTarget
- */
- @Override public final MethodHandle getTarget() {
- return getTargetVolatile();
- }
-
- /**
- * Updates the target method of this call site, as a volatile variable.
- * The type of the new target must agree with the type of the old target.
- * <p>
- * The interactions with memory are the same as of a write to a volatile field.
- * In particular, any threads is guaranteed to see the updated target
- * the next time it calls {@code getTarget}.
- * @param newTarget the new target
- * @throws NullPointerException if the proposed new target is null
- * @throws WrongMethodTypeException if the proposed new target
- * has a method type that differs from the previous target
- * @see #getTarget
- */
- @Override public void setTarget(MethodHandle newTarget) {
- checkTargetChange(getTargetVolatile(), newTarget);
- setTargetVolatile(newTarget);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public final MethodHandle dynamicInvoker() {
- return makeDynamicInvoker();
- }
-}
--- a/jdk/src/share/classes/java/dyn/WrongMethodTypeException.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.dyn;
-
-/**
- * Thrown to indicate that code has attempted to call a method handle
- * via the wrong method type. As with the bytecode representation of
- * normal Java method calls, method handle calls are strongly typed
- * to a specific type descriptor associated with a call site.
- * <p>
- * This exception may also be thrown when two method handles are
- * composed, and the system detects that their types cannot be
- * matched up correctly. This amounts to an early evaluation
- * of the type mismatch, at method handle construction time,
- * instead of when the mismatched method handle is called.
- *
- * @author John Rose, JSR 292 EG
- * @since 1.7
- */
-public class WrongMethodTypeException extends RuntimeException {
- private static final long serialVersionUID = 292L;
-
- /**
- * Constructs a {@code WrongMethodTypeException} with no detail message.
- */
- public WrongMethodTypeException() {
- super();
- }
-
- /**
- * Constructs a {@code WrongMethodTypeException} with the specified
- * detail message.
- *
- * @param s the detail message.
- */
- public WrongMethodTypeException(String s) {
- super(s);
- }
-}
--- a/jdk/src/share/classes/java/dyn/package-info.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,478 +0,0 @@
-/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * The {@code java.lang.invoke} package contains dynamic language support provided directly by
- * the Java core class libraries and virtual machine.
- *
- * <p style="font-size:smaller;">
- * <em>Historic Note:</em> In some early versions of Java SE 7,
- * the name of this package is {@code java.dyn}.
- * <p>
- * Certain types in this package have special relations to dynamic
- * language support in the virtual machine:
- * <ul>
- * <li>The class {@link java.dyn.MethodHandle MethodHandle} contains
- * <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
- * which can be linked regardless of their type descriptor.
- * Normally, method linkage requires exact matching of type descriptors.
- * </li>
- *
- * <li>The JVM bytecode format supports immediate constants of
- * the classes {@link java.dyn.MethodHandle MethodHandle} and {@link java.dyn.MethodType MethodType}.
- * </li>
- * </ul>
- *
- * <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2>
- * <em>The following low-level information is presented here as a preview of
- * changes being made to the Java Virtual Machine specification for JSR 292.
- * This information will be incorporated in a future version of the JVM specification.</em>
- *
- * <h3><a name="indyinsn"></a>{@code invokedynamic} instruction format</h3>
- * In bytecode, an {@code invokedynamic} instruction is formatted as five bytes.
- * The first byte is the opcode 186 (hexadecimal {@code BA}).
- * The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions).
- * The final two bytes are reserved for future use and required to be zero.
- * The constant pool reference of an {@code invokedynamic} instruction is to a entry
- * with tag {@code CONSTANT_InvokeDynamic} (decimal 18). See below for its format.
- * The entry specifies the following information:
- * <ul>
- * <li>a bootstrap method (a {@link java.dyn.MethodHandle MethodHandle} constant)</li>
- * <li>the dynamic invocation name (a UTF8 string)</li>
- * <li>the argument and return types of the call (encoded as a type descriptor in a UTF8 string)</li>
- * <li>optionally, a sequence of additional <em>static arguments</em> to the bootstrap method ({@code ldc}-type constants)</li>
- * </ul>
- * <p>
- * Each instance of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
- * Multiple instances of an {@code invokedynamic} instruction can share a single
- * {@code CONSTANT_InvokeDynamic} entry.
- * In any case, distinct call sites always have distinct linkage state.
- * <p>
- * A dynamic call site is originally in an unlinked state. In this state, there is
- * no target method for the call site to invoke.
- * A dynamic call site is linked by means of a bootstrap method,
- * as <a href="#bsm">described below</a>.
- *
- * <p style="font-size:smaller;">
- * <em>Historic Note:</em> Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
- * instead of a {@code CONSTANT_InvokeDynamic}. In earlier, obsolete versions of this API, the
- * bootstrap method was specified dynamically, in a per-class basis, during class initialization.
- *
- * <h3><a name="indycon"></a>constant pool entries for {@code invokedynamic} instructions</h3>
- * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18),
- * it must contain exactly four more bytes after the tag.
- * These bytes are interpreted as two 16-bit indexes, in the usual {@code u2} format.
- * The first pair of bytes after the tag must be an index into a side table called the
- * <em>bootstrap method table</em>, which is stored in the {@code BootstrapMethods}
- * attribute as <a href="#bsmattr">described below</a>.
- * The second pair of bytes must be an index to a {@code CONSTANT_NameAndType}.
- * <p>
- * The first index specifies a bootstrap method used by the associated dynamic call sites.
- * The second index specifies the method name, argument types, and return type of the dynamic call site.
- * The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref},
- * except that the bootstrap method specifier reference replaces
- * the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry.
- *
- * <h3><a name="mtcon"></a>constant pool entries for {@linkplain java.dyn.MethodType method types}</h3>
- * If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
- * it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
- * entry which represents a method type descriptor.
- * <p>
- * The JVM will ensure that on first
- * execution of an {@code ldc} instruction for this entry, a {@link java.dyn.MethodType MethodType}
- * will be created which represents the type descriptor.
- * Any classes mentioned in the {@code MethodType} will be loaded if necessary,
- * but not initialized.
- * Access checking and error reporting is performed exactly as it is for
- * references by {@code ldc} instructions to {@code CONSTANT_Class} constants.
- *
- * <h3><a name="mhcon"></a>constant pool entries for {@linkplain java.dyn.MethodHandle method handles}</h3>
- * If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
- * it must contain exactly three more bytes. The first byte after the tag is a subtag
- * value which must be in the range 1 through 9, and the last two must be an index to a
- * {@code CONSTANT_Fieldref}, {@code CONSTANT_Methodref}, or
- * {@code CONSTANT_InterfaceMethodref} entry which represents a field or method
- * for which a method handle is to be created.
- * Furthermore, the subtag value and the type of the constant index value
- * must agree according to the table below.
- * <p>
- * The JVM will ensure that on first execution of an {@code ldc} instruction
- * for this entry, a {@link java.dyn.MethodHandle MethodHandle} will be created which represents
- * the field or method reference, according to the specific mode implied by the subtag.
- * <p>
- * As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
- * the {@code Class} or {@code MethodType} object which reifies the field or method's
- * type is created. Any classes mentioned in this reification will be loaded if necessary,
- * but not initialized, and access checking and error reporting performed as usual.
- * <p>
- * Unlike the reflective {@code Lookup} API, there are no security manager calls made
- * when these constants are resolved.
- * <p>
- * The method handle itself will have a type and behavior determined by the subtag as follows:
- * <code>
- * <table border=1 cellpadding=5 summary="CONSTANT_MethodHandle subtypes">
- * <tr><th>N</th><th>subtag name</th><th>member</th><th>MH type</th><th>bytecode behavior</th><th>lookup expression</th></tr>
- * <tr><td>1</td><td>REF_getField</td><td>C.f:T</td><td>(C)T</td><td>getfield C.f:T</td>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findGetter findGetter(C.class,"f",T.class)}</td></tr>
- * <tr><td>2</td><td>REF_getStatic</td><td>C.f:T</td><td>( )T</td><td>getstatic C.f:T</td>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findStaticGetter findStaticGetter(C.class,"f",T.class)}</td></tr>
- * <tr><td>3</td><td>REF_putField</td><td>C.f:T</td><td>(C,T)void</td><td>putfield C.f:T</td>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findSetter findSetter(C.class,"f",T.class)}</td></tr>
- * <tr><td>4</td><td>REF_putStatic</td><td>C.f:T</td><td>(T)void</td><td>putstatic C.f:T</td>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findStaticSetter findStaticSetter(C.class,"f",T.class)}</td></tr>
- * <tr><td>5</td><td>REF_invokeVirtual</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokevirtual C.m(A*)T</td>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
- * <tr><td>6</td><td>REF_invokeStatic</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokestatic C.m(A*)T</td>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findStatic findStatic(C.class,"m",MT)}</td></tr>
- * <tr><td>7</td><td>REF_invokeSpecial</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokespecial C.m(A*)T</td>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findSpecial findSpecial(C.class,"m",MT,this.class)}</td></tr>
- * <tr><td>8</td><td>REF_newInvokeSpecial</td><td>C.<init>(A*)void</td><td>(A*)C</td><td>new C; dup; invokespecial C.<init>(A*)void</td>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findConstructor findConstructor(C.class,MT)}</td></tr>
- * <tr><td>9</td><td>REF_invokeInterface</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokeinterface C.m(A*)T</td>
- * <td>{@linkplain java.dyn.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
- * </table>
- * </code>
- * Here, the type {@code C} is taken from the {@code CONSTANT_Class} reference associated
- * with the {@code CONSTANT_NameAndType} descriptor.
- * The field name {@code f} or method name {@code m} is taken from the {@code CONSTANT_NameAndType}
- * as is the result type {@code T} and (in the case of a method or constructor) the argument type sequence
- * {@code A*}.
- * <p>
- * Each method handle constant has an equivalent instruction sequence called its <em>bytecode behavior</em>.
- * In general, creating a method handle constant can be done in exactly the same circumstances that
- * the JVM would successfully resolve the symbolic references in the bytecode behavior.
- * Also, the type of a method handle constant is such that a valid {@code invokeExact} call
- * on the method handle has exactly the same JVM stack effects as the <em>bytecode behavior</em>.
- * Finally, calling a method handle constant on a valid set of arguments has exactly the same effect
- * and returns the same result (if any) as the corresponding <em>bytecode behavior</em>.
- * <p>
- * Each method handle constant also has an equivalent reflective <em>lookup expression</em>,
- * which is a query to a method in {@link java.dyn.MethodHandles.Lookup}.
- * In the example lookup method expression given in the table above, the name {@code MT}
- * stands for a {@code MethodType} built from {@code T} and the sequence of argument types {@code A*}.
- * (Note that the type {@code C} is not prepended to the query type {@code MT} even if the member is non-static.)
- * In the case of {@code findSpecial}, the name {@code this.class} refers to the class containing
- * the bytecodes.
- * <p>
- * The special name {@code <clinit>} is not allowed.
- * The special name {@code <init>} is not allowed except for subtag 8 as shown.
- * <p>
- * The JVM verifier and linker apply the same access checks and restrictions for these references as for the hypothetical
- * bytecode instructions specified in the last column of the table.
- * A method handle constant will successfully resolve to a method handle if the symbolic references
- * of the corresponding bytecode instruction(s) would also resolve successfully.
- * Otherwise, an attempt to resolve the constant will throw equivalent linkage errors.
- * In particular, method handles to
- * private and protected members can be created in exactly those classes for which the corresponding
- * normal accesses are legal.
- * <p>
- * A constant may refer to a method or constructor with the {@code varargs}
- * bit (hexadecimal {@code 0x0080}) set in its modifier bitmask.
- * The method handle constant produced for such a method behaves as if
- * it were created by {@link java.dyn.MethodHandle#asVarargsCollector asVarargsCollector}.
- * In other words, the constant method handle will exhibit variable arity,
- * when invoked via {@code invokeGeneric}.
- * On the other hand, its behavior with respect to {@code invokeExact} will be the same
- * as if the {@code varargs} bit were not set.
- * <p>
- * Although the {@code CONSTANT_MethodHandle} and {@code CONSTANT_MethodType} constant types
- * resolve class names, they do not force class initialization.
- * Method handle constants for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
- * may force class initialization on their first invocation, just like the corresponding bytecodes.
- * <p>
- * The rules of section 5.4.3 of the
- * <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#73492">JVM Specification</a>
- * apply to the resolution of {@code CONSTANT_MethodType}, {@code CONSTANT_MethodHandle},
- * and {@code CONSTANT_InvokeDynamic} constants,
- * by the execution of {@code invokedynamic} and {@code ldc} instructions.
- * (Roughly speaking, this means that every use of a constant pool entry
- * must lead to the same outcome.
- * If the resolution succeeds, the same object reference is produced
- * by every subsequent execution of the same instruction.
- * If the resolution of the constant causes an error to occur,
- * the same error will be re-thrown on every subsequent attempt
- * to use this particular constant.)
- * <p>
- * Constants created by the resolution of these constant pool types are not necessarily
- * interned. Except for {@code CONSTANT_Class} and {@code CONSTANT_String} entries,
- * two distinct constant pool entries might not resolve to the same reference
- * even if they contain the same symbolic reference.
- *
- * <h2><a name="bsm"></a>Bootstrap Methods</h2>
- * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
- * the call site must first be <em>linked</em>.
- * Linking is accomplished by calling a <em>bootstrap method</em>
- * which is given the static information content of the call site,
- * and which must produce a {@link java.dyn.MethodHandle method handle}
- * that gives the behavior of the call site.
- * <p>
- * Each {@code invokedynamic} instruction statically specifies its own
- * bootstrap method as a constant pool reference.
- * The constant pool reference also specifies the call site's name and type descriptor,
- * just like {@code invokevirtual} and the other invoke instructions.
- * <p>
- * Linking starts with resolving the constant pool entry for the
- * bootstrap method, and resolving a {@link java.dyn.MethodType MethodType} object for
- * the type descriptor of the dynamic call site.
- * This resolution process may trigger class loading.
- * It may therefore throw an error if a class fails to load.
- * This error becomes the abnormal termination of the dynamic
- * call site execution.
- * Linkage does not trigger class initialization.
- * <p>
- * Next, the bootstrap method call is started, with at least four values being stacked:
- * <ul>
- * <li>a {@code MethodHandle}, the resolved bootstrap method itself </li>
- * <li>a {@code MethodHandles.Lookup}, a lookup object on the <em>caller class</em> in which dynamic call site occurs </li>
- * <li>a {@code String}, the method name mentioned in the call site </li>
- * <li>a {@code MethodType}, the resolved type descriptor of the call </li>
- * <li>optionally, one or more <a href="#args">additional static arguments</a> </li>
- * </ul>
- * The method handle is then applied to the other values as if by
- * {@link java.dyn.MethodHandle#invokeGeneric invokeGeneric}.
- * The returned result must be a {@link java.dyn.CallSite CallSite} (or a subclass).
- * The type of the call site's target must be exactly equal to the type
- * derived from the dynamic call site's type descriptor and passed to
- * the bootstrap method.
- * The call site then becomes permanently linked to the dynamic call site.
- * <p>
- * As long as each bootstrap method can be correctly invoked
- * by <code>invokeGeneric</code>, its detailed type is arbitrary.
- * For example, the first argument could be {@code Object}
- * instead of {@code MethodHandles.Lookup}, and the return type
- * could also be {@code Object} instead of {@code CallSite}.
- * <p>
- * As with any method handle constant, a {@code varargs} modifier bit
- * on the bootstrap method is ignored.
- * <p>
- * Note that the first argument of the bootstrap method cannot be
- * a simple {@code Class} reference. (This is a change from earlier
- * versions of this specification. If the caller class is needed,
- * it is easy to {@linkplain java.dyn.MethodHandles.Lookup#lookupClass() extract it}
- * from the {@code Lookup} object.)
- * <p>
- * After resolution, the linkage process may fail in a variety of ways.
- * All failures are reported by an {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrapError},
- * which is thrown as the abnormal termination of the dynamic call
- * site execution.
- * The following circumstances will cause this:
- * <ul>
- * <li>the index to the bootstrap method specifier is out of range </li>
- * <li>the bootstrap method cannot be resolved </li>
- * <li>the {@code MethodType} to pass to the bootstrap method cannot be resolved </li>
- * <li>a static argument to the bootstrap method cannot be resolved
- * (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType},
- * or {@code CONSTANT_MethodHandle} argument cannot be linked) </li>
- * <li>the bootstrap method has the wrong arity,
- * causing {@code invokeGeneric} to throw {@code WrongMethodTypeException} </li>
- * <li>the bootstrap method has a wrong argument or return type </li>
- * <li>the bootstrap method invocation completes abnormally </li>
- * <li>the result from the bootstrap invocation is not a reference to
- * an object of type {@link java.dyn.CallSite CallSite} </li>
- * <li>the target of the {@code CallSite} does not have a target of
- * the expected {@code MethodType} </li>
- * </ul>
- *
- * <h3><a name="linktime"></a>timing of linkage</h3>
- * A dynamic call site is linked just before its first execution.
- * The bootstrap method call implementing the linkage occurs within
- * a thread that is attempting a first execution.
- * <p>
- * If there are several such threads, the bootstrap method may be
- * invoked in several threads concurrently.
- * Therefore, bootstrap methods which access global application
- * data must take the usual precautions against race conditions.
- * In any case, every {@code invokedynamic} instruction is either
- * unlinked or linked to a unique {@code CallSite} object.
- * <p>
- * In an application which requires dynamic call sites with individually
- * mutable behaviors, their bootstrap methods should produce distinct
- * {@link java.dyn.CallSite CallSite} objects, one for each linkage request.
- * Alternatively, an application can link a single {@code CallSite} object
- * to several {@code invokedynamic} instructions, in which case
- * a change to the target method will become visible at each of
- * the instructions.
- * <p>
- * If several threads simultaneously execute a bootstrap method for a single dynamic
- * call site, the JVM must choose one {@code CallSite} object and install it visibly to
- * all threads. Any other bootstrap method calls are allowed to complete, but their
- * results are ignored, and their dynamic call site invocations proceed with the originally
- * chosen target object.
- *
- * <p style="font-size:smaller;">
- * <em>Historic Note:</em> Unlike some previous versions of this specification,
- * these rules do not enable the JVM to duplicate dynamic call sites,
- * or to issue “causeless” bootstrap method calls.
- * Every dynamic call site transitions at most once from unlinked to linked,
- * just before its first invocation.
- *
- * <h3><a name="bsmattr">the {@code BootstrapMethods} attribute </h3>
- * Each {@code CONSTANT_InvokeDynamic} entry contains an index which references
- * a bootstrap method specifier; all such specifiers are contained in a separate array.
- * This array is defined by a class attribute named {@code BootstrapMethods}.
- * The body of this attribute consists of a sequence of byte pairs, all interpreted as
- * as 16-bit counts or constant pool indexes, in the {@code u2} format.
- * The attribute body starts with a count of bootstrap method specifiers,
- * which is immediately followed by the sequence of specifiers.
- * <p>
- * Each bootstrap method specifier contains an index to a
- * {@code CONSTANT_MethodHandle} constant, which is the bootstrap
- * method itself.
- * This is followed by a count, and then a sequence (perhaps empty) of
- * indexes to <a href="#args">additional static arguments</a>
- * for the bootstrap method.
- * <p>
- * During class loading, the verifier must check the structure of the
- * {@code BootstrapMethods} attribute. In particular, each constant
- * pool index must be of the correct type. A bootstrap method index
- * must refer to a {@code CONSTANT_MethodHandle} (tag 15).
- * Every other index must refer to a valid operand of an
- * {@code ldc_w} or {@code ldc2_w} instruction (tag 3..8 or 15..16).
- *
- * <h3><a name="args">static arguments to the bootstrap method</h3>
- * An {@code invokedynamic} instruction specifies at least three arguments
- * to pass to its bootstrap method:
- * The caller class (expressed as a {@link java.dyn.MethodHandles.Lookup Lookup object},
- * the name (extracted from the {@code CONSTANT_NameAndType} entry),
- * and the type (also extracted from the {@code CONSTANT_NameAndType} entry).
- * The {@code invokedynamic} instruction may specify additional metadata values
- * to pass to its bootstrap method.
- * Collectively, these values are called <em>static arguments</em> to the
- * {@code invokedynamic} instruction, because they are used once at link
- * time to determine the instruction's behavior on subsequent sets of
- * <em>dynamic arguments</em>.
- * <p>
- * Static arguments are used to communicate application-specific meta-data
- * to the bootstrap method.
- * Drawn from the constant pool, they may include references to classes, method handles,
- * strings, or numeric data that may be relevant to the task of linking that particular call site.
- * <p>
- * Static arguments are specified constant pool indexes stored in the {@code BootstrapMethods} attribute.
- * Before the bootstrap method is invoked, each index is used to compute an {@code Object}
- * reference to the indexed value in the constant pool.
- * The valid constant pool entries are listed in this table:
- * <code>
- * <table border=1 cellpadding=5 summary="Static argument types">
- * <tr><th>entry type</th><th>argument type</th><th>argument value</th></tr>
- * <tr><td>CONSTANT_String</td><td><code>java.lang.String</code></td><td>the indexed string literal</td></tr>
- * <tr><td>CONSTANT_Class</td><td><code>java.lang.Class</code></td><td>the indexed class, resolved</td></tr>
- * <tr><td>CONSTANT_Integer</td><td><code>java.lang.Integer</code></td><td>the indexed int value</td></tr>
- * <tr><td>CONSTANT_Long</td><td><code>java.lang.Long</code></td><td>the indexed long value</td></tr>
- * <tr><td>CONSTANT_Float</td><td><code>java.lang.Float</code></td><td>the indexed float value</td></tr>
- * <tr><td>CONSTANT_Double</td><td><code>java.lang.Double</code></td><td>the indexed double value</td></tr>
- * <tr><td>CONSTANT_MethodHandle</td><td><code>java.dyn.MethodHandle</code></td><td>the indexed method handle constant</td></tr>
- * <tr><td>CONSTANT_MethodType</td><td><code>java.dyn.MethodType</code></td><td>the indexed method type constant</td></tr>
- * </table>
- * </code>
- * <p>
- * If a given {@code invokedynamic} instruction specifies no static arguments,
- * the instruction's bootstrap method will be invoked on three arguments,
- * conveying the instruction's caller class, name, and method type.
- * If the {@code invokedynamic} instruction specifies one or more static arguments,
- * those values will be passed as additional arguments to the method handle.
- * (Note that because there is a limit of 255 arguments to any method,
- * at most 252 extra arguments can be supplied.)
- * The bootstrap method will be invoked as if by either {@code invokeGeneric}
- * or {@code invokeWithArguments}. (There is no way to tell the difference.)
- * <p>
- * The normal argument conversion rules for {@code invokeGeneric} apply to all stacked arguments.
- * For example, if a pushed value is a primitive type, it may be converted to a reference by boxing conversion.
- * If the bootstrap method is a variable arity method (its modifier bit {@code 0x0080} is set),
- * then some or all of the arguments specified here may be collected into a trailing array parameter.
- * (This is not a special rule, but rather a useful consequence of the interaction
- * between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods,
- * and the {@code java.dyn.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
- * <p>
- * Given these rules, here are examples of legal bootstrap method declarations,
- * given various numbers {@code N} of extra arguments.
- * The first rows (marked {@code *}) will work for any number of extra arguments.
- * <code>
- * <table border=1 cellpadding=5 summary="Static argument types">
- * <tr><th>N</th><th>sample bootstrap method</th></tr>
- * <tr><td>*</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
- * <tr><td>*</td><td><code>CallSite bootstrap(Object... args)</code></td></tr>
- * <tr><td>*</td><td><code>CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs)</code></td></tr>
- * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type)</code></td></tr>
- * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, Object... nameAndType)</code></td></tr>
- * <tr><td>1</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg)</code></td></tr>
- * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
- * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String... args)</code></td></tr>
- * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)</code></td></tr>
- * </table>
- * </code>
- * The last example assumes that the extra arguments are of type
- * {@code CONSTANT_String} and {@code CONSTANT_Integer}, respectively.
- * The second-to-last example assumes that all extra arguments are of type
- * {@code CONSTANT_String}.
- * The other examples work with all types of extra arguments.
- * <p>
- * As noted above, the actual method type of the bootstrap method can vary.
- * For example, the fourth argument could be {@code MethodHandle},
- * if that is the type of the corresponding constant in
- * the {@code CONSTANT_InvokeDynamic} entry.
- * In that case, the {@code invokeGeneric} call will pass the extra method handle
- * constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric}
- * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
- * (If a string constant were passed instead, by badly generated code, that cast would then fail,
- * resulting in an {@code InvokeDynamicBootstrapError}.)
- * <p>
- * Extra bootstrap method arguments are intended to allow language implementors
- * to safely and compactly encode metadata.
- * In principle, the name and extra arguments are redundant,
- * since each call site could be given its own unique bootstrap method.
- * Such a practice is likely to produce large class files and constant pools.
- *
- * <h2><a name="structs"></a>Structure Summary</h2>
- * <blockquote><pre>// summary of constant and attribute structures
-struct CONSTANT_MethodHandle_info {
- u1 tag = 15;
- u1 reference_kind; // 1..8 (one of REF_invokeVirtual, etc.)
- u2 reference_index; // index to CONSTANT_Fieldref or *Methodref
-}
-struct CONSTANT_MethodType_info {
- u1 tag = 16;
- u2 descriptor_index; // index to CONSTANT_Utf8, as in NameAndType
-}
-struct CONSTANT_InvokeDynamic_info {
- u1 tag = 18;
- u2 bootstrap_method_attr_index; // index into BootstrapMethods_attr
- u2 name_and_type_index; // index to CONSTANT_NameAndType, as in Methodref
-}
-struct BootstrapMethods_attr {
- u2 name; // CONSTANT_Utf8 = "BootstrapMethods"
- u4 size;
- u2 bootstrap_method_count;
- struct bootstrap_method_specifier {
- u2 bootstrap_method_ref; // index to CONSTANT_MethodHandle
- u2 bootstrap_argument_count;
- u2 bootstrap_arguments[bootstrap_argument_count]; // constant pool indexes
- } bootstrap_methods[bootstrap_method_count];
-}
- * </pre></blockquote>
- *
- * @author John Rose, JSR 292 EG
- */
-
-package java.dyn;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/BootstrapMethodError.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+/**
+ * Thrown to indicate that an {@code invokedynamic} instruction has
+ * failed to find its bootstrap method,
+ * or the bootstrap method has failed to provide a
+ * {@linkplain java.lang.invoke.CallSite call site} with a {@linkplain java.lang.invoke.CallSite#getTarget target}
+ * of the correct {@linkplain java.lang.invoke.MethodHandle#type method type}.
+ *
+ * @author John Rose, JSR 292 EG
+ * @since 1.7
+ */
+public class BootstrapMethodError extends LinkageError {
+ private static final long serialVersionUID = 292L;
+
+ /**
+ * Constructs an {@code BootstrapMethodError} with no detail message.
+ */
+ public BootstrapMethodError() {
+ super();
+ }
+
+ /**
+ * Constructs an {@code BootstrapMethodError} with the specified
+ * detail message.
+ *
+ * @param s the detail message.
+ */
+ public BootstrapMethodError(String s) {
+ super(s);
+ }
+
+ /**
+ * Constructs a {@code BootstrapMethodError} with the specified
+ * detail message and cause.
+ *
+ * @param s the detail message.
+ * @param cause the cause, may be {@code null}.
+ */
+ public BootstrapMethodError(String s, Throwable cause) {
+ super(s, cause);
+ }
+
+ /**
+ * Constructs a {@code BootstrapMethodError} with the specified
+ * cause.
+ *
+ * @param cause the cause, may be {@code null}.
+ */
+ public BootstrapMethodError(Throwable cause) {
+ // cf. Throwable(Throwable cause) constructor.
+ super(cause == null ? null : cause.toString());
+ initCause(cause);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/ClassValue.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang;
+
+import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Lazily associate a computed value with (potentially) every type.
+ * For example, if a dynamic language needs to construct a message dispatch
+ * table for each class encountered at a message send call site,
+ * it can use a {@code ClassValue} to cache information needed to
+ * perform the message send quickly, for each class encountered.
+ * @author John Rose, JSR 292 EG
+ * @since 1.7
+ */
+public abstract class ClassValue<T> {
+ /**
+ * Computes the given class's derived value for this {@code ClassValue}.
+ * <p>
+ * This method will be invoked within the first thread that accesses
+ * the value with the {@link #get get} method.
+ * <p>
+ * Normally, this method is invoked at most once per class,
+ * but it may be invoked again if there has been a call to
+ * {@link #remove remove}.
+ * <p>
+ * If this method throws an exception, the corresponding call to {@code get}
+ * will terminate abnormally with that exception, and no class value will be recorded.
+ *
+ * @param type the type whose class value must be computed
+ * @return the newly computed value associated with this {@code ClassValue}, for the given class or interface
+ * @see #get
+ * @see #remove
+ */
+ protected abstract T computeValue(Class<?> type);
+
+ /**
+ * Returns the value for the given class.
+ * If no value has yet been computed, it is obtained by
+ * an invocation of the {@link #computeValue computeValue} method.
+ * <p>
+ * The actual installation of the value on the class
+ * is performed atomically.
+ * At that point, if several racing threads have
+ * computed values, one is chosen, and returned to
+ * all the racing threads.
+ * <p>
+ * The {@code type} parameter is typically a class, but it may be any type,
+ * such as an interface, a primitive type (like {@code int.class}), or {@code void.class}.
+ * <p>
+ * In the absence of {@code remove} calls, a class value has a simple
+ * state diagram: uninitialized and initialized.
+ * When {@code remove} calls are made,
+ * the rules for value observation are more complex.
+ * See the documentation for {@link #remove remove} for more information.
+ *
+ * @param type the type whose class value must be computed or retrieved
+ * @return the current value associated with this {@code ClassValue}, for the given class or interface
+ * @throws NullPointerException if the argument is null
+ * @see #remove
+ * @see #computeValue
+ */
+ public T get(Class<?> type) {
+ ClassValueMap map = getMap(type);
+ if (map != null) {
+ Object x = map.get(this);
+ if (x != null) {
+ return (T) map.unmaskNull(x);
+ }
+ }
+ return setComputedValue(type);
+ }
+
+ /**
+ * Removes the associated value for the given class.
+ * If this value is subsequently {@linkplain #get read} for the same class,
+ * its value will be reinitialized by invoking its {@link #computeValue computeValue} method.
+ * This may result in an additional invocation of the
+ * {@code computeValue computeValue} method for the given class.
+ * <p>
+ * In order to explain the interaction between {@code get} and {@code remove} calls,
+ * we must model the state transitions of a class value to take into account
+ * the alternation between uninitialized and initialized states.
+ * To do this, number these states sequentially from zero, and note that
+ * uninitialized (or removed) states are numbered with even numbers,
+ * while initialized (or re-initialized) states have odd numbers.
+ * <p>
+ * When a thread {@code T} removes a class value in state {@code 2N},
+ * nothing happens, since the class value is already uninitialized.
+ * Otherwise, the state is advanced atomically to {@code 2N+1}.
+ * <p>
+ * When a thread {@code T} queries a class value in state {@code 2N},
+ * the thread first attempts to initialize the class value to state {@code 2N+1}
+ * by invoking {@code computeValue} and installing the resulting value.
+ * <p>
+ * When {@code T} attempts to install the newly computed value,
+ * if the state is still at {@code 2N}, the class value will be initialized
+ * with the computed value, advancing it to state {@code 2N+1}.
+ * <p>
+ * Otherwise, whether the new state is even or odd,
+ * {@code T} will discard the newly computed value
+ * and retry the {@code get} operation.
+ * <p>
+ * Discarding and retrying is an important proviso,
+ * since otherwise {@code T} could potentially install
+ * a disastrously stale value. For example:
+ * <ul>
+ * <li>{@code T} calls {@code CV.get(C)} and sees state {@code 2N}
+ * <li>{@code T} quickly computes a time-dependent value {@code V0} and gets ready to install it
+ * <li>{@code T} is hit by an unlucky paging or scheduling event, and goes to sleep for a long time
+ * <li>...meanwhile, {@code T2} also calls {@code CV.get(C)} and sees state {@code 2N}
+ * <li>{@code T2} quickly computes a similar time-dependent value {@code V1} and installs it on {@code CV.get(C)}
+ * <li>{@code T2} (or a third thread) then calls {@code CV.remove(C)}, undoing {@code T2}'s work
+ * <li> the previous actions of {@code T2} are repeated several times
+ * <li> also, the relevant computed values change over time: {@code V1}, {@code V2}, ...
+ * <li>...meanwhile, {@code T} wakes up and attempts to install {@code V0}; <em>this must fail</em>
+ * </ul>
+ * We can assume in the above scenario that {@code CV.computeValue} uses locks to properly
+ * observe the time-dependent states as it computes {@code V1}, etc.
+ * This does not remove the threat of a stale value, since there is a window of time
+ * between the return of {@code computeValue} in {@code T} and the installation
+ * of the the new value. No user synchronization is possible during this time.
+ *
+ * @param type the type whose class value must be removed
+ * @throws NullPointerException if the argument is null
+ */
+ public void remove(Class<?> type) {
+ ClassValueMap map = getMap(type);
+ if (map != null) {
+ synchronized (map) {
+ map.remove(this);
+ }
+ }
+ }
+
+ /// Implementation...
+ // FIXME: Use a data structure here similar that of ThreadLocal (7030453).
+
+ private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
+
+ /** Slow path for {@link #get}. */
+ private T setComputedValue(Class<?> type) {
+ ClassValueMap map = getMap(type);
+ if (map == null) {
+ map = initializeMap(type);
+ }
+ T value = computeValue(type);
+ STORE_BARRIER.lazySet(0);
+ // All stores pending from computeValue are completed.
+ synchronized (map) {
+ // Warm up the table with a null entry.
+ map.preInitializeEntry(this);
+ }
+ STORE_BARRIER.lazySet(0);
+ // All stores pending from table expansion are completed.
+ synchronized (map) {
+ value = (T) map.initializeEntry(this, value);
+ // One might fear a possible race condition here
+ // if the code for map.put has flushed the write
+ // to map.table[*] before the writes to the Map.Entry
+ // are done. This is not possible, since we have
+ // warmed up the table with an empty entry.
+ }
+ return value;
+ }
+
+ // Replace this map by a per-class slot.
+ private static final WeakHashMap<Class<?>, ClassValueMap> ROOT
+ = new WeakHashMap<Class<?>, ClassValueMap>();
+
+ private static ClassValueMap getMap(Class<?> type) {
+ return ROOT.get(type);
+ }
+
+ private static ClassValueMap initializeMap(Class<?> type) {
+ synchronized (ClassValue.class) {
+ ClassValueMap map = ROOT.get(type);
+ if (map == null)
+ ROOT.put(type, map = new ClassValueMap());
+ return map;
+ }
+ }
+
+ static class ClassValueMap extends WeakHashMap<ClassValue, Object> {
+ /** Make sure this table contains an Entry for the given key, even if it is empty. */
+ void preInitializeEntry(ClassValue key) {
+ if (!this.containsKey(key))
+ this.put(key, null);
+ }
+ /** Make sure this table contains a non-empty Entry for the given key. */
+ Object initializeEntry(ClassValue key, Object value) {
+ Object prior = this.get(key);
+ if (prior != null) {
+ return unmaskNull(prior);
+ }
+ this.put(key, maskNull(value));
+ return value;
+ }
+
+ Object maskNull(Object x) {
+ return x == null ? this : x;
+ }
+ Object unmaskNull(Object x) {
+ return x == this ? null : x;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/AdapterMethodHandle.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,943 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.VerifyType;
+import sun.invoke.util.Wrapper;
+import java.util.Arrays;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * This method handle performs simple conversion or checking of a single argument.
+ * @author jrose
+ */
+class AdapterMethodHandle extends BoundMethodHandle {
+
+ //MethodHandle vmtarget; // next AMH or BMH in chain or final DMH
+ //Object argument; // parameter to the conversion if needed
+ //int vmargslot; // which argument slot is affected
+ private final int conversion; // the type of conversion: RETYPE_ONLY, etc.
+
+ // Constructors in this class *must* be package scoped or private.
+ private AdapterMethodHandle(MethodHandle target, MethodType newType,
+ long conv, Object convArg) {
+ super(newType, convArg, newType.parameterSlotDepth(1+convArgPos(conv)));
+ this.conversion = convCode(conv);
+ // JVM might update VM-specific bits of conversion (ignore)
+ MethodHandleNatives.init(this, target, convArgPos(conv));
+ }
+ private AdapterMethodHandle(MethodHandle target, MethodType newType,
+ long conv) {
+ this(target, newType, conv, null);
+ }
+
+ // TO DO: When adapting another MH with a null conversion, clone
+ // the target and change its type, instead of adding another layer.
+
+ /** Can a JVM-level adapter directly implement the proposed
+ * argument conversions, as if by MethodHandles.convertArguments?
+ */
+ static boolean canPairwiseConvert(MethodType newType, MethodType oldType) {
+ // same number of args, of course
+ int len = newType.parameterCount();
+ if (len != oldType.parameterCount())
+ return false;
+
+ // Check return type. (Not much can be done with it.)
+ Class<?> exp = newType.returnType();
+ Class<?> ret = oldType.returnType();
+ if (!VerifyType.isNullConversion(ret, exp))
+ return false;
+
+ // Check args pairwise.
+ for (int i = 0; i < len; i++) {
+ Class<?> src = newType.parameterType(i); // source type
+ Class<?> dst = oldType.parameterType(i); // destination type
+ if (!canConvertArgument(src, dst))
+ return false;
+ }
+
+ return true;
+ }
+
+ /** Can a JVM-level adapter directly implement the proposed
+ * argument conversion, as if by MethodHandles.convertArguments?
+ */
+ static boolean canConvertArgument(Class<?> src, Class<?> dst) {
+ // ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
+ // so we don't need to repeat so much decision making.
+ if (VerifyType.isNullConversion(src, dst)) {
+ return true;
+ } else if (src.isPrimitive()) {
+ if (dst.isPrimitive())
+ return canPrimCast(src, dst);
+ else
+ return canBoxArgument(src, dst);
+ } else {
+ if (dst.isPrimitive())
+ return canUnboxArgument(src, dst);
+ else
+ return true; // any two refs can be interconverted
+ }
+ }
+
+ /**
+ * Create a JVM-level adapter method handle to conform the given method
+ * handle to the similar newType, using only pairwise argument conversions.
+ * For each argument, convert incoming argument to the exact type needed.
+ * Only null conversions are allowed on the return value (until
+ * the JVM supports ricochet adapters).
+ * The argument conversions allowed are casting, unboxing,
+ * integral widening or narrowing, and floating point widening or narrowing.
+ * @param newType required call type
+ * @param target original method handle
+ * @return an adapter to the original handle with the desired new type,
+ * or the original target if the types are already identical
+ * or null if the adaptation cannot be made
+ */
+ static MethodHandle makePairwiseConvert(MethodType newType, MethodHandle target) {
+ MethodType oldType = target.type();
+ if (newType == oldType) return target;
+
+ if (!canPairwiseConvert(newType, oldType))
+ return null;
+ // (after this point, it is an assertion error to fail to convert)
+
+ // Find last non-trivial conversion (if any).
+ int lastConv = newType.parameterCount()-1;
+ while (lastConv >= 0) {
+ Class<?> src = newType.parameterType(lastConv); // source type
+ Class<?> dst = oldType.parameterType(lastConv); // destination type
+ if (VerifyType.isNullConversion(src, dst)) {
+ --lastConv;
+ } else {
+ break;
+ }
+ }
+ // Now build a chain of one or more adapters.
+ MethodHandle adapter = target;
+ MethodType midType = oldType.changeReturnType(newType.returnType());
+ for (int i = 0; i <= lastConv; i++) {
+ Class<?> src = newType.parameterType(i); // source type
+ Class<?> dst = midType.parameterType(i); // destination type
+ if (VerifyType.isNullConversion(src, dst)) {
+ // do nothing: difference is trivial
+ continue;
+ }
+ // Work the current type backward toward the desired caller type:
+ if (i != lastConv) {
+ midType = midType.changeParameterType(i, src);
+ } else {
+ // When doing the last (or only) real conversion,
+ // force all remaining null conversions to happen also.
+ assert(VerifyType.isNullConversion(newType, midType.changeParameterType(i, src)));
+ midType = newType;
+ }
+
+ // Tricky case analysis follows.
+ // It parallels canConvertArgument() above.
+ if (src.isPrimitive()) {
+ if (dst.isPrimitive()) {
+ adapter = makePrimCast(midType, adapter, i, dst);
+ } else {
+ adapter = makeBoxArgument(midType, adapter, i, dst);
+ }
+ } else {
+ if (dst.isPrimitive()) {
+ // Caller has boxed a primitive. Unbox it for the target.
+ // The box type must correspond exactly to the primitive type.
+ // This is simpler than the powerful set of widening
+ // conversions supported by reflect.Method.invoke.
+ // Those conversions require a big nest of if/then/else logic,
+ // which we prefer to make a user responsibility.
+ adapter = makeUnboxArgument(midType, adapter, i, dst);
+ } else {
+ // Simple reference conversion.
+ // Note: Do not check for a class hierarchy relation
+ // between src and dst. In all cases a 'null' argument
+ // will pass the cast conversion.
+ adapter = makeCheckCast(midType, adapter, i, dst);
+ }
+ }
+ assert(adapter != null);
+ assert(adapter.type() == midType);
+ }
+ if (adapter.type() != newType) {
+ // Only trivial conversions remain.
+ adapter = makeRetypeOnly(newType, adapter);
+ assert(adapter != null);
+ // Actually, that's because there were no non-trivial ones:
+ assert(lastConv == -1);
+ }
+ assert(adapter.type() == newType);
+ return adapter;
+ }
+
+ /**
+ * Create a JVM-level adapter method handle to permute the arguments
+ * of the given method.
+ * @param newType required call type
+ * @param target original method handle
+ * @param argumentMap for each target argument, position of its source in newType
+ * @return an adapter to the original handle with the desired new type,
+ * or the original target if the types are already identical
+ * and the permutation is null
+ * @throws IllegalArgumentException if the adaptation cannot be made
+ * directly by a JVM-level adapter, without help from Java code
+ */
+ static MethodHandle makePermutation(MethodType newType, MethodHandle target,
+ int[] argumentMap) {
+ MethodType oldType = target.type();
+ boolean nullPermutation = true;
+ for (int i = 0; i < argumentMap.length; i++) {
+ int pos = argumentMap[i];
+ if (pos != i)
+ nullPermutation = false;
+ if (pos < 0 || pos >= newType.parameterCount()) {
+ argumentMap = new int[0]; break;
+ }
+ }
+ if (argumentMap.length != oldType.parameterCount())
+ throw newIllegalArgumentException("bad permutation: "+Arrays.toString(argumentMap));
+ if (nullPermutation) {
+ MethodHandle res = makePairwiseConvert(newType, target);
+ // well, that was easy
+ if (res == null)
+ throw newIllegalArgumentException("cannot convert pairwise: "+newType);
+ return res;
+ }
+
+ // Check return type. (Not much can be done with it.)
+ Class<?> exp = newType.returnType();
+ Class<?> ret = oldType.returnType();
+ if (!VerifyType.isNullConversion(ret, exp))
+ throw newIllegalArgumentException("bad return conversion for "+newType);
+
+ // See if the argument types match up.
+ for (int i = 0; i < argumentMap.length; i++) {
+ int j = argumentMap[i];
+ Class<?> src = newType.parameterType(j);
+ Class<?> dst = oldType.parameterType(i);
+ if (!VerifyType.isNullConversion(src, dst))
+ throw newIllegalArgumentException("bad argument #"+j+" conversion for "+newType);
+ }
+
+ // Now figure out a nice mix of SWAP, ROT, DUP, and DROP adapters.
+ // A workable greedy algorithm is as follows:
+ // Drop unused outgoing arguments (right to left: shallowest first).
+ // Duplicate doubly-used outgoing arguments (left to right: deepest first).
+ // Then the remaining problem is a true argument permutation.
+ // Marshal the outgoing arguments as required from left to right.
+ // That is, find the deepest outgoing stack position that does not yet
+ // have the correct argument value, and correct at least that position
+ // by swapping or rotating in the misplaced value (from a shallower place).
+ // If the misplaced value is followed by one or more consecutive values
+ // (also misplaced) issue a rotation which brings as many as possible
+ // into position. Otherwise make progress with either a swap or a
+ // rotation. Prefer the swap as cheaper, but do not use it if it
+ // breaks a slot pair. Prefer the rotation over the swap if it would
+ // preserve more consecutive values shallower than the target position.
+ // When more than one rotation will work (because the required value
+ // is already adjacent to the target position), then use a rotation
+ // which moves the old value in the target position adjacent to
+ // one of its consecutive values. Also, prefer shorter rotation
+ // spans, since they use fewer memory cycles for shuffling.
+
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ private static byte basicType(Class<?> type) {
+ if (type == null) return T_VOID;
+ switch (Wrapper.forBasicType(type)) {
+ case BOOLEAN: return T_BOOLEAN;
+ case CHAR: return T_CHAR;
+ case FLOAT: return T_FLOAT;
+ case DOUBLE: return T_DOUBLE;
+ case BYTE: return T_BYTE;
+ case SHORT: return T_SHORT;
+ case INT: return T_INT;
+ case LONG: return T_LONG;
+ case OBJECT: return T_OBJECT;
+ case VOID: return T_VOID;
+ }
+ return 99; // T_ILLEGAL or some such
+ }
+
+ /** Number of stack slots for the given type.
+ * Two for T_DOUBLE and T_FLOAT, one for the rest.
+ */
+ private static int type2size(int type) {
+ assert(type >= T_BOOLEAN && type <= T_OBJECT);
+ return (type == T_LONG || type == T_DOUBLE) ? 2 : 1;
+ }
+ private static int type2size(Class<?> type) {
+ return type2size(basicType(type));
+ }
+
+ /** The given stackMove is the number of slots pushed.
+ * It might be negative. Scale it (multiply) by the
+ * VM's notion of how an address changes with a push,
+ * to get the raw SP change for stackMove.
+ * Then shift and mask it into the correct field.
+ */
+ private static long insertStackMove(int stackMove) {
+ // following variable must be long to avoid sign extension after '<<'
+ long spChange = stackMove * MethodHandleNatives.JVM_STACK_MOVE_UNIT;
+ return (spChange & CONV_STACK_MOVE_MASK) << CONV_STACK_MOVE_SHIFT;
+ }
+
+ /** Construct an adapter conversion descriptor for a single-argument conversion. */
+ private static long makeConv(int convOp, int argnum, int src, int dest) {
+ assert(src == (src & 0xF));
+ assert(dest == (dest & 0xF));
+ assert(convOp >= OP_CHECK_CAST && convOp <= OP_PRIM_TO_REF);
+ int stackMove = type2size(dest) - type2size(src);
+ return ((long) argnum << 32 |
+ (long) convOp << CONV_OP_SHIFT |
+ (int) src << CONV_SRC_TYPE_SHIFT |
+ (int) dest << CONV_DEST_TYPE_SHIFT |
+ insertStackMove(stackMove)
+ );
+ }
+ private static long makeConv(int convOp, int argnum, int stackMove) {
+ assert(convOp >= OP_DUP_ARGS && convOp <= OP_SPREAD_ARGS);
+ byte src = 0, dest = 0;
+ if (convOp >= OP_COLLECT_ARGS && convOp <= OP_SPREAD_ARGS)
+ src = dest = T_OBJECT;
+ return ((long) argnum << 32 |
+ (long) convOp << CONV_OP_SHIFT |
+ (int) src << CONV_SRC_TYPE_SHIFT |
+ (int) dest << CONV_DEST_TYPE_SHIFT |
+ insertStackMove(stackMove)
+ );
+ }
+ private static long makeSwapConv(int convOp, int srcArg, byte type, int destSlot) {
+ assert(convOp >= OP_SWAP_ARGS && convOp <= OP_ROT_ARGS);
+ return ((long) srcArg << 32 |
+ (long) convOp << CONV_OP_SHIFT |
+ (int) type << CONV_SRC_TYPE_SHIFT |
+ (int) type << CONV_DEST_TYPE_SHIFT |
+ (int) destSlot << CONV_VMINFO_SHIFT
+ );
+ }
+ private static long makeConv(int convOp) {
+ assert(convOp == OP_RETYPE_ONLY || convOp == OP_RETYPE_RAW);
+ return ((long)-1 << 32) | (convOp << CONV_OP_SHIFT); // stackMove, src, dst all zero
+ }
+ private static int convCode(long conv) {
+ return (int)conv;
+ }
+ private static int convArgPos(long conv) {
+ return (int)(conv >>> 32);
+ }
+ private static boolean convOpSupported(int convOp) {
+ assert(convOp >= 0 && convOp <= CONV_OP_LIMIT);
+ return ((1<<convOp) & MethodHandleNatives.CONV_OP_IMPLEMENTED_MASK) != 0;
+ }
+
+ /** One of OP_RETYPE_ONLY, etc. */
+ int conversionOp() { return (conversion & CONV_OP_MASK) >> CONV_OP_SHIFT; }
+
+ /* Return one plus the position of the first non-trivial difference
+ * between the given types. This is not a symmetric operation;
+ * we are considering adapting the targetType to adapterType.
+ * Trivial differences are those which could be ignored by the JVM
+ * without subverting the verifier. Otherwise, adaptable differences
+ * are ones for which we could create an adapter to make the type change.
+ * Return zero if there are no differences (other than trivial ones).
+ * Return 1+N if N is the only adaptable argument difference.
+ * Return the -2-N where N is the first of several adaptable
+ * argument differences.
+ * Return -1 if there there are differences which are not adaptable.
+ */
+ private static int diffTypes(MethodType adapterType,
+ MethodType targetType,
+ boolean raw) {
+ int diff;
+ diff = diffReturnTypes(adapterType, targetType, raw);
+ if (diff != 0) return diff;
+ int nargs = adapterType.parameterCount();
+ if (nargs != targetType.parameterCount())
+ return -1;
+ diff = diffParamTypes(adapterType, 0, targetType, 0, nargs, raw);
+ //System.out.println("diff "+adapterType);
+ //System.out.println(" "+diff+" "+targetType);
+ return diff;
+ }
+ private static int diffReturnTypes(MethodType adapterType,
+ MethodType targetType,
+ boolean raw) {
+ Class<?> src = targetType.returnType();
+ Class<?> dst = adapterType.returnType();
+ if ((!raw
+ ? VerifyType.canPassUnchecked(src, dst)
+ : VerifyType.canPassRaw(src, dst)
+ ) > 0)
+ return 0; // no significant difference
+ if (raw && !src.isPrimitive() && !dst.isPrimitive())
+ return 0; // can force a reference return (very carefully!)
+ //if (false) return 1; // never adaptable!
+ return -1; // some significant difference
+ }
+ private static int diffParamTypes(MethodType adapterType, int astart,
+ MethodType targetType, int tstart,
+ int nargs, boolean raw) {
+ assert(nargs >= 0);
+ int res = 0;
+ for (int i = 0; i < nargs; i++) {
+ Class<?> src = adapterType.parameterType(astart+i);
+ Class<?> dest = targetType.parameterType(tstart+i);
+ if ((!raw
+ ? VerifyType.canPassUnchecked(src, dest)
+ : VerifyType.canPassRaw(src, dest)
+ ) <= 0) {
+ // found a difference; is it the only one so far?
+ if (res != 0)
+ return -1-res; // return -2-i for prev. i
+ res = 1+i;
+ }
+ }
+ return res;
+ }
+
+ /** Can a retyping adapter (alone) validly convert the target to newType? */
+ static boolean canRetypeOnly(MethodType newType, MethodType targetType) {
+ return canRetype(newType, targetType, false);
+ }
+ /** Can a retyping adapter (alone) convert the target to newType?
+ * It is allowed to widen subword types and void to int, to make bitwise
+ * conversions between float/int and double/long, and to perform unchecked
+ * reference conversions on return. This last feature requires that the
+ * caller be trusted, and perform explicit cast conversions on return values.
+ */
+ static boolean canRetypeRaw(MethodType newType, MethodType targetType) {
+ return canRetype(newType, targetType, true);
+ }
+ static boolean canRetype(MethodType newType, MethodType targetType, boolean raw) {
+ if (!convOpSupported(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY)) return false;
+ int diff = diffTypes(newType, targetType, raw);
+ // %%% This assert is too strong. Factor diff into VerifyType and reconcile.
+ assert(raw || (diff == 0) == VerifyType.isNullConversion(newType, targetType));
+ return diff == 0;
+ }
+
+ /** Factory method: Performs no conversions; simply retypes the adapter.
+ * Allows unchecked argument conversions pairwise, if they are safe.
+ * Returns null if not possible.
+ */
+ static MethodHandle makeRetypeOnly(MethodType newType, MethodHandle target) {
+ return makeRetype(newType, target, false);
+ }
+ static MethodHandle makeRetypeRaw(MethodType newType, MethodHandle target) {
+ return makeRetype(newType, target, true);
+ }
+ static MethodHandle makeRetype(MethodType newType, MethodHandle target, boolean raw) {
+ MethodType oldType = target.type();
+ if (oldType == newType) return target;
+ if (!canRetype(newType, oldType, raw))
+ return null;
+ // TO DO: clone the target guy, whatever he is, with new type.
+ return new AdapterMethodHandle(target, newType, makeConv(raw ? OP_RETYPE_RAW : OP_RETYPE_ONLY));
+ }
+
+ static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
+ return new AsVarargsCollector(target, arrayType);
+ }
+
+ static class AsVarargsCollector extends AdapterMethodHandle {
+ final MethodHandle target;
+ final Class<?> arrayType;
+ MethodHandle cache;
+
+ AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
+ super(target, target.type(), makeConv(OP_RETYPE_ONLY));
+ this.target = target;
+ this.arrayType = arrayType;
+ this.cache = target.asCollector(arrayType, 0);
+ }
+
+ @Override
+ public boolean isVarargsCollector() {
+ return true;
+ }
+
+ @Override
+ public MethodHandle asType(MethodType newType) {
+ MethodType type = this.type();
+ int collectArg = type.parameterCount() - 1;
+ int newArity = newType.parameterCount();
+ if (newArity == collectArg+1 &&
+ type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
+ // if arity and trailing parameter are compatible, do normal thing
+ return super.asType(newType);
+ }
+ // check cache
+ if (cache.type().parameterCount() == newArity)
+ return cache.asType(newType);
+ // build and cache a collector
+ int arrayLength = newArity - collectArg;
+ MethodHandle collector;
+ try {
+ collector = target.asCollector(arrayType, arrayLength);
+ } catch (IllegalArgumentException ex) {
+ throw new WrongMethodTypeException("cannot build collector");
+ }
+ cache = collector;
+ return collector.asType(newType);
+ }
+
+ @Override
+ public MethodHandle asVarargsCollector(Class<?> arrayType) {
+ MethodType type = this.type();
+ if (type.parameterType(type.parameterCount()-1) == arrayType)
+ return this;
+ return super.asVarargsCollector(arrayType);
+ }
+ }
+
+ /** Can a checkcast adapter validly convert the target to newType?
+ * The JVM supports all kind of reference casts, even silly ones.
+ */
+ static boolean canCheckCast(MethodType newType, MethodType targetType,
+ int arg, Class<?> castType) {
+ if (!convOpSupported(OP_CHECK_CAST)) return false;
+ Class<?> src = newType.parameterType(arg);
+ Class<?> dst = targetType.parameterType(arg);
+ if (!canCheckCast(src, castType)
+ || !VerifyType.isNullConversion(castType, dst))
+ return false;
+ int diff = diffTypes(newType, targetType, false);
+ return (diff == arg+1); // arg is sole non-trivial diff
+ }
+ /** Can an primitive conversion adapter validly convert src to dst? */
+ static boolean canCheckCast(Class<?> src, Class<?> dst) {
+ return (!src.isPrimitive() && !dst.isPrimitive());
+ }
+
+ /** Factory method: Forces a cast at the given argument.
+ * The castType is the target of the cast, and can be any type
+ * with a null conversion to the corresponding target parameter.
+ * Return null if this cannot be done.
+ */
+ static MethodHandle makeCheckCast(MethodType newType, MethodHandle target,
+ int arg, Class<?> castType) {
+ if (!canCheckCast(newType, target.type(), arg, castType))
+ return null;
+ long conv = makeConv(OP_CHECK_CAST, arg, T_OBJECT, T_OBJECT);
+ return new AdapterMethodHandle(target, newType, conv, castType);
+ }
+
+ /** Can an primitive conversion adapter validly convert the target to newType?
+ * The JVM currently supports all conversions except those between
+ * floating and integral types.
+ */
+ static boolean canPrimCast(MethodType newType, MethodType targetType,
+ int arg, Class<?> convType) {
+ if (!convOpSupported(OP_PRIM_TO_PRIM)) return false;
+ Class<?> src = newType.parameterType(arg);
+ Class<?> dst = targetType.parameterType(arg);
+ if (!canPrimCast(src, convType)
+ || !VerifyType.isNullConversion(convType, dst))
+ return false;
+ int diff = diffTypes(newType, targetType, false);
+ return (diff == arg+1); // arg is sole non-trivial diff
+ }
+ /** Can an primitive conversion adapter validly convert src to dst? */
+ static boolean canPrimCast(Class<?> src, Class<?> dst) {
+ if (src == dst || !src.isPrimitive() || !dst.isPrimitive()) {
+ return false;
+ } else if (Wrapper.forPrimitiveType(dst).isFloating()) {
+ // both must be floating types
+ return Wrapper.forPrimitiveType(src).isFloating();
+ } else {
+ // both are integral, and all combinations work fine
+ assert(Wrapper.forPrimitiveType(src).isIntegral() &&
+ Wrapper.forPrimitiveType(dst).isIntegral());
+ return true;
+ }
+ }
+
+ /** Factory method: Truncate the given argument with zero or sign extension,
+ * and/or convert between single and doubleword versions of integer or float.
+ * The convType is the target of the conversion, and can be any type
+ * with a null conversion to the corresponding target parameter.
+ * Return null if this cannot be done.
+ */
+ static MethodHandle makePrimCast(MethodType newType, MethodHandle target,
+ int arg, Class<?> convType) {
+ MethodType oldType = target.type();
+ if (!canPrimCast(newType, oldType, arg, convType))
+ return null;
+ Class<?> src = newType.parameterType(arg);
+ long conv = makeConv(OP_PRIM_TO_PRIM, arg, basicType(src), basicType(convType));
+ return new AdapterMethodHandle(target, newType, conv);
+ }
+
+ /** Can an unboxing conversion validly convert src to dst?
+ * The JVM currently supports all kinds of casting and unboxing.
+ * The convType is the unboxed type; it can be either a primitive or wrapper.
+ */
+ static boolean canUnboxArgument(MethodType newType, MethodType targetType,
+ int arg, Class<?> convType) {
+ if (!convOpSupported(OP_REF_TO_PRIM)) return false;
+ Class<?> src = newType.parameterType(arg);
+ Class<?> dst = targetType.parameterType(arg);
+ Class<?> boxType = Wrapper.asWrapperType(convType);
+ convType = Wrapper.asPrimitiveType(convType);
+ if (!canCheckCast(src, boxType)
+ || boxType == convType
+ || !VerifyType.isNullConversion(convType, dst))
+ return false;
+ int diff = diffTypes(newType, targetType, false);
+ return (diff == arg+1); // arg is sole non-trivial diff
+ }
+ /** Can an primitive unboxing adapter validly convert src to dst? */
+ static boolean canUnboxArgument(Class<?> src, Class<?> dst) {
+ return (!src.isPrimitive() && Wrapper.asPrimitiveType(dst).isPrimitive());
+ }
+
+ /** Factory method: Unbox the given argument.
+ * Return null if this cannot be done.
+ */
+ static MethodHandle makeUnboxArgument(MethodType newType, MethodHandle target,
+ int arg, Class<?> convType) {
+ MethodType oldType = target.type();
+ Class<?> src = newType.parameterType(arg);
+ Class<?> dst = oldType.parameterType(arg);
+ Class<?> boxType = Wrapper.asWrapperType(convType);
+ Class<?> primType = Wrapper.asPrimitiveType(convType);
+ if (!canUnboxArgument(newType, oldType, arg, convType))
+ return null;
+ MethodType castDone = newType;
+ if (!VerifyType.isNullConversion(src, boxType))
+ castDone = newType.changeParameterType(arg, boxType);
+ long conv = makeConv(OP_REF_TO_PRIM, arg, T_OBJECT, basicType(primType));
+ MethodHandle adapter = new AdapterMethodHandle(target, castDone, conv, boxType);
+ if (castDone == newType)
+ return adapter;
+ return makeCheckCast(newType, adapter, arg, boxType);
+ }
+
+ /** Can an primitive boxing adapter validly convert src to dst? */
+ static boolean canBoxArgument(Class<?> src, Class<?> dst) {
+ if (!convOpSupported(OP_PRIM_TO_REF)) return false;
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ /** Factory method: Unbox the given argument.
+ * Return null if this cannot be done.
+ */
+ static MethodHandle makeBoxArgument(MethodType newType, MethodHandle target,
+ int arg, Class<?> convType) {
+ // this is difficult to do in the JVM because it must GC
+ return null;
+ }
+
+ /** Can an adapter simply drop arguments to convert the target to newType? */
+ static boolean canDropArguments(MethodType newType, MethodType targetType,
+ int dropArgPos, int dropArgCount) {
+ if (dropArgCount == 0)
+ return canRetypeOnly(newType, targetType);
+ if (!convOpSupported(OP_DROP_ARGS)) return false;
+ if (diffReturnTypes(newType, targetType, false) != 0)
+ return false;
+ int nptypes = newType.parameterCount();
+ // parameter types must be the same up to the drop point
+ if (dropArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, dropArgPos, false) != 0)
+ return false;
+ int afterPos = dropArgPos + dropArgCount;
+ int afterCount = nptypes - afterPos;
+ if (dropArgPos < 0 || dropArgPos >= nptypes ||
+ dropArgCount < 1 || afterPos > nptypes ||
+ targetType.parameterCount() != nptypes - dropArgCount)
+ return false;
+ // parameter types after the drop point must also be the same
+ if (afterCount != 0 && diffParamTypes(newType, afterPos, targetType, dropArgPos, afterCount, false) != 0)
+ return false;
+ return true;
+ }
+
+ /** Factory method: Drop selected arguments.
+ * Allow unchecked retyping of remaining arguments, pairwise.
+ * Return null if this is not possible.
+ */
+ static MethodHandle makeDropArguments(MethodType newType, MethodHandle target,
+ int dropArgPos, int dropArgCount) {
+ if (dropArgCount == 0)
+ return makeRetypeOnly(newType, target);
+ if (!canDropArguments(newType, target.type(), dropArgPos, dropArgCount))
+ return null;
+ // in arglist: [0: ...keep1 | dpos: drop... | dpos+dcount: keep2... ]
+ // out arglist: [0: ...keep1 | dpos: keep2... ]
+ int keep2InPos = dropArgPos + dropArgCount;
+ int dropSlot = newType.parameterSlotDepth(keep2InPos);
+ int keep1InSlot = newType.parameterSlotDepth(dropArgPos);
+ int slotCount = keep1InSlot - dropSlot;
+ assert(slotCount >= dropArgCount);
+ assert(target.type().parameterSlotCount() + slotCount == newType.parameterSlotCount());
+ long conv = makeConv(OP_DROP_ARGS, dropArgPos + dropArgCount - 1, -slotCount);
+ return new AdapterMethodHandle(target, newType, conv);
+ }
+
+ /** Can an adapter duplicate an argument to convert the target to newType? */
+ static boolean canDupArguments(MethodType newType, MethodType targetType,
+ int dupArgPos, int dupArgCount) {
+ if (!convOpSupported(OP_DUP_ARGS)) return false;
+ if (diffReturnTypes(newType, targetType, false) != 0)
+ return false;
+ int nptypes = newType.parameterCount();
+ if (dupArgCount < 0 || dupArgPos + dupArgCount > nptypes)
+ return false;
+ if (targetType.parameterCount() != nptypes + dupArgCount)
+ return false;
+ // parameter types must be the same up to the duplicated arguments
+ if (diffParamTypes(newType, 0, targetType, 0, nptypes, false) != 0)
+ return false;
+ // duplicated types must be, well, duplicates
+ if (diffParamTypes(newType, dupArgPos, targetType, nptypes, dupArgCount, false) != 0)
+ return false;
+ return true;
+ }
+
+ /** Factory method: Duplicate the selected argument.
+ * Return null if this is not possible.
+ */
+ static MethodHandle makeDupArguments(MethodType newType, MethodHandle target,
+ int dupArgPos, int dupArgCount) {
+ if (!canDupArguments(newType, target.type(), dupArgPos, dupArgCount))
+ return null;
+ if (dupArgCount == 0)
+ return target;
+ // in arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... ]
+ // out arglist: [0: ...keep1 | dpos: dup... | dpos+dcount: keep2... | dup... ]
+ int keep2InPos = dupArgPos + dupArgCount;
+ int dupSlot = newType.parameterSlotDepth(keep2InPos);
+ int keep1InSlot = newType.parameterSlotDepth(dupArgPos);
+ int slotCount = keep1InSlot - dupSlot;
+ assert(target.type().parameterSlotCount() - slotCount == newType.parameterSlotCount());
+ long conv = makeConv(OP_DUP_ARGS, dupArgPos + dupArgCount - 1, slotCount);
+ return new AdapterMethodHandle(target, newType, conv);
+ }
+
+ /** Can an adapter swap two arguments to convert the target to newType? */
+ static boolean canSwapArguments(MethodType newType, MethodType targetType,
+ int swapArg1, int swapArg2) {
+ if (!convOpSupported(OP_SWAP_ARGS)) return false;
+ if (diffReturnTypes(newType, targetType, false) != 0)
+ return false;
+ if (swapArg1 >= swapArg2) return false; // caller resp
+ int nptypes = newType.parameterCount();
+ if (targetType.parameterCount() != nptypes)
+ return false;
+ if (swapArg1 < 0 || swapArg2 >= nptypes)
+ return false;
+ if (diffParamTypes(newType, 0, targetType, 0, swapArg1, false) != 0)
+ return false;
+ if (diffParamTypes(newType, swapArg1, targetType, swapArg2, 1, false) != 0)
+ return false;
+ if (diffParamTypes(newType, swapArg1+1, targetType, swapArg1+1, swapArg2-swapArg1-1, false) != 0)
+ return false;
+ if (diffParamTypes(newType, swapArg2, targetType, swapArg1, 1, false) != 0)
+ return false;
+ if (diffParamTypes(newType, swapArg2+1, targetType, swapArg2+1, nptypes-swapArg2-1, false) != 0)
+ return false;
+ return true;
+ }
+
+ /** Factory method: Swap the selected arguments.
+ * Return null if this is not possible.
+ */
+ static MethodHandle makeSwapArguments(MethodType newType, MethodHandle target,
+ int swapArg1, int swapArg2) {
+ if (swapArg1 == swapArg2)
+ return target;
+ if (swapArg1 > swapArg2) { int t = swapArg1; swapArg1 = swapArg2; swapArg2 = t; }
+ if (!canSwapArguments(newType, target.type(), swapArg1, swapArg2))
+ return null;
+ Class<?> swapType = newType.parameterType(swapArg1);
+ // in arglist: [0: ...keep1 | pos1: a1 | pos1+1: keep2... | pos2: a2 | pos2+1: keep3... ]
+ // out arglist: [0: ...keep1 | pos1: a2 | pos1+1: keep2... | pos2: a1 | pos2+1: keep3... ]
+ int swapSlot2 = newType.parameterSlotDepth(swapArg2 + 1);
+ long conv = makeSwapConv(OP_SWAP_ARGS, swapArg1, basicType(swapType), swapSlot2);
+ return new AdapterMethodHandle(target, newType, conv);
+ }
+
+ static int positiveRotation(int argCount, int rotateBy) {
+ assert(argCount > 0);
+ if (rotateBy >= 0) {
+ if (rotateBy < argCount)
+ return rotateBy;
+ return rotateBy % argCount;
+ } else if (rotateBy >= -argCount) {
+ return rotateBy + argCount;
+ } else {
+ return (-1-((-1-rotateBy) % argCount)) + argCount;
+ }
+ }
+
+ final static int MAX_ARG_ROTATION = 1;
+
+ /** Can an adapter rotate arguments to convert the target to newType? */
+ static boolean canRotateArguments(MethodType newType, MethodType targetType,
+ int firstArg, int argCount, int rotateBy) {
+ if (!convOpSupported(OP_ROT_ARGS)) return false;
+ if (argCount <= 2) return false; // must be a swap, not a rotate
+ rotateBy = positiveRotation(argCount, rotateBy);
+ if (rotateBy == 0) return false; // no rotation
+ if (rotateBy > MAX_ARG_ROTATION && rotateBy < argCount - MAX_ARG_ROTATION)
+ return false; // too many argument positions
+ // Rotate incoming args right N to the out args, N in 1..(argCouunt-1).
+ if (diffReturnTypes(newType, targetType, false) != 0)
+ return false;
+ int nptypes = newType.parameterCount();
+ if (targetType.parameterCount() != nptypes)
+ return false;
+ if (firstArg < 0 || firstArg >= nptypes) return false;
+ int argLimit = firstArg + argCount;
+ if (argLimit > nptypes) return false;
+ if (diffParamTypes(newType, 0, targetType, 0, firstArg, false) != 0)
+ return false;
+ int newChunk1 = argCount - rotateBy, newChunk2 = rotateBy;
+ // swap new chunk1 with target chunk2
+ if (diffParamTypes(newType, firstArg, targetType, argLimit-newChunk1, newChunk1, false) != 0)
+ return false;
+ // swap new chunk2 with target chunk1
+ if (diffParamTypes(newType, firstArg+newChunk1, targetType, firstArg, newChunk2, false) != 0)
+ return false;
+ return true;
+ }
+
+ /** Factory method: Rotate the selected argument range.
+ * Return null if this is not possible.
+ */
+ static MethodHandle makeRotateArguments(MethodType newType, MethodHandle target,
+ int firstArg, int argCount, int rotateBy) {
+ rotateBy = positiveRotation(argCount, rotateBy);
+ if (!canRotateArguments(newType, target.type(), firstArg, argCount, rotateBy))
+ return null;
+ // Decide whether it should be done as a right or left rotation,
+ // on the JVM stack. Return the number of stack slots to rotate by,
+ // positive if right, negative if left.
+ int limit = firstArg + argCount;
+ int depth0 = newType.parameterSlotDepth(firstArg);
+ int depth1 = newType.parameterSlotDepth(limit-rotateBy);
+ int depth2 = newType.parameterSlotDepth(limit);
+ int chunk1Slots = depth0 - depth1; assert(chunk1Slots > 0);
+ int chunk2Slots = depth1 - depth2; assert(chunk2Slots > 0);
+ // From here on out, it assumes a single-argument shift.
+ assert(MAX_ARG_ROTATION == 1);
+ int srcArg, dstArg;
+ byte basicType;
+ if (chunk2Slots <= chunk1Slots) {
+ // Rotate right/down N (rotateBy = +N, N small, c2 small):
+ // in arglist: [0: ...keep1 | arg1: c1... | limit-N: c2 | limit: keep2... ]
+ // out arglist: [0: ...keep1 | arg1: c2 | arg1+N: c1... | limit: keep2... ]
+ srcArg = limit-1;
+ dstArg = firstArg;
+ basicType = basicType(newType.parameterType(srcArg));
+ assert(chunk2Slots == type2size(basicType));
+ } else {
+ // Rotate left/up N (rotateBy = -N, N small, c1 small):
+ // in arglist: [0: ...keep1 | arg1: c1 | arg1+N: c2... | limit: keep2... ]
+ // out arglist: [0: ...keep1 | arg1: c2 ... | limit-N: c1 | limit: keep2... ]
+ srcArg = firstArg;
+ dstArg = limit-1;
+ basicType = basicType(newType.parameterType(srcArg));
+ assert(chunk1Slots == type2size(basicType));
+ }
+ int dstSlot = newType.parameterSlotDepth(dstArg + 1);
+ long conv = makeSwapConv(OP_ROT_ARGS, srcArg, basicType, dstSlot);
+ return new AdapterMethodHandle(target, newType, conv);
+ }
+
+ /** Can an adapter spread an argument to convert the target to newType? */
+ static boolean canSpreadArguments(MethodType newType, MethodType targetType,
+ Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
+ if (!convOpSupported(OP_SPREAD_ARGS)) return false;
+ if (diffReturnTypes(newType, targetType, false) != 0)
+ return false;
+ int nptypes = newType.parameterCount();
+ // parameter types must be the same up to the spread point
+ if (spreadArgPos != 0 && diffParamTypes(newType, 0, targetType, 0, spreadArgPos, false) != 0)
+ return false;
+ int afterPos = spreadArgPos + spreadArgCount;
+ int afterCount = nptypes - (spreadArgPos + 1);
+ if (spreadArgPos < 0 || spreadArgPos >= nptypes ||
+ spreadArgCount < 0 ||
+ targetType.parameterCount() != afterPos + afterCount)
+ return false;
+ // parameter types after the spread point must also be the same
+ if (afterCount != 0 && diffParamTypes(newType, spreadArgPos+1, targetType, afterPos, afterCount, false) != 0)
+ return false;
+ // match the array element type to the spread arg types
+ Class<?> rawSpreadArgType = newType.parameterType(spreadArgPos);
+ if (rawSpreadArgType != spreadArgType && !canCheckCast(rawSpreadArgType, spreadArgType))
+ return false;
+ for (int i = 0; i < spreadArgCount; i++) {
+ Class<?> src = VerifyType.spreadArgElementType(spreadArgType, i);
+ Class<?> dst = targetType.parameterType(spreadArgPos + i);
+ if (src == null || !VerifyType.isNullConversion(src, dst))
+ return false;
+ }
+ return true;
+ }
+
+
+ /** Factory method: Spread selected argument. */
+ static MethodHandle makeSpreadArguments(MethodType newType, MethodHandle target,
+ Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
+ MethodType targetType = target.type();
+ if (!canSpreadArguments(newType, targetType, spreadArgType, spreadArgPos, spreadArgCount))
+ return null;
+ // in arglist: [0: ...keep1 | spos: spreadArg | spos+1: keep2... ]
+ // out arglist: [0: ...keep1 | spos: spread... | spos+scount: keep2... ]
+ int keep2OutPos = spreadArgPos + spreadArgCount;
+ int spreadSlot = targetType.parameterSlotDepth(keep2OutPos);
+ int keep1OutSlot = targetType.parameterSlotDepth(spreadArgPos);
+ int slotCount = keep1OutSlot - spreadSlot;
+ assert(spreadSlot == newType.parameterSlotDepth(spreadArgPos+1));
+ assert(slotCount >= spreadArgCount);
+ long conv = makeConv(OP_SPREAD_ARGS, spreadArgPos, slotCount-1);
+ MethodHandle res = new AdapterMethodHandle(target, newType, conv, spreadArgType);
+ assert(res.type().parameterType(spreadArgPos) == spreadArgType);
+ return res;
+ }
+
+ // TO DO: makeCollectArguments, makeFlyby, makeRicochet
+
+ @Override
+ public String toString() {
+ return getNameString(nonAdapter((MethodHandle)vmtarget), this);
+ }
+
+ private static MethodHandle nonAdapter(MethodHandle mh) {
+ while (mh instanceof AdapterMethodHandle) {
+ mh = (MethodHandle) mh.vmtarget;
+ }
+ return mh;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.VerifyType;
+import sun.invoke.util.Wrapper;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * The flavor of method handle which emulates an invoke instruction
+ * on a predetermined argument. The JVM dispatches to the correct method
+ * when the handle is created, not when it is invoked.
+ * @author jrose
+ */
+class BoundMethodHandle extends MethodHandle {
+ //MethodHandle vmtarget; // next BMH or final DMH or methodOop
+ private final Object argument; // argument to insert
+ private final int vmargslot; // position at which it is inserted
+
+ // Constructors in this class *must* be package scoped or private.
+
+ /** Bind a direct MH to its receiver (or first ref. argument).
+ * The JVM will pre-dispatch the MH if it is not already static.
+ */
+ /*non-public*/ BoundMethodHandle(DirectMethodHandle mh, Object argument) {
+ super(mh.type().dropParameterTypes(0, 1));
+ // check the type now, once for all:
+ this.argument = checkReferenceArgument(argument, mh, 0);
+ this.vmargslot = this.type().parameterSlotCount();
+ initTarget(mh, 0);
+ }
+
+ /** Insert an argument into an arbitrary method handle.
+ * If argnum is zero, inserts the first argument, etc.
+ * The argument type must be a reference.
+ */
+ /*non-public*/ BoundMethodHandle(MethodHandle mh, Object argument, int argnum) {
+ this(mh.type().dropParameterTypes(argnum, argnum+1),
+ mh, argument, argnum);
+ }
+
+ /** Insert an argument into an arbitrary method handle.
+ * If argnum is zero, inserts the first argument, etc.
+ */
+ /*non-public*/ BoundMethodHandle(MethodType type, MethodHandle mh, Object argument, int argnum) {
+ super(type);
+ if (mh.type().parameterType(argnum).isPrimitive())
+ this.argument = bindPrimitiveArgument(argument, mh, argnum);
+ else {
+ this.argument = checkReferenceArgument(argument, mh, argnum);
+ }
+ this.vmargslot = type.parameterSlotDepth(argnum);
+ initTarget(mh, argnum);
+ }
+
+ private void initTarget(MethodHandle mh, int argnum) {
+ //this.vmtarget = mh; // maybe updated by JVM
+ MethodHandleNatives.init(this, mh, argnum);
+ }
+
+ /** For the AdapterMethodHandle subclass.
+ */
+ /*non-public*/ BoundMethodHandle(MethodType type, Object argument, int vmargslot) {
+ super(type);
+ this.argument = argument;
+ this.vmargslot = vmargslot;
+ assert(this instanceof AdapterMethodHandle);
+ }
+
+ /** Initialize the current object as a self-bound method handle, binding it
+ * as the first argument of the method handle {@code entryPoint}.
+ * The invocation type of the resulting method handle will be the
+ * same as {@code entryPoint}, except that the first argument
+ * type will be dropped.
+ */
+ /*non-public*/ BoundMethodHandle(MethodHandle entryPoint) {
+ super(entryPoint.type().dropParameterTypes(0, 1));
+ this.argument = this; // kludge; get rid of
+ this.vmargslot = this.type().parameterSlotDepth(0);
+ initTarget(entryPoint, 0);
+ }
+
+ /** Make sure the given {@code argument} can be used as {@code argnum}-th
+ * parameter of the given method handle {@code mh}, which must be a reference.
+ * <p>
+ * If this fails, throw a suitable {@code WrongMethodTypeException},
+ * which will prevent the creation of an illegally typed bound
+ * method handle.
+ */
+ final static Object checkReferenceArgument(Object argument, MethodHandle mh, int argnum) {
+ Class<?> ptype = mh.type().parameterType(argnum);
+ if (ptype.isPrimitive()) {
+ // fail
+ } else if (argument == null) {
+ return null;
+ } else if (VerifyType.isNullReferenceConversion(argument.getClass(), ptype)) {
+ return argument;
+ }
+ throw badBoundArgumentException(argument, mh, argnum);
+ }
+
+ /** Make sure the given {@code argument} can be used as {@code argnum}-th
+ * parameter of the given method handle {@code mh}, which must be a primitive.
+ * <p>
+ * If this fails, throw a suitable {@code WrongMethodTypeException},
+ * which will prevent the creation of an illegally typed bound
+ * method handle.
+ */
+ final static Object bindPrimitiveArgument(Object argument, MethodHandle mh, int argnum) {
+ Class<?> ptype = mh.type().parameterType(argnum);
+ Wrapper wrap = Wrapper.forPrimitiveType(ptype);
+ Object zero = wrap.zero();
+ if (zero == null) {
+ // fail
+ } else if (argument == null) {
+ if (ptype != int.class && wrap.isSubwordOrInt())
+ return Integer.valueOf(0);
+ else
+ return zero;
+ } else if (VerifyType.isNullReferenceConversion(argument.getClass(), zero.getClass())) {
+ if (ptype != int.class && wrap.isSubwordOrInt())
+ return Wrapper.INT.wrap(argument);
+ else
+ return argument;
+ }
+ throw badBoundArgumentException(argument, mh, argnum);
+ }
+
+ final static RuntimeException badBoundArgumentException(Object argument, MethodHandle mh, int argnum) {
+ String atype = (argument == null) ? "null" : argument.getClass().toString();
+ return new WrongMethodTypeException("cannot bind "+atype+" argument to parameter #"+argnum+" of "+mh.type());
+ }
+
+ @Override
+ public String toString() {
+ return addTypeString(baseName(), this);
+ }
+
+ /** Component of toString() before the type string. */
+ protected String baseName() {
+ MethodHandle mh = this;
+ while (mh instanceof BoundMethodHandle) {
+ Object info = MethodHandleNatives.getTargetInfo(mh);
+ if (info instanceof MethodHandle) {
+ mh = (MethodHandle) info;
+ } else {
+ String name = null;
+ if (info instanceof MemberName)
+ name = ((MemberName)info).getName();
+ if (name != null)
+ return name;
+ else
+ return noParens(super.toString()); // "invoke", probably
+ }
+ assert(mh != this);
+ }
+ return noParens(mh.toString());
+ }
+
+ private static String noParens(String str) {
+ int paren = str.indexOf('(');
+ if (paren >= 0) str = str.substring(0, paren);
+ return str;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/CallSite.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.empty.Empty;
+import sun.misc.Unsafe;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * A {@code CallSite} is a holder for a variable {@link MethodHandle},
+ * which is called its {@code target}.
+ * An {@code invokedynamic} instruction linked to a {@code CallSite} delegates
+ * all calls to the site's current target.
+ * A {@code CallSite} may be associated with several {@code invokedynamic}
+ * instructions, or it may be "free floating", associated with none.
+ * In any case, it may be invoked through an associated method handle
+ * called its {@linkplain #dynamicInvoker dynamic invoker}.
+ * <p>
+ * {@code CallSite} is an abstract class which does not allow
+ * direct subclassing by users. It has three immediate,
+ * concrete subclasses that may be either instantiated or subclassed.
+ * <ul>
+ * <li>If a mutable target is not required, an {@code invokedynamic} instruction
+ * may be permanently bound by means of a {@linkplain ConstantCallSite constant call site}.
+ * <li>If a mutable target is required which has volatile variable semantics,
+ * because updates to the target must be immediately and reliably witnessed by other threads,
+ * a {@linkplain VolatileCallSite volatile call site} may be used.
+ * <li>Otherwise, if a mutable target is required,
+ * a {@linkplain MutableCallSite mutable call site} may be used.
+ * </ul>
+ * <p>
+ * A non-constant call site may be <em>relinked</em> by changing its target.
+ * The new target must have the same {@linkplain MethodHandle#type() type}
+ * as the previous target.
+ * Thus, though a call site can be relinked to a series of
+ * successive targets, it cannot change its type.
+ * <p>
+ * Here is a sample use of call sites and bootstrap methods which links every
+ * dynamic call site to print its arguments:
+<blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java -->
+static void test() throws Throwable {
+ // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION
+ InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14);
+}
+private static void printArgs(Object... args) {
+ System.out.println(java.util.Arrays.deepToString(args));
+}
+private static final MethodHandle printArgs;
+static {
+ MethodHandles.Lookup lookup = MethodHandles.lookup();
+ Class thisClass = lookup.lookupClass(); // (who am I?)
+ printArgs = lookup.findStatic(thisClass,
+ "printArgs", MethodType.methodType(void.class, Object[].class));
+}
+private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) {
+ // ignore caller and name, but match the type:
+ return new ConstantCallSite(printArgs.asType(type));
+}
+</pre></blockquote>
+ * @author John Rose, JSR 292 EG
+ */
+abstract
+public class CallSite {
+ static { MethodHandleImpl.initStatics(); }
+
+ // Fields used only by the JVM. Do not use or change.
+ private MemberName vmmethod; // supplied by the JVM (ref. to calling method)
+ private int vmindex; // supplied by the JVM (BCI within calling method)
+
+ // The actual payload of this call site:
+ /*package-private*/
+ MethodHandle target;
+
+ /**
+ * Make a blank call site object with the given method type.
+ * An initial target method is supplied which will throw
+ * an {@link IllegalStateException} if called.
+ * <p>
+ * Before this {@code CallSite} object is returned from a bootstrap method,
+ * it is usually provided with a more useful target method,
+ * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
+ * @throws NullPointerException if the proposed type is null
+ */
+ /*package-private*/
+ CallSite(MethodType type) {
+ target = type.invokers().uninitializedCallSite();
+ }
+
+ /**
+ * Make a blank call site object, possibly equipped with an initial target method handle.
+ * @param target the method handle which will be the initial target of the call site
+ * @throws NullPointerException if the proposed target is null
+ */
+ /*package-private*/
+ CallSite(MethodHandle target) {
+ target.type(); // null check
+ this.target = target;
+ }
+
+ /**
+ * Returns the type of this call site's target.
+ * Although targets may change, any call site's type is permanent, and can never change to an unequal type.
+ * The {@code setTarget} method enforces this invariant by refusing any new target that does
+ * not have the previous target's type.
+ * @return the type of the current target, which is also the type of any future target
+ */
+ public MethodType type() {
+ return target.type();
+ }
+
+ /** Called from JVM (or low-level Java code) after the BSM returns the newly created CallSite.
+ * The parameters are JVM-specific.
+ */
+ void initializeFromJVM(String name,
+ MethodType type,
+ MemberName callerMethod,
+ int callerBCI) {
+ if (this.vmmethod != null) {
+ // FIXME
+ throw new BootstrapMethodError("call site has already been linked to an invokedynamic instruction");
+ }
+ if (!this.type().equals(type)) {
+ throw wrongTargetType(target, type);
+ }
+ this.vmindex = callerBCI;
+ this.vmmethod = callerMethod;
+ }
+
+ /**
+ * Returns the target method of the call site, according to the
+ * behavior defined by this call site's specific class.
+ * The immediate subclasses of {@code CallSite} document the
+ * class-specific behaviors of this method.
+ *
+ * @return the current linkage state of the call site, its target method handle
+ * @see ConstantCallSite
+ * @see VolatileCallSite
+ * @see #setTarget
+ * @see ConstantCallSite#getTarget
+ * @see MutableCallSite#getTarget
+ * @see VolatileCallSite#getTarget
+ */
+ public abstract MethodHandle getTarget();
+
+ /**
+ * Updates the target method of this call site, according to the
+ * behavior defined by this call site's specific class.
+ * The immediate subclasses of {@code CallSite} document the
+ * class-specific behaviors of this method.
+ * <p>
+ * The type of the new target must be {@linkplain MethodType#equals equal to}
+ * the type of the old target.
+ *
+ * @param newTarget the new target
+ * @throws NullPointerException if the proposed new target is null
+ * @throws WrongMethodTypeException if the proposed new target
+ * has a method type that differs from the previous target
+ * @see CallSite#getTarget
+ * @see ConstantCallSite#setTarget
+ * @see MutableCallSite#setTarget
+ * @see VolatileCallSite#setTarget
+ */
+ public abstract void setTarget(MethodHandle newTarget);
+
+ void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
+ MethodType oldType = oldTarget.type();
+ MethodType newType = newTarget.type(); // null check!
+ if (!newType.equals(oldType))
+ throw wrongTargetType(newTarget, oldType);
+ }
+
+ private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) {
+ return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type);
+ }
+
+ /**
+ * Produces a method handle equivalent to an invokedynamic instruction
+ * which has been linked to this call site.
+ * <p>
+ * This method is equivalent to the following code:
+ * <blockquote><pre>
+ * MethodHandle getTarget, invoker, result;
+ * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
+ * invoker = MethodHandles.exactInvoker(this.type());
+ * result = MethodHandles.foldArguments(invoker, getTarget)
+ * </pre></blockquote>
+ *
+ * @return a method handle which always invokes this call site's current target
+ */
+ public abstract MethodHandle dynamicInvoker();
+
+ /*non-public*/ MethodHandle makeDynamicInvoker() {
+ MethodHandle getTarget = MethodHandleImpl.bindReceiver(GET_TARGET, this);
+ MethodHandle invoker = MethodHandles.exactInvoker(this.type());
+ return MethodHandles.foldArguments(invoker, getTarget);
+ }
+
+ private static final MethodHandle GET_TARGET;
+ static {
+ try {
+ GET_TARGET = IMPL_LOOKUP.
+ findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
+ } catch (ReflectiveOperationException ignore) {
+ throw new InternalError();
+ }
+ }
+
+ /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
+ /*package-private*/
+ static Empty uninitializedCallSite() {
+ throw new IllegalStateException("uninitialized call site");
+ }
+
+ // unsafe stuff:
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ private static final long TARGET_OFFSET;
+
+ static {
+ try {
+ TARGET_OFFSET = unsafe.objectFieldOffset(CallSite.class.getDeclaredField("target"));
+ } catch (Exception ex) { throw new Error(ex); }
+ }
+
+ /*package-private*/
+ void setTargetNormal(MethodHandle newTarget) {
+ target = newTarget;
+ }
+ /*package-private*/
+ MethodHandle getTargetVolatile() {
+ return (MethodHandle) unsafe.getObjectVolatile(this, TARGET_OFFSET);
+ }
+ /*package-private*/
+ void setTargetVolatile(MethodHandle newTarget) {
+ unsafe.putObjectVolatile(this, TARGET_OFFSET, newTarget);
+ }
+
+ // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
+ static CallSite makeSite(MethodHandle bootstrapMethod,
+ // Callee information:
+ String name, MethodType type,
+ // Extra arguments for BSM, if any:
+ Object info,
+ // Caller information:
+ MemberName callerMethod, int callerBCI) {
+ Class<?> callerClass = callerMethod.getDeclaringClass();
+ Object caller = IMPL_LOOKUP.in(callerClass);
+ CallSite site;
+ try {
+ Object binding;
+ info = maybeReBox(info);
+ if (info == null) {
+ binding = bootstrapMethod.invokeGeneric(caller, name, type);
+ } else if (!info.getClass().isArray()) {
+ binding = bootstrapMethod.invokeGeneric(caller, name, type, info);
+ } else {
+ Object[] argv = (Object[]) info;
+ maybeReBoxElements(argv);
+ if (3 + argv.length > 255)
+ throw new BootstrapMethodError("too many bootstrap method arguments");
+ MethodType bsmType = bootstrapMethod.type();
+ if (bsmType.parameterCount() == 4 && bsmType.parameterType(3) == Object[].class)
+ binding = bootstrapMethod.invokeGeneric(caller, name, type, argv);
+ else
+ binding = MethodHandles.spreadInvoker(bsmType, 3)
+ .invokeGeneric(bootstrapMethod, caller, name, type, argv);
+ }
+ //System.out.println("BSM for "+name+type+" => "+binding);
+ if (binding instanceof CallSite) {
+ site = (CallSite) binding;
+ } else {
+ throw new ClassCastException("bootstrap method failed to produce a CallSite");
+ }
+ assert(site.getTarget() != null);
+ assert(site.getTarget().type().equals(type));
+ } catch (Throwable ex) {
+ BootstrapMethodError bex;
+ if (ex instanceof BootstrapMethodError)
+ bex = (BootstrapMethodError) ex;
+ else
+ bex = new BootstrapMethodError("call site initialization exception", ex);
+ throw bex;
+ }
+ return site;
+ }
+
+ private static Object maybeReBox(Object x) {
+ if (x instanceof Integer) {
+ int xi = (int) x;
+ if (xi == (byte) xi)
+ x = xi; // must rebox; see JLS 5.1.7
+ }
+ return x;
+ }
+ private static void maybeReBoxElements(Object[] xa) {
+ for (int i = 0; i < xa.length; i++) {
+ xa[i] = maybeReBox(xa[i]);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/ConstantCallSite.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
+ * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
+ * bound to the call site's target.
+ * @author John Rose, JSR 292 EG
+ */
+public class ConstantCallSite extends CallSite {
+ /**
+ * Creates a call site with a permanent target.
+ * @param target the target to be permanently associated with this call site
+ * @throws NullPointerException if the proposed target is null
+ */
+ public ConstantCallSite(MethodHandle target) {
+ super(target);
+ }
+
+ /**
+ * Returns the target method of the call site, which behaves
+ * like a {@code final} field of the {@code ConstantCallSite}.
+ * That is, the the target is always the original value passed
+ * to the constructor call which created this instance.
+ *
+ * @return the immutable linkage state of this call site, a constant method handle
+ * @throws UnsupportedOperationException because this kind of call site cannot change its target
+ */
+ @Override public final MethodHandle getTarget() {
+ return target;
+ }
+
+ /**
+ * Always throws an {@link UnsupportedOperationException}.
+ * This kind of call site cannot change its target.
+ * @param ignore a new target proposed for the call site, which is ignored
+ * @throws UnsupportedOperationException because this kind of call site cannot change its target
+ */
+ @Override public final void setTarget(MethodHandle ignore) {
+ throw new UnsupportedOperationException("ConstantCallSite");
+ }
+
+ /**
+ * Returns this call site's permanent target.
+ * Since that target will never change, this is a correct implementation
+ * of {@link CallSite#dynamicInvoker CallSite.dynamicInvoker}.
+ * @return the immutable linkage state of this call site, a constant method handle
+ */
+ @Override
+ public final MethodHandle dynamicInvoker() {
+ return getTarget();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/DirectMethodHandle.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+
+/**
+ * The flavor of method handle which emulates invokespecial or invokestatic.
+ * @author jrose
+ */
+class DirectMethodHandle extends MethodHandle {
+ //inherited oop vmtarget; // methodOop or virtual class/interface oop
+ private final int vmindex; // method index within class or interface
+ { vmindex = VM_INDEX_UNINITIALIZED; } // JVM may change this
+
+ // Constructors in this class *must* be package scoped or private.
+ DirectMethodHandle(MethodType mtype, MemberName m, boolean doDispatch, Class<?> lookupClass) {
+ super(mtype);
+
+ assert(m.isMethod() || !doDispatch && m.isConstructor());
+ if (!m.isResolved())
+ throw new InternalError();
+
+ MethodHandleNatives.init(this, (Object) m, doDispatch, lookupClass);
+ }
+
+ boolean isValid() {
+ return (vmindex != VM_INDEX_UNINITIALIZED);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/FilterGeneric.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,4496 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.lang.reflect.*;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * These adapters apply arbitrary conversions to arguments
+ * on the way to a ultimate target.
+ * For simplicity, these are all generically typed.
+ * @author jrose
+ */
+class FilterGeneric {
+ // type for the incoming call (will be generic)
+ private final MethodType entryType;
+ // prototype adapters (clone and customize for each new target & conversion!)
+ private final Adapter[] adapters;
+
+ /** Compute and cache information common to all filtering adapters
+ * with the given generic type
+ */
+ FilterGeneric(MethodType entryType) {
+ this.entryType = entryType;
+ int tableSize = Kind.LIMIT.invokerIndex(1 + entryType.parameterCount());
+ this.adapters = new Adapter[tableSize];
+ }
+
+ Adapter getAdapter(Kind kind, int pos) {
+ int index = kind.invokerIndex(pos);
+ Adapter ad = adapters[index];
+ if (ad != null) return ad;
+ ad = findAdapter(entryType, kind, pos);
+ if (ad == null)
+ ad = buildAdapterFromBytecodes(entryType, kind, pos);
+ adapters[index] = ad;
+ return ad;
+ }
+
+ Adapter makeInstance(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
+ Adapter ad = getAdapter(kind, pos);
+ return ad.makeInstance(ad.prototypeEntryPoint(), filter, target);
+ }
+
+ /** Build an adapter of the given generic type, which invokes filter
+ * on the selected incoming argument before passing it to the target.
+ * @param pos the argument to filter
+ * @param filter the function to call on the argument
+ * @param target the target to call with the modified argument list
+ * @return an adapter method handle
+ */
+ public static MethodHandle makeArgumentFilter(int pos, MethodHandle filter, MethodHandle target) {
+ return make(Kind.value, pos, filter, target);
+ }
+
+ /** Build an adapter of the given generic type, which invokes a combiner
+ * on a selected group of leading arguments.
+ * The result of the combiner is prepended before all those arguments.
+ * @param combiner the function to call on the selected leading arguments
+ * @param target the target to call with the modified argument list
+ * @return an adapter method handle
+ */
+ public static MethodHandle makeArgumentFolder(MethodHandle combiner, MethodHandle target) {
+ int num = combiner.type().parameterCount();
+ return make(Kind.fold, num, combiner, target);
+ }
+
+ /** Build an adapter of the given generic type, which invokes a filter
+ * on the incoming arguments, reified as a group.
+ * The argument may be modified (by side effects in the filter).
+ * The arguments, possibly modified, are passed on to the target.
+ * @param filter the function to call on the arguments
+ * @param target the target to call with the possibly-modified argument list
+ * @return an adapter method handle
+ */
+ public static MethodHandle makeFlyby(MethodHandle filter, MethodHandle target) {
+ return make(Kind.flyby, 0, filter, target);
+ }
+
+ /** Build an adapter of the given generic type, which invokes a collector
+ * on the selected incoming argument and all following arguments.
+ * The result of the collector replaces all those arguments.
+ * @param collector the function to call on the selected trailing arguments
+ * @param target the target to call with the modified argument list
+ * @return an adapter method handle
+ */
+ public static MethodHandle makeArgumentCollector(MethodHandle collector, MethodHandle target) {
+ int pos = target.type().parameterCount() - 1;
+ return make(Kind.collect, pos, collector, target);
+ }
+
+ static MethodHandle make(Kind kind, int pos, MethodHandle filter, MethodHandle target) {
+ FilterGeneric fgen = of(kind, pos, filter.type(), target.type());
+ return fgen.makeInstance(kind, pos, filter, target);
+ }
+
+ /** Return the adapter information for this target and filter type. */
+ static FilterGeneric of(Kind kind, int pos, MethodType filterType, MethodType targetType) {
+ MethodType entryType = entryType(kind, pos, filterType, targetType);
+ if (entryType.generic() != entryType)
+ throw newIllegalArgumentException("must be generic: "+entryType);
+ MethodTypeForm form = entryType.form();
+ FilterGeneric filterGen = form.filterGeneric;
+ if (filterGen == null)
+ form.filterGeneric = filterGen = new FilterGeneric(entryType);
+ return filterGen;
+ }
+
+ public String toString() {
+ return "FilterGeneric/"+entryType;
+ }
+
+ static MethodType targetType(MethodType entryType, Kind kind, int pos, MethodType filterType) {
+ MethodType type = entryType;
+ switch (kind) {
+ case value:
+ case flyby:
+ break; // no change
+ case fold:
+ type = type.insertParameterTypes(0, filterType.returnType());
+ break;
+ case collect:
+ type = type.dropParameterTypes(pos, type.parameterCount());
+ type = type.insertParameterTypes(pos, filterType.returnType());
+ break;
+ default:
+ throw new InternalError();
+ }
+ return type;
+ }
+
+ static MethodType entryType(Kind kind, int pos, MethodType filterType, MethodType targetType) {
+ MethodType type = targetType;
+ switch (kind) {
+ case value:
+ case flyby:
+ break; // no change
+ case fold:
+ type = type.dropParameterTypes(0, 1);
+ break;
+ case collect:
+ type = type.dropParameterTypes(pos, pos+1);
+ type = type.insertParameterTypes(pos, filterType.parameterList());
+ break;
+ default:
+ throw new InternalError();
+ }
+ return type;
+ }
+
+ /* Create an adapter that handles spreading calls for the given type. */
+ static Adapter findAdapter(MethodType entryType, Kind kind, int pos) {
+ int argc = entryType.parameterCount();
+ String cname0 = "F"+argc;
+ String cname1 = "F"+argc+kind.key;
+ String[] cnames = { cname0, cname1 };
+ String iname = kind.invokerName(pos);
+ // e.g., F5; invoke_C3
+ for (String cname : cnames) {
+ Class<? extends Adapter> acls = Adapter.findSubClass(cname);
+ if (acls == null) continue;
+ // see if it has the required invoke method
+ MethodHandle entryPoint = null;
+ try {
+ entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
+ } catch (ReflectiveOperationException ex) {
+ }
+ if (entryPoint == null) continue;
+ Constructor<? extends Adapter> ctor = null;
+ try {
+ ctor = acls.getDeclaredConstructor(MethodHandle.class);
+ } catch (NoSuchMethodException ex) {
+ } catch (SecurityException ex) {
+ }
+ if (ctor == null) continue;
+ try {
+ // Produce an instance configured as a prototype.
+ return ctor.newInstance(entryPoint);
+ } catch (IllegalArgumentException ex) {
+ } catch (InvocationTargetException wex) {
+ Throwable ex = wex.getTargetException();
+ if (ex instanceof Error) throw (Error)ex;
+ if (ex instanceof RuntimeException) throw (RuntimeException)ex;
+ } catch (InstantiationException ex) {
+ } catch (IllegalAccessException ex) {
+ }
+ }
+ return null;
+ }
+
+ static Adapter buildAdapterFromBytecodes(MethodType entryType, Kind kind, int pos) {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ /**
+ * This adapter takes some untyped arguments, and returns an untyped result.
+ * Internally, it applies the invoker to the target, which causes the
+ * objects to be unboxed; the result is a raw type in L/I/J/F/D.
+ * This result is passed to convert, which is responsible for
+ * converting the raw result into a boxed object.
+ * The invoker is kept separate from the target because it can be
+ * generated once per type erasure family, and reused across adapters.
+ */
+ static abstract class Adapter extends BoundMethodHandle {
+ protected final MethodHandle filter; // transforms one or more arguments
+ protected final MethodHandle target; // ultimate target
+
+ @Override
+ public String toString() {
+ return addTypeString(target, this);
+ }
+
+ protected boolean isPrototype() { return target == null; }
+ protected Adapter(MethodHandle entryPoint) {
+ this(entryPoint, entryPoint, null);
+ assert(isPrototype());
+ }
+ protected MethodHandle prototypeEntryPoint() {
+ if (!isPrototype()) throw new InternalError();
+ return filter;
+ }
+
+ protected Adapter(MethodHandle entryPoint,
+ MethodHandle filter, MethodHandle target) {
+ super(entryPoint);
+ this.filter = filter;
+ this.target = target;
+ }
+
+ /** Make a copy of self, with new fields. */
+ protected abstract Adapter makeInstance(MethodHandle entryPoint,
+ MethodHandle filter, MethodHandle target);
+ // { return new ThisType(entryPoint, filter, target); }
+
+ static private final String CLASS_PREFIX; // "java.lang.invoke.FilterGeneric$"
+ static {
+ String aname = Adapter.class.getName();
+ String sname = Adapter.class.getSimpleName();
+ if (!aname.endsWith(sname)) throw new InternalError();
+ CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
+ }
+ /** Find a sibing class of Adapter. */
+ static Class<? extends Adapter> findSubClass(String name) {
+ String cname = Adapter.CLASS_PREFIX + name;
+ try {
+ return Class.forName(cname).asSubclass(Adapter.class);
+ } catch (ClassNotFoundException ex) {
+ return null;
+ } catch (ClassCastException ex) {
+ return null;
+ }
+ }
+ }
+
+ static enum Kind {
+ value('V'), // filter and replace Nth argument value
+ fold('F'), // fold first N arguments, prepend result
+ collect('C'), // collect last N arguments, replace with result
+ flyby('Y'), // reify entire argument list, filter, pass to target
+ LIMIT('?');
+ static final int COUNT = LIMIT.ordinal();
+
+ final char key;
+ Kind(char key) { this.key = key; }
+ String invokerName(int pos) { return "invoke_"+key+""+pos; }
+ int invokerIndex(int pos) { return pos * COUNT + ordinal(); }
+ }
+
+ /* generated classes follow this pattern:
+ static class F1X extends Adapter {
+ protected F1X(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F1X(MethodHandle e, MethodHandle f, MethodHandle t)
+ { super(e, f, t); }
+ protected F1X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
+ { return new F1X(e, f, t); }
+ protected Object invoke_V0(Object a0) { return target.invokeExact(filter.invokeExact(a0)); }
+ protected Object invoke_F0(Object a0) { return target.invokeExact(filter.invokeExact(), a0); }
+ protected Object invoke_F1(Object a0) { return target.invokeExact(filter.invokeExact(a0), a0); }
+ protected Object invoke_C0(Object a0) { return target.invokeExact(filter.invokeExact(a0)); }
+ protected Object invoke_C1(Object a0) { return target.invokeExact(a0, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0) { Object[] av = { a0 };
+ filter.invokeExact(av); return target.invokeExact(av[0]); }
+ }
+ static class F2X extends Adapter {
+ protected F2X(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F2X(MethodHandle e, MethodHandle f, MethodHandle t)
+ { super(e, f, t); }
+ protected F2X makeInstance(MethodHandle e, MethodHandle f, MethodHandle t)
+ { return new F2X(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0), a1); }
+ protected Object invoke_V1(Object a0, Object a1) { return target.invokeExact(a0, filter.invokeExact(a1)); }
+ protected Object invoke_F0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(), a0, a1); }
+ protected Object invoke_F1(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0), a0, a1); }
+ protected Object invoke_F2(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0, a1), a0, a1); }
+ protected Object invoke_C0(Object a0, Object a1) { return target.invokeExact(filter.invokeExact(a0, a1)); }
+ protected Object invoke_C1(Object a0, Object a1) { return target.invokeExact(a0, filter.invokeExact(a1)); }
+ protected Object invoke_C2(Object a0, Object a1) { return target.invokeExact(a0, a1, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1) { Object[] av = { a0, a1 };
+ filter.invokeExact(av); return target.invokeExact(av[0], av[1]); }
+ }
+ // */
+
+ // This one is written by hand:
+ static class F0 extends Adapter {
+ protected F0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F0(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F0 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F0(e, f, t); }
+ protected Object invoke_F0() throws Throwable {
+ return target.invokeExact(filter.invokeExact()); }
+ protected Object invoke_C0() throws Throwable {
+ return target.invokeExact(filter.invokeExact()); }
+ static final Object[] NO_ARGS = { };
+ protected Object invoke_Y0() throws Throwable {
+ filter.invokeExact(NO_ARGS); // make the flyby
+ return target.invokeExact(); }
+ }
+
+/*
+ : SHELL; n=FilterGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -ea -cp . genclasses | sed 's| *[/]/ *$||') >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
+//{{{
+import java.util.*;
+class genclasses {
+ static String[][] TEMPLATES = { {
+ "@for@ N=1..20",
+ " //@each-cat@",
+ " static class @cat@ extends Adapter {",
+ " protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
+ " protected @cat@(MethodHandle e, MethodHandle f, MethodHandle t) {",
+ " super(e, f, t); }",
+ " protected @cat@ makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {",
+ " return new @cat@(e, f, t); }",
+ " //@each-P@",
+ " protected Object invoke_V@P@(@Tvav@) throws Throwable {",
+ " return target.invokeExact(@a0_@@Psp@filter.invokeExact(a@P@)@_aN@); }",
+ " //@end-P@",
+ " //@each-P@",
+ " protected Object invoke_F@P@(@Tvav@) throws Throwable {",
+ " return target.invokeExact(filter.invokeExact(@a0@),",
+ " @av@); }",
+ " //@end-P@",
+ " protected Object invoke_F@N@(@Tvav@) throws Throwable {",
+ " return target.invokeExact(filter.invokeExact(@av@),",
+ " @av@); }",
+ " //@each-P@",
+ " protected Object invoke_C@P@(@Tvav@) throws Throwable {",
+ " return target.invokeExact(@a0_@filter.invokeExact(a@P@@_aN@)); }",
+ " //@end-P@",
+ " protected Object invoke_C@N@(@Tvav@) throws Throwable {",
+ " return target.invokeExact(@av@, filter.invokeExact()); }",
+ " protected Object invoke_Y0(@Tvav@) throws Throwable {",
+ " Object[] av = { @av@ };",
+ " filter.invokeExact(av); // make the flyby",
+ " return target.invokeExact(@av[i]@); }",
+ " }",
+ } };
+ static final String NEWLINE_INDENT = " //\n ";
+ enum VAR {
+ cat, N, P, Tvav, av, a0, a0_, _aN, Psp, av_i_;
+ public final String pattern = "@"+toString().replace('_','.')+"@";
+ public String binding = toString();
+ static void makeBindings(boolean topLevel, int inargs, int pos) {
+ assert(-1 <= pos && pos < inargs);
+ VAR.cat.binding = "F"+inargs;
+ VAR.N.binding = String.valueOf(inargs); // incoming arg count
+ VAR.P.binding = String.valueOf(pos); // selected arg position
+ String[] av = new String[inargs];
+ String[] Tvav = new String[inargs];
+ String[] av_i_ = new String[inargs];
+ for (int i = 0; i < inargs; i++) {
+ av[i] = arg(i);
+ av_i_[i] = "av["+i+"]";
+ String spc = "";
+ if (i > 0 && i % 4 == 0) spc = NEWLINE_INDENT+(pos>9?" ":"")+" ";
+ Tvav[i] = spc+param("Object", av[i]);
+ }
+ VAR.av.binding = comma(av);
+ VAR.av_i_.binding = comma(av_i_);
+ VAR.Tvav.binding = comma(Tvav);
+ if (pos >= 0) {
+ VAR.Psp.binding = (pos > 0 && pos % 10 == 0) ? NEWLINE_INDENT : "";
+ String[] a0 = new String[pos];
+ String[] aN = new String[inargs - (pos+1)];
+ for (int i = 0; i < pos; i++) {
+ String spc = "";
+ if (i > 0 && i % 10 == 0) spc = NEWLINE_INDENT;
+ a0[i] = spc+av[i];
+ }
+ VAR.a0.binding = comma(a0);
+ VAR.a0_.binding = comma(a0, ", ");
+ for (int i = pos+1; i < inargs; i++) {
+ String spc = "";
+ if (i > 0 && i % 10 == 0) spc = NEWLINE_INDENT;
+ aN[i - (pos+1)] = spc+av[i];
+ }
+ VAR._aN.binding = comma(", ", aN);
+ }
+ }
+ static String arg(int i) { return "a"+i; }
+ static String param(String t, String a) { return t+" "+a; }
+ static String comma(String[] v) { return comma(v, ""); }
+ static String comma(String[] v, String sep) { return comma("", v, sep); }
+ static String comma(String sep, String[] v) { return comma(sep, v, ""); }
+ static String comma(String sep1, String[] v, String sep2) {
+ if (v.length == 0) return "";
+ String res = v[0];
+ for (int i = 1; i < v.length; i++) res += ", "+v[i];
+ return sep1 + res + sep2;
+ }
+ static String transform(String string) {
+ for (VAR var : values())
+ string = string.replaceAll(var.pattern, var.binding);
+ return string;
+ }
+ }
+ static String[] stringsIn(String[] strings, int beg, int end) {
+ return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
+ }
+ static String[] stringsBefore(String[] strings, int pos) {
+ return stringsIn(strings, 0, pos);
+ }
+ static String[] stringsAfter(String[] strings, int pos) {
+ return stringsIn(strings, pos, strings.length);
+ }
+ static int indexAfter(String[] strings, int pos, String tag) {
+ return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
+ }
+ static int indexBefore(String[] strings, int pos, String tag) {
+ for (int i = pos, end = strings.length; ; i++) {
+ if (i == end || strings[i].endsWith(tag)) return i;
+ }
+ }
+ static int MIN_ARITY, MAX_ARITY;
+ public static void main(String... av) {
+ for (String[] template : TEMPLATES) {
+ int forLinesLimit = indexBefore(template, 0, "@each-cat@");
+ String[] forLines = stringsBefore(template, forLinesLimit);
+ template = stringsAfter(template, forLinesLimit);
+ for (String forLine : forLines)
+ expandTemplate(forLine, template);
+ }
+ }
+ static void expandTemplate(String forLine, String[] template) {
+ String[] params = forLine.split("[^0-9]+");
+ if (params[0].length() == 0) params = stringsAfter(params, 1);
+ System.out.println("//params="+Arrays.asList(params));
+ int pcur = 0;
+ MIN_ARITY = Integer.valueOf(params[pcur++]);
+ MAX_ARITY = Integer.valueOf(params[pcur++]);
+ if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
+ for (int inargs = MIN_ARITY; inargs <= MAX_ARITY; inargs++) {
+ expandTemplate(template, true, inargs, -1);
+ }
+ }
+ static void expandTemplate(String[] template, boolean topLevel, int inargs, int pos) {
+ VAR.makeBindings(topLevel, inargs, pos);
+ for (int i = 0; i < template.length; i++) {
+ String line = template[i];
+ if (line.endsWith("@each-cat@")) {
+ // ignore
+ } else if (line.endsWith("@each-P@")) {
+ int blockEnd = indexAfter(template, i, "@end-P@");
+ String[] block = stringsIn(template, i+1, blockEnd-1);
+ for (int pos1 = Math.max(0,pos); pos1 < inargs; pos1++)
+ expandTemplate(block, false, inargs, pos1);
+ VAR.makeBindings(topLevel, inargs, pos);
+ i = blockEnd-1; continue;
+ } else {
+ System.out.println(VAR.transform(line));
+ }
+ }
+ }
+}
+//}}} */
+//params=[1, 20]
+ static class F1 extends Adapter {
+ protected F1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F1(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F1 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F1(e, f, t); }
+ protected Object invoke_V0(Object a0) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0)); }
+ protected Object invoke_F0(Object a0) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0); }
+ protected Object invoke_F1(Object a0) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0); }
+ protected Object invoke_C0(Object a0) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0)); }
+ protected Object invoke_C1(Object a0) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0) throws Throwable {
+ Object[] av = { a0 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0]); }
+ }
+ static class F2 extends Adapter {
+ protected F2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F2(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F2 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F2(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1); }
+ protected Object invoke_V1(Object a0, Object a1) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1)); }
+ protected Object invoke_F0(Object a0, Object a1) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1); }
+ protected Object invoke_F1(Object a0, Object a1) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1); }
+ protected Object invoke_F2(Object a0, Object a1) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1); }
+ protected Object invoke_C0(Object a0, Object a1) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1)); }
+ protected Object invoke_C1(Object a0, Object a1) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1)); }
+ protected Object invoke_C2(Object a0, Object a1) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1) throws Throwable {
+ Object[] av = { a0, a1 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1]); }
+ }
+ static class F3 extends Adapter {
+ protected F3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F3(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F3 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F3(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2) throws Throwable {
+ Object[] av = { a0, a1, a2 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2]); }
+ }
+ static class F4 extends Adapter {
+ protected F4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F4(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F4 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F4(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ Object[] av = { a0, a1, a2, a3 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3]); }
+ }
+ static class F5 extends Adapter {
+ protected F5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F5(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F5 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F5(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4]); }
+ }
+ static class F6 extends Adapter {
+ protected F6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F6(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F6 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F6(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5]); }
+ }
+ static class F7 extends Adapter {
+ protected F7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F7(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F7 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F7(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6]); }
+ }
+ static class F8 extends Adapter {
+ protected F8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F8(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F8 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F8(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7]); }
+ }
+ static class F9 extends Adapter {
+ protected F9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F9(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F9 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F9(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8]); }
+ }
+ static class F10 extends Adapter {
+ protected F10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F10(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F10 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F10(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9]); }
+ }
+ static class F11 extends Adapter {
+ protected F11(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F11(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F11 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F11(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+ a10); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
+ a10); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
+ a10); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
+ a10); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
+ a10); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
+ a10); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
+ a10); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
+ a10); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
+ a10); }
+ protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ filter.invokeExact(a10)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
+ a10)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
+ a10)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
+ a10)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
+ a10)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
+ a10)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
+ a10)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
+ a10)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
+ a10)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10)); }
+ protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10]); }
+ }
+ static class F12 extends Adapter {
+ protected F12(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F12(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F12 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F12(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
+ a10, a11); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
+ a10, a11); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
+ a10, a11); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
+ a10, a11); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
+ a10, a11); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
+ a10, a11); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
+ a10, a11); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
+ a10, a11); }
+ protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ filter.invokeExact(a10), a11); }
+ protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
+ a10, a11)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
+ a10, a11)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
+ a10, a11)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
+ a10, a11)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
+ a10, a11)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
+ a10, a11)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
+ a10, a11)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11)); }
+ protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11)); }
+ protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11]); }
+ }
+ static class F13 extends Adapter {
+ protected F13(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F13(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F13 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F13(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
+ a10, a11, a12); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
+ a10, a11, a12); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
+ a10, a11, a12); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
+ a10, a11, a12); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
+ a10, a11, a12); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
+ a10, a11, a12); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
+ a10, a11, a12); }
+ protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ filter.invokeExact(a10), a11, a12); }
+ protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11), a12); }
+ protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
+ a10, a11, a12)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
+ a10, a11, a12)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
+ a10, a11, a12)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
+ a10, a11, a12)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
+ a10, a11, a12)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
+ a10, a11, a12)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12)); }
+ protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11, a12)); }
+ protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12)); }
+ protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12]); }
+ }
+ static class F14 extends Adapter {
+ protected F14(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F14(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F14 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F14(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
+ a10, a11, a12, a13); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
+ a10, a11, a12, a13); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
+ a10, a11, a12, a13); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
+ a10, a11, a12, a13); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
+ a10, a11, a12, a13); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
+ a10, a11, a12, a13); }
+ protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ filter.invokeExact(a10), a11, a12, a13); }
+ protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11), a12, a13); }
+ protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12), a13); }
+ protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
+ a10, a11, a12, a13)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
+ a10, a11, a12, a13)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
+ a10, a11, a12, a13)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
+ a10, a11, a12, a13)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
+ a10, a11, a12, a13)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13)); }
+ protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11, a12, a13)); }
+ protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12, a13)); }
+ protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13)); }
+ protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13]); }
+ }
+ static class F15 extends Adapter {
+ protected F15(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F15(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F15 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F15(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
+ a10, a11, a12, a13, a14); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
+ a10, a11, a12, a13, a14); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
+ a10, a11, a12, a13, a14); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
+ a10, a11, a12, a13, a14); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
+ a10, a11, a12, a13, a14); }
+ protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ filter.invokeExact(a10), a11, a12, a13, a14); }
+ protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11), a12, a13, a14); }
+ protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12), a13, a14); }
+ protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13), a14); }
+ protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
+ a10, a11, a12, a13, a14)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
+ a10, a11, a12, a13, a14)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
+ a10, a11, a12, a13, a14)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
+ a10, a11, a12, a13, a14)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14)); }
+ protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11, a12, a13, a14)); }
+ protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12, a13, a14)); }
+ protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13, a14)); }
+ protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14)); }
+ protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14]); }
+ }
+ static class F16 extends Adapter {
+ protected F16(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F16(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F16 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F16(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
+ a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
+ a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
+ a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
+ a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ filter.invokeExact(a10), a11, a12, a13, a14, a15); }
+ protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11), a12, a13, a14, a15); }
+ protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12), a13, a14, a15); }
+ protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13), a14, a15); }
+ protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14), a15); }
+ protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, filter.invokeExact(a15)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
+ a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
+ a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
+ a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14, a15)); }
+ protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11, a12, a13, a14, a15)); }
+ protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12, a13, a14, a15)); }
+ protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13, a14, a15)); }
+ protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14, a15)); }
+ protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, filter.invokeExact(a15)); }
+ protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15]); }
+ }
+ static class F17 extends Adapter {
+ protected F17(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F17(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F17 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F17(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
+ a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
+ a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
+ a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ filter.invokeExact(a10), a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11), a12, a13, a14, a15, a16); }
+ protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12), a13, a14, a15, a16); }
+ protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13), a14, a15, a16); }
+ protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14), a15, a16); }
+ protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, filter.invokeExact(a15), a16); }
+ protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, filter.invokeExact(a16)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
+ a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
+ a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11, a12, a13, a14, a15, a16)); }
+ protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12, a13, a14, a15, a16)); }
+ protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13, a14, a15, a16)); }
+ protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14, a15, a16)); }
+ protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, filter.invokeExact(a15, a16)); }
+ protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, filter.invokeExact(a16)); }
+ protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16]); }
+ }
+ static class F18 extends Adapter {
+ protected F18(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F18(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F18 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F18(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
+ a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
+ a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ filter.invokeExact(a10), a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11), a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12), a13, a14, a15, a16, a17); }
+ protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13), a14, a15, a16, a17); }
+ protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14), a15, a16, a17); }
+ protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, filter.invokeExact(a15), a16, a17); }
+ protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, filter.invokeExact(a16), a17); }
+ protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
+ a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11, a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12, a13, a14, a15, a16, a17)); }
+ protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13, a14, a15, a16, a17)); }
+ protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14, a15, a16, a17)); }
+ protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, filter.invokeExact(a15, a16, a17)); }
+ protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, filter.invokeExact(a16, a17)); }
+ protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17)); }
+ protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17]); }
+ }
+ static class F19 extends Adapter {
+ protected F19(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F19(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F19 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F19(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
+ a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ filter.invokeExact(a10), a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11), a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12), a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13), a14, a15, a16, a17, a18); }
+ protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14), a15, a16, a17, a18); }
+ protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, filter.invokeExact(a15), a16, a17, a18); }
+ protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, filter.invokeExact(a16), a17, a18); }
+ protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17), a18); }
+ protected Object invoke_V18(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(a18)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_F19(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11, a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12, a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13, a14, a15, a16, a17, a18)); }
+ protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14, a15, a16, a17, a18)); }
+ protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, filter.invokeExact(a15, a16, a17, a18)); }
+ protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, filter.invokeExact(a16, a17, a18)); }
+ protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17, a18)); }
+ protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(a18)); }
+ protected Object invoke_C19(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18]); }
+ }
+ static class F20 extends Adapter {
+ protected F20(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected F20(MethodHandle e, MethodHandle f, MethodHandle t) {
+ super(e, f, t); }
+ protected F20 makeInstance(MethodHandle e, MethodHandle f, MethodHandle t) {
+ return new F20(e, f, t); }
+ protected Object invoke_V0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0), a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1), a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2), a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3), a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4), a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5), a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6), a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7), a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8), a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9),
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ filter.invokeExact(a10), a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11), a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12), a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13), a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_V14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14), a15, a16, a17, a18, a19); }
+ protected Object invoke_V15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, filter.invokeExact(a15), a16, a17, a18, a19); }
+ protected Object invoke_V16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, filter.invokeExact(a16), a17, a18, a19); }
+ protected Object invoke_V17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17), a18, a19); }
+ protected Object invoke_V18(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(a18), a19); }
+ protected Object invoke_V19(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact(a19)); }
+ protected Object invoke_F0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F18(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F19(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_F20(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19),
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); }
+ protected Object invoke_C0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(filter.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C1(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, filter.invokeExact(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C2(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, filter.invokeExact(a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C3(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, filter.invokeExact(a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C4(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, filter.invokeExact(a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C5(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, filter.invokeExact(a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C6(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, filter.invokeExact(a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C7(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, filter.invokeExact(a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C8(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, filter.invokeExact(a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C9(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, filter.invokeExact(a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C10(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, filter.invokeExact(a10, a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C11(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, filter.invokeExact(a11, a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C12(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, filter.invokeExact(a12, a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C13(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, filter.invokeExact(a13, a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C14(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, filter.invokeExact(a14, a15, a16, a17, a18, a19)); }
+ protected Object invoke_C15(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, filter.invokeExact(a15, a16, a17, a18, a19)); }
+ protected Object invoke_C16(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, filter.invokeExact(a16, a17, a18, a19)); }
+ protected Object invoke_C17(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, filter.invokeExact(a17, a18, a19)); }
+ protected Object invoke_C18(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, filter.invokeExact(a18, a19)); }
+ protected Object invoke_C19(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,
+ a10, a11, a12, a13, a14, a15, a16, a17, a18, filter.invokeExact(a19)); }
+ protected Object invoke_C20(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, filter.invokeExact()); }
+ protected Object invoke_Y0(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9, Object a10, Object a11,
+ Object a12, Object a13, Object a14, Object a15,
+ Object a16, Object a17, Object a18, Object a19) throws Throwable {
+ Object[] av = { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19 };
+ filter.invokeExact(av); // make the flyby
+ return target.invokeExact(av[0], av[1], av[2], av[3], av[4], av[5], av[6], av[7], av[8], av[9], av[10], av[11], av[12], av[13], av[14], av[15], av[16], av[17], av[18], av[19]); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/FilterOneArgument.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Unary function composition, useful for many small plumbing jobs.
+ * The invoke method takes a single reference argument, and returns a reference
+ * Internally, it first calls the {@code filter} method on the argument,
+ * Making up the difference between the raw method type and the
+ * final method type is the responsibility of a JVM-level adapter.
+ * @author jrose
+ */
+class FilterOneArgument extends BoundMethodHandle {
+ protected final MethodHandle filter; // Object -> Object
+ protected final MethodHandle target; // Object -> Object
+
+ @Override
+ public String toString() {
+ return target.toString();
+ }
+
+ protected Object invoke(Object argument) throws Throwable {
+ Object filteredArgument = filter.invokeExact(argument);
+ return target.invokeExact(filteredArgument);
+ }
+
+ private static final MethodHandle INVOKE;
+ static {
+ try {
+ INVOKE =
+ IMPL_LOOKUP.findVirtual(FilterOneArgument.class, "invoke",
+ MethodType.genericMethodType(1));
+ } catch (ReflectiveOperationException ex) {
+ throw uncaughtException(ex);
+ }
+ }
+
+ protected FilterOneArgument(MethodHandle filter, MethodHandle target) {
+ super(INVOKE);
+ this.filter = filter;
+ this.target = target;
+ }
+
+ public static MethodHandle make(MethodHandle filter, MethodHandle target) {
+ if (filter == null) return target;
+ if (target == null) return filter;
+ return new FilterOneArgument(filter, target);
+ }
+
+// MethodHandle make(MethodHandle filter1, MethodHandle filter2, MethodHandle target) {
+// MethodHandle filter = make(filter1, filter2);
+// return make(filter, target);
+// }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/FromGeneric.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,630 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
+import java.lang.reflect.*;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Adapters which mediate between incoming calls which are generic
+ * and outgoing calls which are not. Any call can be represented generically
+ * boxing up its arguments, and (on return) unboxing the return value.
+ * <p>
+ * A call is "generic" (in MethodHandle terms) if its MethodType features
+ * only Object arguments. A non-generic call therefore features
+ * primitives and/or reference types other than Object.
+ * An adapter has types for its incoming and outgoing calls.
+ * The incoming call type is simply determined by the adapter's type
+ * (the MethodType it presents to callers). The outgoing call type
+ * is determined by the adapter's target (a MethodHandle that the adapter
+ * either binds internally or else takes as a leading argument).
+ * (To stretch the term, adapter-like method handles may have multiple
+ * targets or be polymorphic across multiple call types.)
+ * @author jrose
+ */
+class FromGeneric {
+ // type for the outgoing call (may have primitives, etc.)
+ private final MethodType targetType;
+ // type of the outgoing call internal to the adapter
+ private final MethodType internalType;
+ // prototype adapter (clone and customize for each new target!)
+ private final Adapter adapter;
+ // entry point for adapter (Adapter mh, a...) => ...
+ private final MethodHandle entryPoint;
+ // unboxing invoker of type (MH, Object**N) => raw return value
+ // it makes up the difference of internalType => targetType
+ private final MethodHandle unboxingInvoker;
+ // conversion which boxes a the target's raw return value
+ private final MethodHandle returnConversion;
+
+ /** Compute and cache information common to all unboxing adapters
+ * that can call out to targets of the erasure-family of the given erased type.
+ */
+ private FromGeneric(MethodType targetType) {
+ this.targetType = targetType;
+ MethodType internalType0;
+ // the target invoker will generally need casts on reference arguments
+ Adapter ad = findAdapter(internalType0 = targetType.erase());
+ if (ad != null) {
+ // Immediate hit to exactly the adapter we want,
+ // with no monkeying around with primitive types.
+ this.internalType = internalType0;
+ this.adapter = ad;
+ this.entryPoint = ad.prototypeEntryPoint();
+ this.returnConversion = computeReturnConversion(targetType, internalType0);
+ this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
+ return;
+ }
+
+ // outgoing primitive arguments will be wrapped; unwrap them
+ MethodType primsAsObj = targetType.form().primArgsAsBoxes();
+ MethodType objArgsRawRet = primsAsObj.form().primsAsInts();
+ if (objArgsRawRet != targetType)
+ ad = findAdapter(internalType0 = objArgsRawRet);
+ if (ad == null) {
+ ad = buildAdapterFromBytecodes(internalType0 = targetType);
+ }
+ this.internalType = internalType0;
+ this.adapter = ad;
+ MethodType tepType = targetType.insertParameterTypes(0, adapter.getClass());
+ this.entryPoint = ad.prototypeEntryPoint();
+ this.returnConversion = computeReturnConversion(targetType, internalType0);
+ this.unboxingInvoker = computeUnboxingInvoker(targetType, internalType0);
+ }
+
+ /**
+ * The typed target will be called according to targetType.
+ * The adapter code will in fact see the raw result from internalType,
+ * and must box it into an object. Produce a converter for this.
+ */
+ private static MethodHandle computeReturnConversion(
+ MethodType targetType, MethodType internalType) {
+ Class<?> tret = targetType.returnType();
+ Class<?> iret = internalType.returnType();
+ Wrapper wrap = Wrapper.forBasicType(tret);
+ if (!iret.isPrimitive()) {
+ assert(iret == Object.class);
+ return ValueConversions.identity();
+ } else if (wrap.primitiveType() == iret) {
+ return ValueConversions.box(wrap, false);
+ } else {
+ assert(tret == double.class ? iret == long.class : iret == int.class);
+ return ValueConversions.boxRaw(wrap, false);
+ }
+ }
+
+ /**
+ * The typed target will need an exact invocation point; provide it here.
+ * The adapter will possibly need to make a slightly different call,
+ * so adapt the invoker. This way, the logic for making up the
+ * difference between what the adapter can call and what the target
+ * needs can be cached once per type.
+ */
+ private static MethodHandle computeUnboxingInvoker(
+ MethodType targetType, MethodType internalType) {
+ // All the adapters we have here have reference-untyped internal calls.
+ assert(internalType == internalType.erase());
+ MethodHandle invoker = targetType.invokers().exactInvoker();
+ // cast all narrow reference types, unbox all primitive arguments:
+ MethodType fixArgsType = internalType.changeReturnType(targetType.returnType());
+ MethodHandle fixArgs = MethodHandleImpl.convertArguments(
+ invoker, Invokers.invokerType(fixArgsType),
+ invoker.type(), null);
+ if (fixArgs == null)
+ throw new InternalError("bad fixArgs");
+ // reinterpret the calling sequence as raw:
+ MethodHandle retyper = AdapterMethodHandle.makeRetypeRaw(
+ Invokers.invokerType(internalType), fixArgs);
+ if (retyper == null)
+ throw new InternalError("bad retyper");
+ return retyper;
+ }
+
+ Adapter makeInstance(MethodHandle typedTarget) {
+ MethodType type = typedTarget.type();
+ if (type == targetType) {
+ return adapter.makeInstance(entryPoint, unboxingInvoker, returnConversion, typedTarget);
+ }
+ // my erased-type is not exactly the same as the desired type
+ assert(type.erase() == targetType); // else we are busted
+ MethodHandle invoker = computeUnboxingInvoker(type, internalType);
+ return adapter.makeInstance(entryPoint, invoker, returnConversion, typedTarget);
+ }
+
+ /** Build an adapter of the given generic type, which invokes typedTarget
+ * on the incoming arguments, after unboxing as necessary.
+ * The return value is boxed if necessary.
+ * @param genericType the required type of the result
+ * @param typedTarget the target
+ * @return an adapter method handle
+ */
+ public static MethodHandle make(MethodHandle typedTarget) {
+ MethodType type = typedTarget.type();
+ if (type == type.generic()) return typedTarget;
+ return FromGeneric.of(type).makeInstance(typedTarget);
+ }
+
+ /** Return the adapter information for this type's erasure. */
+ static FromGeneric of(MethodType type) {
+ MethodTypeForm form = type.form();
+ FromGeneric fromGen = form.fromGeneric;
+ if (fromGen == null)
+ form.fromGeneric = fromGen = new FromGeneric(form.erasedType());
+ return fromGen;
+ }
+
+ public String toString() {
+ return "FromGeneric"+targetType;
+ }
+
+ /* Create an adapter that handles spreading calls for the given type. */
+ static Adapter findAdapter(MethodType internalType) {
+ MethodType entryType = internalType.generic();
+ MethodTypeForm form = internalType.form();
+ Class<?> rtype = internalType.returnType();
+ int argc = form.parameterCount();
+ int lac = form.longPrimitiveParameterCount();
+ int iac = form.primitiveParameterCount() - lac;
+ String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
+ String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
+ String cname0 = rawReturn + argc;
+ String cname1 = "A" + argc;
+ String[] cnames = { cname0+intsAndLongs, cname0, cname1+intsAndLongs, cname1 };
+ String iname = "invoke_"+cname0+intsAndLongs;
+ // e.g., D5I2, D5, L5I2, L5; invoke_D5
+ for (String cname : cnames) {
+ Class<? extends Adapter> acls = Adapter.findSubClass(cname);
+ if (acls == null) continue;
+ // see if it has the required invoke method
+ MethodHandle entryPoint = null;
+ try {
+ entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
+ } catch (ReflectiveOperationException ex) {
+ }
+ if (entryPoint == null) continue;
+ Constructor<? extends Adapter> ctor = null;
+ try {
+ ctor = acls.getDeclaredConstructor(MethodHandle.class);
+ } catch (NoSuchMethodException ex) {
+ } catch (SecurityException ex) {
+ }
+ if (ctor == null) continue;
+ try {
+ // Produce an instance configured as a prototype.
+ return ctor.newInstance(entryPoint);
+ } catch (IllegalArgumentException ex) {
+ } catch (InvocationTargetException wex) {
+ Throwable ex = wex.getTargetException();
+ if (ex instanceof Error) throw (Error)ex;
+ if (ex instanceof RuntimeException) throw (RuntimeException)ex;
+ } catch (InstantiationException ex) {
+ } catch (IllegalAccessException ex) {
+ }
+ }
+ return null;
+ }
+
+ static Adapter buildAdapterFromBytecodes(MethodType internalType) {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ /**
+ * This adapter takes some untyped arguments, and returns an untyped result.
+ * Internally, it applies the invoker to the target, which causes the
+ * objects to be unboxed; the result is a raw type in L/I/J/F/D.
+ * This result is passed to convert, which is responsible for
+ * converting the raw result into a boxed object.
+ * The invoker is kept separate from the target because it can be
+ * generated once per type erasure family, and reused across adapters.
+ */
+ static abstract class Adapter extends BoundMethodHandle {
+ /*
+ * class X<<R,int N>> extends Adapter {
+ * (MH, Object**N)=>raw(R) invoker;
+ * (any**N)=>R target;
+ * raw(R)=>Object convert;
+ * Object invoke(Object**N a) = convert(invoker(target, a...))
+ * }
+ */
+ protected final MethodHandle invoker; // (MH, Object**N) => raw(R)
+ protected final MethodHandle convert; // raw(R) => Object
+ protected final MethodHandle target; // (any**N) => R
+
+ @Override
+ public String toString() {
+ return addTypeString(target, this);
+ }
+
+ protected boolean isPrototype() { return target == null; }
+ protected Adapter(MethodHandle entryPoint) {
+ this(entryPoint, null, entryPoint, null);
+ assert(isPrototype());
+ }
+ protected MethodHandle prototypeEntryPoint() {
+ if (!isPrototype()) throw new InternalError();
+ return convert;
+ }
+
+ protected Adapter(MethodHandle entryPoint,
+ MethodHandle invoker, MethodHandle convert, MethodHandle target) {
+ super(entryPoint);
+ this.invoker = invoker;
+ this.convert = convert;
+ this.target = target;
+ }
+
+ /** Make a copy of self, with new fields. */
+ protected abstract Adapter makeInstance(MethodHandle entryPoint,
+ MethodHandle invoker, MethodHandle convert, MethodHandle target);
+ // { return new ThisType(entryPoint, convert, target); }
+
+ /// Conversions on the value returned from the target.
+ protected Object convert_L(Object result) throws Throwable { return convert.invokeExact(result); }
+ protected Object convert_I(int result) throws Throwable { return convert.invokeExact(result); }
+ protected Object convert_J(long result) throws Throwable { return convert.invokeExact(result); }
+ protected Object convert_F(float result) throws Throwable { return convert.invokeExact(result); }
+ protected Object convert_D(double result) throws Throwable { return convert.invokeExact(result); }
+
+ static private final String CLASS_PREFIX; // "java.lang.invoke.FromGeneric$"
+ static {
+ String aname = Adapter.class.getName();
+ String sname = Adapter.class.getSimpleName();
+ if (!aname.endsWith(sname)) throw new InternalError();
+ CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
+ }
+ /** Find a sibing class of Adapter. */
+ static Class<? extends Adapter> findSubClass(String name) {
+ String cname = Adapter.CLASS_PREFIX + name;
+ try {
+ return Class.forName(cname).asSubclass(Adapter.class);
+ } catch (ClassNotFoundException ex) {
+ return null;
+ } catch (ClassCastException ex) {
+ return null;
+ }
+ }
+ }
+
+ /* generated classes follow this pattern:
+ static class xA2 extends Adapter {
+ protected xA2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected xA2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected xA2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new xA2(e, i, c, t); }
+ protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
+ protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1)); }
+ protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1)); }
+ protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
+ protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
+ }
+ // */
+
+/*
+: SHELL; n=FromGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
+//{{{
+import java.util.*;
+class genclasses {
+ static String[] TYPES = { "Object", "int ", "long ", "float ", "double" };
+ static String[] WRAPS = { " ", "(Integer)", "(Long) ", "(Float) ", "(Double) " };
+ static String[] TCHARS = { "L", "I", "J", "F", "D", "A" };
+ static String[][] TEMPLATES = { {
+ "@for@ arity=0..10 rcat<=4 nrefs<=99 nints=0 nlongs=0",
+ " //@each-cat@",
+ " static class @cat@ extends Adapter {",
+ " protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
+ " protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
+ " { super(e, i, c, t); }",
+ " protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)",
+ " { return new @cat@(e, i, c, t); }",
+ " //@each-R@",
+ " protected Object invoke_@catN@(@Tvav@) throws Throwable { return convert_@Rc@((@R@)@W@invoker.invokeExact(target@av@)); }",
+ " //@end-R@",
+ " }",
+ } };
+ static final String NEWLINE_INDENT = "\n ";
+ enum VAR {
+ cat, catN, R, Rc, W, av, Tvav, Ovav;
+ public final String pattern = "@"+toString().replace('_','.')+"@";
+ public String binding;
+ static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
+ int nargs = nrefs + nints + nlongs;
+ if (topLevel)
+ VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
+ VAR.catN.binding = catstr(rcat, nrefs, nints, nlongs);
+ VAR.R.binding = TYPES[rcat];
+ VAR.Rc.binding = TCHARS[rcat];
+ VAR.W.binding = WRAPS[rcat];
+ String[] Tv = new String[nargs];
+ String[] av = new String[nargs];
+ String[] Tvav = new String[nargs];
+ String[] Ovav = new String[nargs];
+ for (int i = 0; i < nargs; i++) {
+ int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
+ Tv[i] = TYPES[tcat];
+ av[i] = arg(i);
+ Tvav[i] = param(Tv[i], av[i]);
+ Ovav[i] = param("Object", av[i]);
+ }
+ VAR.av.binding = comma(", ", av);
+ VAR.Tvav.binding = comma(Tvav);
+ VAR.Ovav.binding = comma(Ovav);
+ }
+ static String arg(int i) { return "a"+i; }
+ static String param(String t, String a) { return t+" "+a; }
+ static String comma(String[] v) { return comma("", v); }
+ static String comma(String sep, String[] v) {
+ if (v.length == 0) return "";
+ String res = sep+v[0];
+ for (int i = 1; i < v.length; i++) res += ", "+v[i];
+ return res;
+ }
+ static String transform(String string) {
+ for (VAR var : values())
+ string = string.replaceAll(var.pattern, var.binding);
+ return string;
+ }
+ }
+ static String[] stringsIn(String[] strings, int beg, int end) {
+ return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
+ }
+ static String[] stringsBefore(String[] strings, int pos) {
+ return stringsIn(strings, 0, pos);
+ }
+ static String[] stringsAfter(String[] strings, int pos) {
+ return stringsIn(strings, pos, strings.length);
+ }
+ static int indexAfter(String[] strings, int pos, String tag) {
+ return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
+ }
+ static int indexBefore(String[] strings, int pos, String tag) {
+ for (int i = pos, end = strings.length; ; i++) {
+ if (i == end || strings[i].endsWith(tag)) return i;
+ }
+ }
+ static int MIN_ARITY, MAX_ARITY, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
+ static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
+ static HashSet<String> done = new HashSet<String>();
+ public static void main(String... av) {
+ for (String[] template : TEMPLATES) {
+ int forLinesLimit = indexBefore(template, 0, "@each-cat@");
+ String[] forLines = stringsBefore(template, forLinesLimit);
+ template = stringsAfter(template, forLinesLimit);
+ for (String forLine : forLines)
+ expandTemplate(forLine, template);
+ }
+ }
+ static void expandTemplate(String forLine, String[] template) {
+ String[] params = forLine.split("[^0-9]+");
+ if (params[0].length() == 0) params = stringsAfter(params, 1);
+ System.out.println("//params="+Arrays.asList(params));
+ int pcur = 0;
+ MIN_ARITY = Integer.valueOf(params[pcur++]);
+ MAX_ARITY = Integer.valueOf(params[pcur++]);
+ MAX_RCAT = Integer.valueOf(params[pcur++]);
+ MAX_REFS = Integer.valueOf(params[pcur++]);
+ MAX_INTS = Integer.valueOf(params[pcur++]);
+ MAX_LONGS = Integer.valueOf(params[pcur++]);
+ if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
+ if (MAX_RCAT >= TYPES.length) MAX_RCAT = TYPES.length - 1;
+ ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
+ ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
+ for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
+ for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
+ expandTemplate(template, true, rcat, nargs, 0, 0);
+ if (ALL_ARG_TYPES) break;
+ expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
+ if (ALL_RETURN_TYPES) break;
+ }
+ }
+ }
+ static String catstr(int rcat, int nrefs, int nints, int nlongs) {
+ int nargs = nrefs + nints + nlongs;
+ String cat = TCHARS[rcat] + nargs;
+ if (!ALL_ARG_TYPES) cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
+ return cat;
+ }
+ static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
+ for (int isLong = 0; isLong <= 1; isLong++) {
+ for (int nprims = 1; nprims <= nargs; nprims++) {
+ int nrefs = nargs - nprims;
+ int nints = ((1-isLong) * nprims);
+ int nlongs = (isLong * nprims);
+ expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
+ }
+ }
+ }
+ static void expandTemplate(String[] template, boolean topLevel,
+ int rcat, int nrefs, int nints, int nlongs) {
+ int nargs = nrefs + nints + nlongs;
+ if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS) return;
+ VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+ if (topLevel && !done.add(VAR.cat.binding)) {
+ System.out.println(" //repeat "+VAR.cat.binding);
+ return;
+ }
+ for (int i = 0; i < template.length; i++) {
+ String line = template[i];
+ if (line.endsWith("@each-cat@")) {
+ // ignore
+ } else if (line.endsWith("@each-R@")) {
+ int blockEnd = indexAfter(template, i, "@end-R@");
+ String[] block = stringsIn(template, i+1, blockEnd-1);
+ for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
+ expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
+ VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+ i = blockEnd-1; continue;
+ } else if (line.endsWith("@each-Tv@")) {
+ int blockEnd = indexAfter(template, i, "@end-Tv@");
+ String[] block = stringsIn(template, i+1, blockEnd-1);
+ expandTemplate(block, false, rcat, nrefs, nints, nlongs);
+ expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
+ VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+ i = blockEnd-1; continue;
+ } else {
+ System.out.println(VAR.transform(line));
+ }
+ }
+ }
+}
+//}}} */
+//params=[0, 10, 4, 99, 0, 0]
+ static class A0 extends Adapter {
+ protected A0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A0(e, i, c, t); }
+ protected Object invoke_L0() throws Throwable { return convert_L((Object)invoker.invokeExact(target)); }
+ protected Object invoke_I0() throws Throwable { return convert_I((int) invoker.invokeExact(target)); }
+ protected Object invoke_J0() throws Throwable { return convert_J((long) invoker.invokeExact(target)); }
+ protected Object invoke_F0() throws Throwable { return convert_F((float) invoker.invokeExact(target)); }
+ protected Object invoke_D0() throws Throwable { return convert_D((double)invoker.invokeExact(target)); }
+ }
+ static class A1 extends Adapter {
+ protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A1(e, i, c, t); }
+ protected Object invoke_L1(Object a0) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0)); }
+ protected Object invoke_I1(Object a0) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0)); }
+ protected Object invoke_J1(Object a0) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0)); }
+ protected Object invoke_F1(Object a0) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0)); }
+ protected Object invoke_D1(Object a0) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0)); }
+ }
+ static class A2 extends Adapter {
+ protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A2(e, i, c, t); }
+ protected Object invoke_L2(Object a0, Object a1) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1)); }
+ protected Object invoke_I2(Object a0, Object a1) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1)); }
+ protected Object invoke_J2(Object a0, Object a1) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1)); }
+ protected Object invoke_F2(Object a0, Object a1) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1)); }
+ protected Object invoke_D2(Object a0, Object a1) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1)); }
+ }
+ static class A3 extends Adapter {
+ protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A3(e, i, c, t); }
+ protected Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2)); }
+ protected Object invoke_I3(Object a0, Object a1, Object a2) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2)); }
+ protected Object invoke_J3(Object a0, Object a1, Object a2) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2)); }
+ protected Object invoke_F3(Object a0, Object a1, Object a2) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2)); }
+ protected Object invoke_D3(Object a0, Object a1, Object a2) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2)); }
+ }
+ static class A4 extends Adapter {
+ protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A4(e, i, c, t); }
+ protected Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3)); }
+ protected Object invoke_I4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3)); }
+ protected Object invoke_J4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3)); }
+ protected Object invoke_F4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3)); }
+ protected Object invoke_D4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3)); }
+ }
+ static class A5 extends Adapter {
+ protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A5(e, i, c, t); }
+ protected Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
+ protected Object invoke_I5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
+ protected Object invoke_J5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
+ protected Object invoke_F5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
+ protected Object invoke_D5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4)); }
+ }
+ static class A6 extends Adapter {
+ protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A6(e, i, c, t); }
+ protected Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_I6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_J6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_F6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_D6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5)); }
+ }
+ static class A7 extends Adapter {
+ protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A7(e, i, c, t); }
+ protected Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_I7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_J7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_F7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_D7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6)); }
+ }
+ static class A8 extends Adapter {
+ protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A8(e, i, c, t); }
+ protected Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_I8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_J8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_F8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_D8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7)); }
+ }
+ static class A9 extends Adapter {
+ protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A9(e, i, c, t); }
+ protected Object invoke_L9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_I9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_J9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_F9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_D9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ }
+ static class A10 extends Adapter {
+ protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { super(e, i, c, t); }
+ protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t)
+ { return new A10(e, i, c, t); }
+ protected Object invoke_L10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_L((Object)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_I10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_I((int) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_J10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_J((long) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_F10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_F((float) invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_D10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return convert_D((double)invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/InvokeDynamic.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * This is a place-holder class. Some HotSpot implementations need to see it.
+ */
+final class InvokeDynamic {
+ private InvokeDynamic() { throw new InternalError(); } // do not instantiate
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/InvokeGeneric.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Adapters which manage MethodHandle.invokeGeneric calls.
+ * The JVM calls one of these when the exact type match fails.
+ * @author jrose
+ */
+class InvokeGeneric {
+ // erased type for the call, which originates from an invokeGeneric site
+ private final MethodType erasedCallerType;
+ // an invoker of type (MT, MH; A...) -> R
+ private final MethodHandle initialInvoker;
+
+ /** Compute and cache information for this adapter, so that it can
+ * call out to targets of the erasure-family of the given erased type.
+ */
+ /*non-public*/ InvokeGeneric(MethodType erasedCallerType) throws ReflectiveOperationException {
+ assert(erasedCallerType.equals(erasedCallerType.erase()));
+ this.erasedCallerType = erasedCallerType;
+ this.initialInvoker = makeInitialInvoker();
+ assert initialInvoker.type().equals(erasedCallerType
+ .insertParameterTypes(0, MethodType.class, MethodHandle.class))
+ : initialInvoker.type();
+ }
+
+ private static MethodHandles.Lookup lookup() {
+ return IMPL_LOOKUP;
+ }
+
+ /** Return the adapter information for this type's erasure. */
+ /*non-public*/ static MethodHandle genericInvokerOf(MethodType erasedCallerType) throws ReflectiveOperationException {
+ InvokeGeneric gen = new InvokeGeneric(erasedCallerType);
+ return gen.initialInvoker;
+ }
+
+ private MethodHandle makeInitialInvoker() throws ReflectiveOperationException {
+ // postDispatch = #(MH'; MT, MH; A...){MH'(MT, MH; A)}
+ MethodHandle postDispatch = makePostDispatchInvoker();
+ MethodHandle invoker;
+ if (returnConversionPossible()) {
+ invoker = MethodHandles.foldArguments(postDispatch,
+ dispatcher("dispatchWithConversion"));
+ } else {
+ invoker = MethodHandles.foldArguments(postDispatch, dispatcher("dispatch"));
+ }
+ return invoker;
+ }
+
+ private static final Class<?>[] EXTRA_ARGS = { MethodType.class, MethodHandle.class };
+ private MethodHandle makePostDispatchInvoker() {
+ // Take (MH'; MT, MH; A...) and run MH'(MT, MH; A...).
+ MethodType invokerType = erasedCallerType.insertParameterTypes(0, EXTRA_ARGS);
+ return invokerType.invokers().exactInvoker();
+ }
+ private MethodHandle dropDispatchArguments(MethodHandle targetInvoker) {
+ assert(targetInvoker.type().parameterType(0) == MethodHandle.class);
+ return MethodHandles.dropArguments(targetInvoker, 1, EXTRA_ARGS);
+ }
+
+ private MethodHandle dispatcher(String dispatchName) throws ReflectiveOperationException {
+ return lookup().bind(this, dispatchName,
+ MethodType.methodType(MethodHandle.class,
+ MethodType.class, MethodHandle.class));
+ }
+
+ static final boolean USE_AS_TYPE_PATH = true;
+
+ /** Return a method handle to invoke on the callerType, target, and remaining arguments.
+ * The method handle must finish the call.
+ * This is the first look at the caller type and target.
+ */
+ private MethodHandle dispatch(MethodType callerType, MethodHandle target) {
+ MethodType targetType = target.type();
+ if (USE_AS_TYPE_PATH || target.isVarargsCollector()) {
+ MethodHandle newTarget = target.asType(callerType);
+ targetType = callerType;
+ Invokers invokers = targetType.invokers();
+ MethodHandle invoker = invokers.erasedInvokerWithDrops;
+ if (invoker == null) {
+ invokers.erasedInvokerWithDrops = invoker =
+ dropDispatchArguments(invokers.erasedInvoker());
+ }
+ return invoker.bindTo(newTarget);
+ }
+ throw new RuntimeException("NYI");
+ }
+
+ private MethodHandle dispatchWithConversion(MethodType callerType, MethodHandle target) {
+ MethodHandle finisher = dispatch(callerType, target);
+ if (returnConversionNeeded(callerType, target))
+ finisher = addReturnConversion(finisher, callerType.returnType()); //FIXME: slow
+ return finisher;
+ }
+
+ private boolean returnConversionPossible() {
+ Class<?> needType = erasedCallerType.returnType();
+ return !needType.isPrimitive();
+ }
+ private boolean returnConversionNeeded(MethodType callerType, MethodHandle target) {
+ Class<?> needType = callerType.returnType();
+ if (needType == erasedCallerType.returnType())
+ return false; // no conversions possible, since must be primitive or Object
+ Class<?> haveType = target.type().returnType();
+ if (VerifyType.isNullConversion(haveType, needType))
+ return false;
+ return true;
+ }
+ private MethodHandle addReturnConversion(MethodHandle target, Class<?> type) {
+ if (true) throw new RuntimeException("NYI");
+ // FIXME: This is slow because it creates a closure node on every call that requires a return cast.
+ MethodType targetType = target.type();
+ MethodHandle caster = ValueConversions.identity(type);
+ caster = caster.asType(MethodType.methodType(type, targetType.returnType()));
+ // Drop irrelevant arguments, because we only care about the return value:
+ caster = MethodHandles.dropArguments(caster, 1, targetType.parameterList());
+ MethodHandle result = MethodHandles.foldArguments(caster, target);
+ return result.asType(target.type());
+ }
+
+ public String toString() {
+ return "InvokeGeneric"+erasedCallerType;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/Invokers.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.empty.Empty;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Construction and caching of often-used invokers.
+ * @author jrose
+ */
+class Invokers {
+ // exact type (sans leading taget MH) for the outgoing call
+ private final MethodType targetType;
+
+ // exact invoker for the outgoing call
+ private /*lazy*/ MethodHandle exactInvoker;
+
+ // erased (partially untyped but with primitives) invoker for the outgoing call
+ private /*lazy*/ MethodHandle erasedInvoker;
+ /*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric
+
+ // generic (untyped) invoker for the outgoing call
+ private /*lazy*/ MethodHandle genericInvoker;
+
+ // generic (untyped) invoker for the outgoing call; accepts a single Object[]
+ private final /*lazy*/ MethodHandle[] spreadInvokers;
+
+ // invoker for an unbound callsite
+ private /*lazy*/ MethodHandle uninitializedCallSite;
+
+ /** Compute and cache information common to all collecting adapters
+ * that implement members of the erasure-family of the given erased type.
+ */
+ /*non-public*/ Invokers(MethodType targetType) {
+ this.targetType = targetType;
+ this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
+ }
+
+ /*non-public*/ static MethodType invokerType(MethodType targetType) {
+ return targetType.insertParameterTypes(0, MethodHandle.class);
+ }
+
+ /*non-public*/ MethodHandle exactInvoker() {
+ MethodHandle invoker = exactInvoker;
+ if (invoker != null) return invoker;
+ try {
+ invoker = IMPL_LOOKUP.findVirtual(MethodHandle.class, "invokeExact", targetType);
+ } catch (ReflectiveOperationException ex) {
+ throw new InternalError("JVM cannot find invoker for "+targetType);
+ }
+ assert(invokerType(targetType) == invoker.type());
+ exactInvoker = invoker;
+ return invoker;
+ }
+
+ /*non-public*/ MethodHandle genericInvoker() {
+ MethodHandle invoker1 = exactInvoker();
+ MethodHandle invoker = genericInvoker;
+ if (invoker != null) return invoker;
+ MethodType genericType = targetType.generic();
+ invoker = MethodHandles.convertArguments(invoker1, invokerType(genericType));
+ genericInvoker = invoker;
+ return invoker;
+ }
+
+ /*non-public*/ MethodHandle erasedInvoker() {
+ MethodHandle invoker1 = exactInvoker();
+ MethodHandle invoker = erasedInvoker;
+ if (invoker != null) return invoker;
+ MethodType erasedType = targetType.erase();
+ if (erasedType == targetType.generic())
+ invoker = genericInvoker();
+ else
+ invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType));
+ erasedInvoker = invoker;
+ return invoker;
+ }
+
+ /*non-public*/ MethodHandle spreadInvoker(int objectArgCount) {
+ MethodHandle vaInvoker = spreadInvokers[objectArgCount];
+ if (vaInvoker != null) return vaInvoker;
+ MethodHandle gInvoker = genericInvoker();
+ vaInvoker = gInvoker.asSpreader(Object[].class, targetType.parameterCount() - objectArgCount);
+ spreadInvokers[objectArgCount] = vaInvoker;
+ return vaInvoker;
+ }
+
+ private static MethodHandle THROW_UCS = null;
+
+ /*non-public*/ MethodHandle uninitializedCallSite() {
+ MethodHandle invoker = uninitializedCallSite;
+ if (invoker != null) return invoker;
+ if (targetType.parameterCount() > 0) {
+ MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
+ Invokers invokers0 = type0.invokers();
+ invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
+ 0, targetType.parameterList());
+ assert(invoker.type().equals(targetType));
+ uninitializedCallSite = invoker;
+ return invoker;
+ }
+ if (THROW_UCS == null) {
+ try {
+ THROW_UCS = IMPL_LOOKUP
+ .findStatic(CallSite.class, "uninitializedCallSite",
+ MethodType.methodType(Empty.class));
+ } catch (ReflectiveOperationException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ invoker = AdapterMethodHandle.makeRetypeRaw(targetType, THROW_UCS);
+ assert(invoker.type().equals(targetType));
+ uninitializedCallSite = invoker;
+ return invoker;
+ }
+
+ public String toString() {
+ return "Invokers"+targetType;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MemberName.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,718 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.BytecodeDescriptor;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Member;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * A {@code MemberName} is a compact symbolic datum which fully characterizes
+ * a method or field reference.
+ * A member name refers to a field, method, constructor, or member type.
+ * Every member name has a simple name (a string) and a type (either a Class or MethodType).
+ * A member name may also have a non-null declaring class, or it may be simply
+ * a naked name/type pair.
+ * A member name may also have non-zero modifier flags.
+ * Finally, a member name may be either resolved or unresolved.
+ * If it is resolved, the existence of the named
+ * <p>
+ * Whether resolved or not, a member name provides no access rights or
+ * invocation capability to its possessor. It is merely a compact
+ * representation of all symbolic information necessary to link to
+ * and properly use the named member.
+ * <p>
+ * When resolved, a member name's internal implementation may include references to JVM metadata.
+ * This representation is stateless and only decriptive.
+ * It provides no private information and no capability to use the member.
+ * <p>
+ * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
+ * about the internals of a method (except its bytecodes) and also
+ * allows invocation. A MemberName is much lighter than a Method,
+ * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
+ * and those seven fields omit much of the information in Method.
+ * @author jrose
+ */
+/*non-public*/ final class MemberName implements Member, Cloneable {
+ private Class<?> clazz; // class in which the method is defined
+ private String name; // may be null if not yet materialized
+ private Object type; // may be null if not yet materialized
+ private int flags; // modifier bits; see reflect.Modifier
+
+ private Object vmtarget; // VM-specific target value
+ private int vmindex; // method index within class or interface
+
+ { vmindex = VM_INDEX_UNINITIALIZED; }
+
+ /** Return the declaring class of this member.
+ * In the case of a bare name and type, the declaring class will be null.
+ */
+ public Class<?> getDeclaringClass() {
+ if (clazz == null && isResolved()) {
+ expandFromVM();
+ }
+ return clazz;
+ }
+
+ /** Utility method producing the class loader of the declaring class. */
+ public ClassLoader getClassLoader() {
+ return clazz.getClassLoader();
+ }
+
+ /** Return the simple name of this member.
+ * For a type, it is the same as {@link Class#getSimpleName}.
+ * For a method or field, it is the simple name of the member.
+ * For a constructor, it is always {@code "<init>"}.
+ */
+ public String getName() {
+ if (name == null) {
+ expandFromVM();
+ if (name == null) return null;
+ }
+ return name;
+ }
+
+ /** Return the declared type of this member, which
+ * must be a method or constructor.
+ */
+ public MethodType getMethodType() {
+ if (type == null) {
+ expandFromVM();
+ if (type == null) return null;
+ }
+ if (!isInvocable())
+ throw newIllegalArgumentException("not invocable, no method type");
+ if (type instanceof MethodType) {
+ return (MethodType) type;
+ }
+ if (type instanceof String) {
+ String sig = (String) type;
+ MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
+ this.type = res;
+ return res;
+ }
+ if (type instanceof Object[]) {
+ Object[] typeInfo = (Object[]) type;
+ Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
+ Class<?> rtype = (Class<?>) typeInfo[0];
+ MethodType res = MethodType.methodType(rtype, ptypes);
+ this.type = res;
+ return res;
+ }
+ throw new InternalError("bad method type "+type);
+ }
+
+ /** Return the actual type under which this method or constructor must be invoked.
+ * For non-static methods or constructors, this is the type with a leading parameter,
+ * a reference to declaring class. For static methods, it is the same as the declared type.
+ */
+ public MethodType getInvocationType() {
+ MethodType itype = getMethodType();
+ if (!isStatic())
+ itype = itype.insertParameterTypes(0, clazz);
+ return itype;
+ }
+
+ /** Utility method producing the parameter types of the method type. */
+ public Class<?>[] getParameterTypes() {
+ return getMethodType().parameterArray();
+ }
+
+ /** Utility method producing the return type of the method type. */
+ public Class<?> getReturnType() {
+ return getMethodType().returnType();
+ }
+
+ /** Return the declared type of this member, which
+ * must be a field or type.
+ * If it is a type member, that type itself is returned.
+ */
+ public Class<?> getFieldType() {
+ if (type == null) {
+ expandFromVM();
+ if (type == null) return null;
+ }
+ if (isInvocable())
+ throw newIllegalArgumentException("not a field or nested class, no simple type");
+ if (type instanceof Class<?>) {
+ return (Class<?>) type;
+ }
+ if (type instanceof String) {
+ String sig = (String) type;
+ MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
+ Class<?> res = mtype.returnType();
+ this.type = res;
+ return res;
+ }
+ throw new InternalError("bad field type "+type);
+ }
+
+ /** Utility method to produce either the method type or field type of this member. */
+ public Object getType() {
+ return (isInvocable() ? getMethodType() : getFieldType());
+ }
+
+ /** Utility method to produce the signature of this member,
+ * used within the class file format to describe its type.
+ */
+ public String getSignature() {
+ if (type == null) {
+ expandFromVM();
+ if (type == null) return null;
+ }
+ if (type instanceof String)
+ return (String) type;
+ if (isInvocable())
+ return BytecodeDescriptor.unparse(getMethodType());
+ else
+ return BytecodeDescriptor.unparse(getFieldType());
+ }
+
+ /** Return the modifier flags of this member.
+ * @see java.lang.reflect.Modifier
+ */
+ public int getModifiers() {
+ return (flags & RECOGNIZED_MODIFIERS);
+ }
+
+ private void setFlags(int flags) {
+ this.flags = flags;
+ assert(testAnyFlags(ALL_KINDS));
+ }
+
+ private boolean testFlags(int mask, int value) {
+ return (flags & mask) == value;
+ }
+ private boolean testAllFlags(int mask) {
+ return testFlags(mask, mask);
+ }
+ private boolean testAnyFlags(int mask) {
+ return !testFlags(mask, 0);
+ }
+
+ /** Utility method to query the modifier flags of this member. */
+ public boolean isStatic() {
+ return Modifier.isStatic(flags);
+ }
+ /** Utility method to query the modifier flags of this member. */
+ public boolean isPublic() {
+ return Modifier.isPublic(flags);
+ }
+ /** Utility method to query the modifier flags of this member. */
+ public boolean isPrivate() {
+ return Modifier.isPrivate(flags);
+ }
+ /** Utility method to query the modifier flags of this member. */
+ public boolean isProtected() {
+ return Modifier.isProtected(flags);
+ }
+ /** Utility method to query the modifier flags of this member. */
+ public boolean isFinal() {
+ return Modifier.isFinal(flags);
+ }
+ /** Utility method to query the modifier flags of this member. */
+ public boolean isAbstract() {
+ return Modifier.isAbstract(flags);
+ }
+ // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
+
+ // unofficial modifier flags, used by HotSpot:
+ static final int BRIDGE = 0x00000040;
+ static final int VARARGS = 0x00000080;
+ static final int SYNTHETIC = 0x00001000;
+ static final int ANNOTATION= 0x00002000;
+ static final int ENUM = 0x00004000;
+ /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
+ public boolean isBridge() {
+ return testAllFlags(IS_METHOD | BRIDGE);
+ }
+ /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
+ public boolean isVarargs() {
+ return testAllFlags(VARARGS) && isInvocable();
+ }
+ /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
+ public boolean isSynthetic() {
+ return testAllFlags(SYNTHETIC);
+ }
+
+ static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
+
+ // modifiers exported by the JVM:
+ static final int RECOGNIZED_MODIFIERS = 0xFFFF;
+
+ // private flags, not part of RECOGNIZED_MODIFIERS:
+ static final int
+ IS_METHOD = MN_IS_METHOD, // method (not constructor)
+ IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
+ IS_FIELD = MN_IS_FIELD, // field
+ IS_TYPE = MN_IS_TYPE; // nested type
+ static final int // for MethodHandleNatives.getMembers
+ SEARCH_SUPERCLASSES = MN_SEARCH_SUPERCLASSES,
+ SEARCH_INTERFACES = MN_SEARCH_INTERFACES;
+
+ static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
+ static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
+ static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
+ static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
+ static final int SEARCH_ALL_SUPERS = SEARCH_SUPERCLASSES | SEARCH_INTERFACES;
+
+ /** Utility method to query whether this member is a method or constructor. */
+ public boolean isInvocable() {
+ return testAnyFlags(IS_INVOCABLE);
+ }
+ /** Utility method to query whether this member is a method, constructor, or field. */
+ public boolean isFieldOrMethod() {
+ return testAnyFlags(IS_FIELD_OR_METHOD);
+ }
+ /** Query whether this member is a method. */
+ public boolean isMethod() {
+ return testAllFlags(IS_METHOD);
+ }
+ /** Query whether this member is a constructor. */
+ public boolean isConstructor() {
+ return testAllFlags(IS_CONSTRUCTOR);
+ }
+ /** Query whether this member is a field. */
+ public boolean isField() {
+ return testAllFlags(IS_FIELD);
+ }
+ /** Query whether this member is a type. */
+ public boolean isType() {
+ return testAllFlags(IS_TYPE);
+ }
+ /** Utility method to query whether this member is neither public, private, nor protected. */
+ public boolean isPackage() {
+ return !testAnyFlags(ALL_ACCESS);
+ }
+
+ /** Initialize a query. It is not resolved. */
+ private void init(Class<?> defClass, String name, Object type, int flags) {
+ // defining class is allowed to be null (for a naked name/type pair)
+ //name.toString(); // null check
+ //type.equals(type); // null check
+ // fill in fields:
+ this.clazz = defClass;
+ this.name = name;
+ this.type = type;
+ setFlags(flags);
+ assert(!isResolved());
+ }
+
+ private void expandFromVM() {
+ if (!isResolved()) return;
+ if (type instanceof Object[])
+ type = null; // don't saddle JVM w/ typeInfo
+ MethodHandleNatives.expand(this);
+ }
+
+ // Capturing information from the Core Reflection API:
+ private static int flagsMods(int flags, int mods) {
+ assert((flags & RECOGNIZED_MODIFIERS) == 0);
+ assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
+ return flags | mods;
+ }
+ /** Create a name for the given reflected method. The resulting name will be in a resolved state. */
+ public MemberName(Method m) {
+ Object[] typeInfo = { m.getReturnType(), m.getParameterTypes() };
+ init(m.getDeclaringClass(), m.getName(), typeInfo, flagsMods(IS_METHOD, m.getModifiers()));
+ // fill in vmtarget, vmindex while we have m in hand:
+ MethodHandleNatives.init(this, m);
+ assert(isResolved());
+ }
+ /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */
+ public MemberName(Constructor ctor) {
+ Object[] typeInfo = { void.class, ctor.getParameterTypes() };
+ init(ctor.getDeclaringClass(), CONSTRUCTOR_NAME, typeInfo, flagsMods(IS_CONSTRUCTOR, ctor.getModifiers()));
+ // fill in vmtarget, vmindex while we have ctor in hand:
+ MethodHandleNatives.init(this, ctor);
+ assert(isResolved());
+ }
+ /** Create a name for the given reflected field. The resulting name will be in a resolved state. */
+ public MemberName(Field fld) {
+ init(fld.getDeclaringClass(), fld.getName(), fld.getType(), flagsMods(IS_FIELD, fld.getModifiers()));
+ // fill in vmtarget, vmindex while we have fld in hand:
+ MethodHandleNatives.init(this, fld);
+ assert(isResolved());
+ }
+ /** Create a name for the given class. The resulting name will be in a resolved state. */
+ public MemberName(Class<?> type) {
+ init(type.getDeclaringClass(), type.getSimpleName(), type, flagsMods(IS_TYPE, type.getModifiers()));
+ vmindex = 0; // isResolved
+ assert(isResolved());
+ }
+
+ // bare-bones constructor; the JVM will fill it in
+ MemberName() { }
+
+ // locally useful cloner
+ @Override protected MemberName clone() {
+ try {
+ return (MemberName) super.clone();
+ } catch (CloneNotSupportedException ex) {
+ throw new InternalError();
+ }
+ }
+
+ // %%% define equals/hashcode?
+
+ // Construction from symbolic parts, for queries:
+ /** Create a field or type name from the given components: Declaring class, name, type, modifiers.
+ * The declaring class may be supplied as null if this is to be a bare name and type.
+ * The resulting name will in an unresolved state.
+ */
+ public MemberName(Class<?> defClass, String name, Class<?> type, int modifiers) {
+ init(defClass, name, type, IS_FIELD | (modifiers & RECOGNIZED_MODIFIERS));
+ }
+ /** Create a field or type name from the given components: Declaring class, name, type.
+ * The declaring class may be supplied as null if this is to be a bare name and type.
+ * The modifier flags default to zero.
+ * The resulting name will in an unresolved state.
+ */
+ public MemberName(Class<?> defClass, String name, Class<?> type) {
+ this(defClass, name, type, 0);
+ }
+ /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers.
+ * It will be a constructor if and only if the name is {@code "<init>"}.
+ * The declaring class may be supplied as null if this is to be a bare name and type.
+ * The resulting name will in an unresolved state.
+ */
+ public MemberName(Class<?> defClass, String name, MethodType type, int modifiers) {
+ int flagBit = (name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
+ init(defClass, name, type, flagBit | (modifiers & RECOGNIZED_MODIFIERS));
+ }
+ /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers.
+ * It will be a constructor if and only if the name is {@code "<init>"}.
+ * The declaring class may be supplied as null if this is to be a bare name and type.
+ * The modifier flags default to zero.
+ * The resulting name will in an unresolved state.
+ */
+ public MemberName(Class<?> defClass, String name, MethodType type) {
+ this(defClass, name, type, 0);
+ }
+
+ /** Query whether this member name is resolved.
+ * A resolved member name is one for which the JVM has found
+ * a method, constructor, field, or type binding corresponding exactly to the name.
+ * (Document?)
+ */
+ public boolean isResolved() {
+ return (vmindex != VM_INDEX_UNINITIALIZED);
+ }
+
+ /** Query whether this member name is resolved to a non-static, non-final method.
+ */
+ public boolean hasReceiverTypeDispatch() {
+ return (isMethod() && getVMIndex() >= 0);
+ }
+
+ /** Produce a string form of this member name.
+ * For types, it is simply the type's own string (as reported by {@code toString}).
+ * For fields, it is {@code "DeclaringClass.name/type"}.
+ * For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}.
+ * If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted.
+ * If the member is unresolved, a prefix {@code "*."} is prepended.
+ */
+ @Override
+ public String toString() {
+ if (isType())
+ return type.toString(); // class java.lang.String
+ // else it is a field, method, or constructor
+ StringBuilder buf = new StringBuilder();
+ if (getDeclaringClass() != null) {
+ buf.append(getName(clazz));
+ buf.append('.');
+ }
+ String name = getName();
+ buf.append(name == null ? "*" : name);
+ Object type = getType();
+ if (!isInvocable()) {
+ buf.append('/');
+ buf.append(type == null ? "*" : getName(type));
+ } else {
+ buf.append(type == null ? "(*)*" : getName(type));
+ }
+ /*
+ buf.append('/');
+ // key: Public, private, pRotected, sTatic, Final, sYnchronized,
+ // transient/Varargs, native, (interface), abstract, sTrict, sYnthetic,
+ // (annotation), Enum, (unused)
+ final String FIELD_MOD_CHARS = "PprTF?vt????Y?E?";
+ final String METHOD_MOD_CHARS = "PprTFybVn?atY???";
+ String modChars = (isInvocable() ? METHOD_MOD_CHARS : FIELD_MOD_CHARS);
+ for (int i = 0; i < modChars.length(); i++) {
+ if ((flags & (1 << i)) != 0) {
+ char mc = modChars.charAt(i);
+ if (mc != '?')
+ buf.append(mc);
+ }
+ }
+ */
+ return buf.toString();
+ }
+ private static String getName(Object obj) {
+ if (obj instanceof Class<?>)
+ return ((Class<?>)obj).getName();
+ return String.valueOf(obj);
+ }
+
+ // Queries to the JVM:
+ /** Document? */
+ /*non-public*/ int getVMIndex() {
+ if (!isResolved())
+ throw newIllegalStateException("not resolved", this);
+ return vmindex;
+ }
+// /*non-public*/ Object getVMTarget() {
+// if (!isResolved())
+// throw newIllegalStateException("not resolved", this);
+// return vmtarget;
+// }
+
+ public IllegalAccessException makeAccessException(String message, Object from) {
+ message = message + ": "+ toString();
+ if (from != null) message += ", from " + from;
+ return new IllegalAccessException(message);
+ }
+ public ReflectiveOperationException makeAccessException(String message) {
+ message = message + ": "+ toString();
+ if (isResolved())
+ return new IllegalAccessException(message);
+ else if (isConstructor())
+ return new NoSuchMethodException(message);
+ else if (isMethod())
+ return new NoSuchMethodException(message);
+ else
+ return new NoSuchFieldException(message);
+ }
+
+ /** Actually making a query requires an access check. */
+ /*non-public*/ static Factory getFactory() {
+ return Factory.INSTANCE;
+ }
+ /** A factory type for resolving member names with the help of the VM.
+ * TBD: Define access-safe public constructors for this factory.
+ */
+ public static class Factory {
+ private Factory() { } // singleton pattern
+ static Factory INSTANCE = new Factory();
+
+ private static int ALLOWED_FLAGS = SEARCH_ALL_SUPERS | ALL_KINDS;
+
+ /// Queries
+ List<MemberName> getMembers(Class<?> defc,
+ String matchName, Object matchType,
+ int matchFlags, Class<?> lookupClass) {
+ matchFlags &= ALLOWED_FLAGS;
+ String matchSig = null;
+ if (matchType != null) {
+ matchSig = BytecodeDescriptor.unparse(matchType);
+ if (matchSig.startsWith("("))
+ matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
+ else
+ matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
+ }
+ final int BUF_MAX = 0x2000;
+ int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
+ MemberName[] buf = newMemberBuffer(len1);
+ int totalCount = 0;
+ ArrayList<MemberName[]> bufs = null;
+ int bufCount = 0;
+ for (;;) {
+ bufCount = MethodHandleNatives.getMembers(defc,
+ matchName, matchSig, matchFlags,
+ lookupClass,
+ totalCount, buf);
+ if (bufCount <= buf.length) {
+ if (bufCount < 0) bufCount = 0;
+ totalCount += bufCount;
+ break;
+ }
+ // JVM returned to us with an intentional overflow!
+ totalCount += buf.length;
+ int excess = bufCount - buf.length;
+ if (bufs == null) bufs = new ArrayList<MemberName[]>(1);
+ bufs.add(buf);
+ int len2 = buf.length;
+ len2 = Math.max(len2, excess);
+ len2 = Math.max(len2, totalCount / 4);
+ buf = newMemberBuffer(Math.min(BUF_MAX, len2));
+ }
+ ArrayList<MemberName> result = new ArrayList<MemberName>(totalCount);
+ if (bufs != null) {
+ for (MemberName[] buf0 : bufs) {
+ Collections.addAll(result, buf0);
+ }
+ }
+ result.addAll(Arrays.asList(buf).subList(0, bufCount));
+ // Signature matching is not the same as type matching, since
+ // one signature might correspond to several types.
+ // So if matchType is a Class or MethodType, refilter the results.
+ if (matchType != null && matchType != matchSig) {
+ for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
+ MemberName m = it.next();
+ if (!matchType.equals(m.getType()))
+ it.remove();
+ }
+ }
+ return result;
+ }
+ boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
+ if (m.name == null || m.type == null) { // find unique non-overloaded name
+ Class<?> defc = m.getDeclaringClass();
+ List<MemberName> choices = null;
+ if (m.isMethod())
+ choices = getMethods(defc, searchSupers, m.name, (MethodType) m.type, lookupClass);
+ else if (m.isConstructor())
+ choices = getConstructors(defc, lookupClass);
+ else if (m.isField())
+ choices = getFields(defc, searchSupers, m.name, (Class<?>) m.type, lookupClass);
+ //System.out.println("resolving "+m+" to "+choices);
+ if (choices == null || choices.size() != 1)
+ return false;
+ if (m.name == null) m.name = choices.get(0).name;
+ if (m.type == null) m.type = choices.get(0).type;
+ }
+ MethodHandleNatives.resolve(m, lookupClass);
+ if (m.isResolved()) return true;
+ int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
+ String matchSig = m.getSignature();
+ MemberName[] buf = { m };
+ int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
+ m.getName(), matchSig, matchFlags, lookupClass, 0, buf);
+ if (n != 1) return false;
+ return m.isResolved();
+ }
+ /** Produce a resolved version of the given member.
+ * Super types are searched (for inherited members) if {@code searchSupers} is true.
+ * Access checking is performed on behalf of the given {@code lookupClass}.
+ * If lookup fails or access is not permitted, null is returned.
+ * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
+ */
+ public MemberName resolveOrNull(MemberName m, boolean searchSupers, Class<?> lookupClass) {
+ MemberName result = m.clone();
+ if (resolveInPlace(result, searchSupers, lookupClass))
+ return result;
+ return null;
+ }
+ /** Produce a resolved version of the given member.
+ * Super types are searched (for inherited members) if {@code searchSupers} is true.
+ * Access checking is performed on behalf of the given {@code lookupClass}.
+ * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
+ * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
+ */
+ public
+ <NoSuchMemberException extends ReflectiveOperationException>
+ MemberName resolveOrFail(MemberName m, boolean searchSupers, Class<?> lookupClass,
+ Class<NoSuchMemberException> nsmClass)
+ throws IllegalAccessException, NoSuchMemberException {
+ MemberName result = resolveOrNull(m, searchSupers, lookupClass);
+ if (result != null)
+ return result;
+ ReflectiveOperationException ex = m.makeAccessException("no access");
+ if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex;
+ throw nsmClass.cast(ex);
+ }
+ /** Return a list of all methods defined by the given class.
+ * Super types are searched (for inherited members) if {@code searchSupers} is true.
+ * Access checking is performed on behalf of the given {@code lookupClass}.
+ * Inaccessible members are not added to the last.
+ */
+ public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
+ Class<?> lookupClass) {
+ return getMethods(defc, searchSupers, null, null, lookupClass);
+ }
+ /** Return a list of matching methods defined by the given class.
+ * Super types are searched (for inherited members) if {@code searchSupers} is true.
+ * Returned methods will match the name (if not null) and the type (if not null).
+ * Access checking is performed on behalf of the given {@code lookupClass}.
+ * Inaccessible members are not added to the last.
+ */
+ public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
+ String name, MethodType type, Class<?> lookupClass) {
+ int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
+ return getMembers(defc, name, type, matchFlags, lookupClass);
+ }
+ /** Return a list of all constructors defined by the given class.
+ * Access checking is performed on behalf of the given {@code lookupClass}.
+ * Inaccessible members are not added to the last.
+ */
+ public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
+ return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
+ }
+ /** Return a list of all fields defined by the given class.
+ * Super types are searched (for inherited members) if {@code searchSupers} is true.
+ * Access checking is performed on behalf of the given {@code lookupClass}.
+ * Inaccessible members are not added to the last.
+ */
+ public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
+ Class<?> lookupClass) {
+ return getFields(defc, searchSupers, null, null, lookupClass);
+ }
+ /** Return a list of all fields defined by the given class.
+ * Super types are searched (for inherited members) if {@code searchSupers} is true.
+ * Returned fields will match the name (if not null) and the type (if not null).
+ * Access checking is performed on behalf of the given {@code lookupClass}.
+ * Inaccessible members are not added to the last.
+ */
+ public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
+ String name, Class<?> type, Class<?> lookupClass) {
+ int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
+ return getMembers(defc, name, type, matchFlags, lookupClass);
+ }
+ /** Return a list of all nested types defined by the given class.
+ * Super types are searched (for inherited members) if {@code searchSupers} is true.
+ * Access checking is performed on behalf of the given {@code lookupClass}.
+ * Inaccessible members are not added to the last.
+ */
+ public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
+ Class<?> lookupClass) {
+ int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
+ return getMembers(defc, null, null, matchFlags, lookupClass);
+ }
+ private static MemberName[] newMemberBuffer(int length) {
+ MemberName[] buf = new MemberName[length];
+ // fill the buffer with dummy structs for the JVM to fill in
+ for (int i = 0; i < length; i++)
+ buf[i] = new MemberName();
+ return buf;
+ }
+ }
+
+// static {
+// System.out.println("Hello world! My methods are:");
+// System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
+// }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,1028 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * A method handle is a typed, directly executable reference to an underlying method,
+ * constructor, field, or similar low-level operation, with optional
+ * transformations of arguments or return values.
+ * These transformations are quite general, and include such patterns as
+ * {@linkplain #asType conversion},
+ * {@linkplain #bindTo insertion},
+ * {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion},
+ * and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
+ *
+ * <h3>Method handle contents</h3>
+ * Method handles are dynamically and strongly typed according to type descriptor.
+ * They are not distinguished by the name or defining class of their underlying methods.
+ * A method handle must be invoked using type descriptor which matches
+ * the method handle's own {@linkplain #type method type}.
+ * <p>
+ * Every method handle reports its type via the {@link #type type} accessor.
+ * This type descriptor is a {@link java.lang.invoke.MethodType MethodType} object,
+ * whose structure is a series of classes, one of which is
+ * the return type of the method (or {@code void.class} if none).
+ * <p>
+ * A method handle's type controls the types of invocations it accepts,
+ * and the kinds of transformations that apply to it.
+ * <p>
+ * A method handle contains a pair of special invoker methods
+ * called {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}.
+ * Both invoker methods provide direct access to the method handle's
+ * underlying method, constructor, field, or other operation,
+ * as modified by transformations of arguments and return values.
+ * Both invokers accept calls which exactly match the method handle's own type.
+ * The {@code invokeGeneric} invoker also accepts a range of other call types.
+ * <p>
+ * Method handles are immutable and have no visible state.
+ * Of course, they can be bound to underlying methods or data which exhibit state.
+ * With respect to the Java Memory Model, any method handle will behave
+ * as if all of its (internal) fields are final variables. This means that any method
+ * handle made visible to the application will always be fully formed.
+ * This is true even if the method handle is published through a shared
+ * variable in a data race.
+ * <p>
+ * Method handles cannot be subclassed by the user.
+ * Implementations may (or may not) create internal subclasses of {@code MethodHandle}
+ * which may be visible via the {@link java.lang.Object#getClass Object.getClass}
+ * operation. The programmer should not draw conclusions about a method handle
+ * from its specific class, as the method handle class hierarchy (if any)
+ * may change from time to time or across implementations from different vendors.
+ *
+ * <h3>Method handle compilation</h3>
+ * A Java method call expression naming {@code invokeExact} or {@code invokeGeneric}
+ * can invoke a method handle from Java source code.
+ * From the viewpoint of source code, these methods can take any arguments
+ * and their result can be cast to any return type.
+ * Formally this is accomplished by giving the invoker methods
+ * {@code Object} return types and variable-arity {@code Object} arguments,
+ * but they have an additional quality called <em>signature polymorphism</em>
+ * which connects this freedom of invocation directly to the JVM execution stack.
+ * <p>
+ * As is usual with virtual methods, source-level calls to {@code invokeExact}
+ * and {@code invokeGeneric} compile to an {@code invokevirtual} instruction.
+ * More unusually, the compiler must record the actual argument types,
+ * and may not perform method invocation conversions on the arguments.
+ * Instead, it must push them on the stack according to their own unconverted types.
+ * The method handle object itself is pushed on the stack before the arguments.
+ * The compiler then calls the method handle with a type descriptor which
+ * describes the argument and return types.
+ * <p>
+ * To issue a complete type descriptor, the compiler must also determine
+ * the return type. This is based on a cast on the method invocation expression,
+ * if there is one, or else {@code Object} if the invocation is an expression
+ * or else {@code void} if the invocation is a statement.
+ * The cast may be to a primitive type (but not {@code void}).
+ * <p>
+ * As a corner case, an uncasted {@code null} argument is given
+ * a type descriptor of {@code java.lang.Void}.
+ * The ambiguity with the type {@code Void} is harmless, since there are no references of type
+ * {@code Void} except the null reference.
+ *
+ * <h3>Method handle invocation</h3>
+ * The first time a {@code invokevirtual} instruction is executed
+ * it is linked, by symbolically resolving the names in the instruction
+ * and verifying that the method call is statically legal.
+ * This is true of calls to {@code invokeExact} and {@code invokeGeneric}.
+ * In this case, the type descriptor emitted by the compiler is checked for
+ * correct syntax and names it contains are resolved.
+ * Thus, an {@code invokevirtual} instruction which invokes
+ * a method handle will always link, as long
+ * as the type descriptor is syntactically well-formed
+ * and the types exist.
+ * <p>
+ * When the {@code invokevirtual} is executed after linking,
+ * the receiving method handle's type is first checked by the JVM
+ * to ensure that it matches the descriptor.
+ * If the type match fails, it means that the method which the
+ * caller is invoking is not present on the individual
+ * method handle being invoked.
+ * <p>
+ * In the case of {@code invokeExact}, the type descriptor of the invocation
+ * (after resolving symbolic type names) must exactly match the method type
+ * of the receiving method handle.
+ * In the case of {@code invokeGeneric}, the resolved type descriptor
+ * must be a valid argument to the receiver's {@link #asType asType} method.
+ * Thus, {@code invokeGeneric} is more permissive than {@code invokeExact}.
+ * <p>
+ * After type matching, a call to {@code invokeExact} directly
+ * and immediately invoke the method handle's underlying method
+ * (or other behavior, as the case may be).
+ * <p>
+ * A call to {@code invokeGeneric} works the same as a call to
+ * {@code invokeExact}, if the type descriptor specified by the caller
+ * exactly matches the method handle's own type.
+ * If there is a type mismatch, {@code invokeGeneric} attempts
+ * to adjust the type of the receiving method handle,
+ * as if by a call to {@link #asType asType},
+ * to obtain an exactly invokable method handle {@code M2}.
+ * This allows a more powerful negotiation of method type
+ * between caller and callee.
+ * <p>
+ * (<em>Note:</em> The adjusted method handle {@code M2} is not directly observable,
+ * and implementations are therefore not required to materialize it.)
+ *
+ * <h3>Invocation checking</h3>
+ * In typical programs, method handle type matching will usually succeed.
+ * But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
+ * either directly (in the case of {@code invokeExact}) or indirectly as if
+ * by a failed call to {@code asType} (in the case of {@code invokeGeneric}).
+ * <p>
+ * Thus, a method type mismatch which might show up as a linkage error
+ * in a statically typed program can show up as
+ * a dynamic {@code WrongMethodTypeException}
+ * in a program which uses method handles.
+ * <p>
+ * Because method types contain "live" {@code Class} objects,
+ * method type matching takes into account both types names and class loaders.
+ * Thus, even if a method handle {@code M} is created in one
+ * class loader {@code L1} and used in another {@code L2},
+ * method handle calls are type-safe, because the caller's type
+ * descriptor, as resolved in {@code L2},
+ * is matched against the original callee method's type descriptor,
+ * as resolved in {@code L1}.
+ * The resolution in {@code L1} happens when {@code M} is created
+ * and its type is assigned, while the resolution in {@code L2} happens
+ * when the {@code invokevirtual} instruction is linked.
+ * <p>
+ * Apart from the checking of type descriptors,
+ * a method handle's capability to call its underlying method is unrestricted.
+ * If a method handle is formed on a non-public method by a class
+ * that has access to that method, the resulting handle can be used
+ * in any place by any caller who receives a reference to it.
+ * <p>
+ * Unlike with the Core Reflection API, where access is checked every time
+ * a reflective method is invoked,
+ * method handle access checking is performed
+ * <a href="MethodHandles.Lookup.html#access">when the method handle is created</a>.
+ * In the case of {@code ldc} (see below), access checking is performed as part of linking
+ * the constant pool entry underlying the constant method handle.
+ * <p>
+ * Thus, handles to non-public methods, or to methods in non-public classes,
+ * should generally be kept secret.
+ * They should not be passed to untrusted code unless their use from
+ * the untrusted code would be harmless.
+ *
+ * <h3>Method handle creation</h3>
+ * Java code can create a method handle that directly accesses
+ * any method, constructor, or field that is accessible to that code.
+ * This is done via a reflective, capability-based API called
+ * {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}
+ * For example, a static method handle can be obtained
+ * from {@link java.lang.invoke.MethodHandles.Lookup#findStatic Lookup.findStatic}.
+ * There are also conversion methods from Core Reflection API objects,
+ * such as {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
+ * <p>
+ * Like classes and strings, method handles that correspond to accessible
+ * fields, methods, and constructors can also be represented directly
+ * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
+ * A new type of constant pool entry, {@code CONSTANT_MethodHandle},
+ * refers directly to an associated {@code CONSTANT_Methodref},
+ * {@code CONSTANT_InterfaceMethodref}, or {@code CONSTANT_Fieldref}
+ * constant pool entry.
+ * (For more details on method handle constants,
+ * see the <a href="package-summary.html#mhcon">package summary</a>.)
+ * <p>
+ * Method handles produced by lookups or constant loads from methods or
+ * constructors with the variable arity modifier bit ({@code 0x0080})
+ * have a corresponding variable arity, as if they were defined with
+ * the help of {@link #asVarargsCollector asVarargsCollector}.
+ * <p>
+ * A method reference may refer either to a static or non-static method.
+ * In the non-static case, the method handle type includes an explicit
+ * receiver argument, prepended before any other arguments.
+ * In the method handle's type, the initial receiver argument is typed
+ * according to the class under which the method was initially requested.
+ * (E.g., if a non-static method handle is obtained via {@code ldc},
+ * the type of the receiver is the class named in the constant pool entry.)
+ * <p>
+ * When a method handle to a virtual method is invoked, the method is
+ * always looked up in the receiver (that is, the first argument).
+ * <p>
+ * A non-virtual method handle to a specific virtual method implementation
+ * can also be created. These do not perform virtual lookup based on
+ * receiver type. Such a method handle simulates the effect of
+ * an {@code invokespecial} instruction to the same method.
+ *
+ * <h3>Usage examples</h3>
+ * Here are some examples of usage:
+ * <p><blockquote><pre>
+Object x, y; String s; int i;
+MethodType mt; MethodHandle mh;
+MethodHandles.Lookup lookup = MethodHandles.lookup();
+// mt is (char,char)String
+mt = MethodType.methodType(String.class, char.class, char.class);
+mh = lookup.findVirtual(String.class, "replace", mt);
+s = (String) mh.invokeExact("daddy",'d','n');
+// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
+assert(s.equals("nanny"));
+// weakly typed invocation (using MHs.invoke)
+s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
+assert(s.equals("savvy"));
+// mt is (Object[])List
+mt = MethodType.methodType(java.util.List.class, Object[].class);
+mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
+assert(mh.isVarargsCollector());
+x = mh.invokeGeneric("one", "two");
+// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
+assert(x.equals(java.util.Arrays.asList("one","two")));
+// mt is (Object,Object,Object)Object
+mt = MethodType.genericMethodType(3);
+mh = mh.asType(mt);
+x = mh.invokeExact((Object)1, (Object)2, (Object)3);
+// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+assert(x.equals(java.util.Arrays.asList(1,2,3)));
+// mt is int()
+mt = MethodType.methodType(int.class);
+mh = lookup.findVirtual(java.util.List.class, "size", mt);
+i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
+// invokeExact(Ljava/util/List;)I
+assert(i == 3);
+mt = MethodType.methodType(void.class, String.class);
+mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
+mh.invokeExact(System.out, "Hello, world.");
+// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
+ * </pre></blockquote>
+ * Each of the above calls to {@code invokeExact} or {@code invokeGeneric}
+ * generates a single invokevirtual instruction with
+ * the type descriptor indicated in the following comment.
+ *
+ * <h3>Exceptions</h3>
+ * The methods {@code invokeExact} and {@code invokeGeneric} are declared
+ * to throw {@link java.lang.Throwable Throwable},
+ * which is to say that there is no static restriction on what a method handle
+ * can throw. Since the JVM does not distinguish between checked
+ * and unchecked exceptions (other than by their class, of course),
+ * there is no particular effect on bytecode shape from ascribing
+ * checked exceptions to method handle invocations. But in Java source
+ * code, methods which perform method handle calls must either explicitly
+ * throw {@code java.lang.Throwable Throwable}, or else must catch all
+ * throwables locally, rethrowing only those which are legal in the context,
+ * and wrapping ones which are illegal.
+ *
+ * <h3><a name="sigpoly"></a>Signature polymorphism</h3>
+ * The unusual compilation and linkage behavior of
+ * {@code invokeExact} and {@code invokeGeneric}
+ * is referenced by the term <em>signature polymorphism</em>.
+ * A signature polymorphic method is one which can operate with
+ * any of a wide range of call signatures and return types.
+ * In order to make this work, both the Java compiler and the JVM must
+ * give special treatment to signature polymorphic methods.
+ * <p>
+ * In source code, a call to a signature polymorphic method will
+ * compile, regardless of the requested type descriptor.
+ * As usual, the Java compiler emits an {@code invokevirtual}
+ * instruction with the given type descriptor against the named method.
+ * The unusual part is that the type descriptor is derived from
+ * the actual argument and return types, not from the method declaration.
+ * <p>
+ * When the JVM processes bytecode containing signature polymorphic calls,
+ * it will successfully link any such call, regardless of its type descriptor.
+ * (In order to retain type safety, the JVM will guard such calls with suitable
+ * dynamic type checks, as described elsewhere.)
+ * <p>
+ * Bytecode generators, including the compiler back end, are required to emit
+ * untransformed type descriptors for these methods.
+ * Tools which determine symbolic linkage are required to accept such
+ * untransformed descriptors, without reporting linkage errors.
+ * <p>
+ * For the sake of tools (but not as a programming API), the signature polymorphic
+ * methods are marked with a private yet standard annotation,
+ * {@code @java.lang.invoke.MethodHandle.PolymorphicSignature}.
+ * The annotation's retention is {@code RUNTIME}, so that all tools can see it.
+ *
+ * <h3>Formal rules for processing signature polymorphic methods</h3>
+ * <p>
+ * The following methods (and no others) are signature polymorphic:
+ * <ul>
+ * <li>{@link java.lang.invoke.MethodHandle#invokeExact MethodHandle.invokeExact}
+ * <li>{@link java.lang.invoke.MethodHandle#invokeGeneric MethodHandle.invokeGeneric}
+ * </ul>
+ * <p>
+ * A signature polymorphic method will be declared with the following properties:
+ * <ul>
+ * <li>It must be native.
+ * <li>It must take a single varargs parameter of the form {@code Object...}.
+ * <li>It must produce a return value of type {@code Object}.
+ * <li>It must be contained within the {@code java.lang.invoke} package.
+ * </ul>
+ * Because of these requirements, a signature polymorphic method is able to accept
+ * any number and type of actual arguments, and can, with a cast, produce a value of any type.
+ * However, the JVM will treat these declaration features as a documentation convention,
+ * rather than a description of the actual structure of the methods as executed.
+ * <p>
+ * When a call to a signature polymorphic method is compiled, the associated linkage information for
+ * its arguments is not array of {@code Object} (as for other similar varargs methods)
+ * but rather the erasure of the static types of all the arguments.
+ * <p>
+ * In an argument position of a method invocation on a signature polymorphic method,
+ * a null literal has type {@code java.lang.Void}, unless cast to a reference type.
+ * (<em>Note:</em> This typing rule allows the null type to have its own encoding in linkage information
+ * distinct from other types.
+ * <p>
+ * The linkage information for the return type is derived from a context-dependent target typing convention.
+ * The return type for a signature polymorphic method invocation is determined as follows:
+ * <ul>
+ * <li>If the method invocation expression is an expression statement, the method is {@code void}.
+ * <li>Otherwise, if the method invocation expression is the immediate operand of a cast,
+ * the return type is the erasure of the cast type.
+ * <li>Otherwise, the return type is the method's nominal return type, {@code Object}.
+ * </ul>
+ * (Programmers are encouraged to use explicit casts unless it is clear that a signature polymorphic
+ * call will be used as a plain {@code Object} expression.)
+ * <p>
+ * The linkage information for argument and return types is stored in the descriptor for the
+ * compiled (bytecode) call site. As for any invocation instruction, the arguments and return value
+ * will be passed directly on the JVM stack, in accordance with the descriptor,
+ * and without implicit boxing or unboxing.
+ *
+ * <h3>Interoperation between method handles and the Core Reflection API</h3>
+ * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API,
+ * any class member represented by a Core Reflection API object
+ * can be converted to a behaviorally equivalent method handle.
+ * For example, a reflective {@link java.lang.reflect.Method Method} can
+ * be converted to a method handle using
+ * {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
+ * The resulting method handles generally provide more direct and efficient
+ * access to the underlying class members.
+ * <p>
+ * As a special case,
+ * when the Core Reflection API is used to view the signature polymorphic
+ * methods {@code invokeExact} or {@code invokeGeneric} in this class,
+ * they appear as single, non-polymorphic native methods.
+ * Calls to these native methods do not result in method handle invocations.
+ * Since {@code invokevirtual} instructions can natively
+ * invoke method handles under any type descriptor, this reflective view conflicts
+ * with the normal presentation via bytecodes.
+ * Thus, these two native methods, as viewed by
+ * {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod},
+ * are placeholders only.
+ * If invoked via {@link java.lang.reflect.Method#invoke Method.invoke},
+ * they will throw {@code UnsupportedOperationException}.
+ * <p>
+ * In order to obtain an invoker method for a particular type descriptor,
+ * use {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker},
+ * or {@link java.lang.invoke.MethodHandles#genericInvoker MethodHandles.genericInvoker}.
+ * The {@link java.lang.invoke.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
+ * API is also able to return a method handle
+ * to call {@code invokeExact} or {@code invokeGeneric},
+ * for any specified type descriptor .
+ *
+ * <h3>Interoperation between method handles and Java generics</h3>
+ * A method handle can be obtained on a method, constructor, or field
+ * which is declared with Java generic types.
+ * As with the Core Reflection API, the type of the method handle
+ * will constructed from the erasure of the source-level type.
+ * When a method handle is invoked, the types of its arguments
+ * or the return value cast type may be generic types or type instances.
+ * If this occurs, the compiler will replace those
+ * types by their erasures when when it constructs the type descriptor
+ * for the {@code invokevirtual} instruction.
+ * <p>
+ * Method handles do not represent
+ * their function-like types in terms of Java parameterized (generic) types,
+ * because there are three mismatches between function-like types and parameterized
+ * Java types.
+ * <ul>
+ * <li>Method types range over all possible arities,
+ * from no arguments to up to 255 of arguments (a limit imposed by the JVM).
+ * Generics are not variadic, and so cannot represent this.</li>
+ * <li>Method types can specify arguments of primitive types,
+ * which Java generic types cannot range over.</li>
+ * <li>Higher order functions over method handles (combinators) are
+ * often generic across a wide range of function types, including
+ * those of multiple arities. It is impossible to represent such
+ * genericity with a Java type parameter.</li>
+ * </ul>
+ *
+ * @see MethodType
+ * @see MethodHandles
+ * @author John Rose, JSR 292 EG
+ */
+public abstract class MethodHandle {
+ // { JVM internals:
+
+ private byte vmentry; // adapter stub or method entry point
+ //private int vmslots; // optionally, hoist type.form.vmslots
+ /*non-public*/ Object vmtarget; // VM-specific, class-specific target value
+
+ // TO DO: vmtarget should be invisible to Java, since the JVM puts internal
+ // managed pointers into it. Making it visible exposes it to debuggers,
+ // which can cause errors when they treat the pointer as an Object.
+
+ // These two dummy fields are present to force 'I' and 'J' signatures
+ // into this class's constant pool, so they can be transferred
+ // to vmentry when this class is loaded.
+ static final int INT_FIELD = 0;
+ static final long LONG_FIELD = 0;
+
+ // vmentry (a void* field) is used *only* by the JVM.
+ // The JVM adjusts its type to int or long depending on system wordsize.
+ // Since it is statically typed as neither int nor long, it is impossible
+ // to use this field from Java bytecode. (Please don't try to, either.)
+
+ // The vmentry is an assembly-language stub which is jumped to
+ // immediately after the method type is verified.
+ // For a direct MH, this stub loads the vmtarget's entry point
+ // and jumps to it.
+
+ // } End of JVM internals.
+
+ static { MethodHandleImpl.initStatics(); }
+
+ // interface MethodHandle<R throws X extends Exception,A...>
+ // { MethodType<R throws X,A...> type(); public R invokeExact(A...) throws X; }
+
+ /**
+ * Internal marker interface which distinguishes (to the Java compiler)
+ * those methods which are <a href="MethodHandle.html#sigpoly">signature polymorphic</a>.
+ */
+ @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
+ @interface PolymorphicSignature { }
+
+ private MethodType type;
+
+ /**
+ * Reports the type of this method handle.
+ * Every invocation of this method handle via {@code invokeExact} must exactly match this type.
+ * @return the method handle type
+ */
+ public MethodType type() {
+ return type;
+ }
+
+ /**
+ * Package-private constructor for the method handle implementation hierarchy.
+ * Method handle inheritance will be contained completely within
+ * the {@code java.lang.invoke} package.
+ */
+ // @param type type (permanently assigned) of the new method handle
+ /*non-public*/ MethodHandle(MethodType type) {
+ type.getClass(); // elicit NPE
+ this.type = type;
+ }
+
+ /**
+ * Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match.
+ * The type descriptor at the call site of {@code invokeExact} must
+ * exactly match this method handle's {@link #type type}.
+ * No conversions are allowed on arguments or return values.
+ * <p>
+ * When this method is observed via the Core Reflection API,
+ * it will appear as a single native method, taking an object array and returning an object.
+ * If this native method is invoked directly via
+ * {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
+ * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
+ * it will throw an {@code UnsupportedOperationException}.
+ * @throws WrongMethodTypeException if the target's type is not identical with the caller's type descriptor
+ * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
+ */
+ public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
+
+ /**
+ * Invokes the method handle, allowing any caller type descriptor,
+ * and optionally performing conversions on arguments and return values.
+ * <p>
+ * If the call site type descriptor exactly matches this method handle's {@link #type type},
+ * the call proceeds as if by {@link #invokeExact invokeExact}.
+ * <p>
+ * Otherwise, the call proceeds as if this method handle were first
+ * adjusted by calling {@link #asType asType} to adjust this method handle
+ * to the required type, and then the call proceeds as if by
+ * {@link #invokeExact invokeExact} on the adjusted method handle.
+ * <p>
+ * There is no guarantee that the {@code asType} call is actually made.
+ * If the JVM can predict the results of making the call, it may perform
+ * adaptations directly on the caller's arguments,
+ * and call the target method handle according to its own exact type.
+ * <p>
+ * The type descriptor at the call site of {@code invokeGeneric} must
+ * be a valid argument to the receivers {@code asType} method.
+ * In particular, the caller must specify the same argument arity
+ * as the callee's type,
+ * if the callee is not a {@linkplain #asVarargsCollector variable arity collector}.
+ * <p>
+ * When this method is observed via the Core Reflection API,
+ * it will appear as a single native method, taking an object array and returning an object.
+ * If this native method is invoked directly via
+ * {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
+ * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
+ * it will throw an {@code UnsupportedOperationException}.
+ * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type descriptor
+ * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
+ * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
+ */
+ public final native @PolymorphicSignature Object invokeGeneric(Object... args) throws Throwable;
+
+ /**
+ * Performs a varargs invocation, passing the arguments in the given array
+ * to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
+ * which mentions only the type {@code Object}, and whose arity is the length
+ * of the argument array.
+ * <p>
+ * Specifically, execution proceeds as if by the following steps,
+ * although the methods are not guaranteed to be called if the JVM
+ * can predict their effects.
+ * <ul>
+ * <li>Determine the length of the argument array as {@code N}.
+ * For a null reference, {@code N=0}. </li>
+ * <li>Determine the generic type {@code TN} of {@code N} arguments as
+ * as {@code TN=MethodType.genericMethodType(N)}.</li>
+ * <li>Force the original target method handle {@code MH0} to the
+ * required type, as {@code MH1 = MH0.asType(TN)}. </li>
+ * <li>Spread the array into {@code N} separate arguments {@code A0, ...}. </li>
+ * <li>Invoke the type-adjusted method handle on the unpacked arguments:
+ * MH1.invokeExact(A0, ...). </li>
+ * <li>Take the return value as an {@code Object} reference. </li>
+ * </ul>
+ * <p>
+ * Because of the action of the {@code asType} step, the following argument
+ * conversions are applied as necessary:
+ * <ul>
+ * <li>reference casting
+ * <li>unboxing
+ * <li>widening primitive conversions
+ * </ul>
+ * <p>
+ * The result returned by the call is boxed if it is a primitive,
+ * or forced to null if the return type is void.
+ * <p>
+ * This call is equivalent to the following code:
+ * <p><blockquote><pre>
+ * MethodHandle invoker = MethodHandles.spreadInvoker(this.type(), 0);
+ * Object result = invoker.invokeExact(this, arguments);
+ * </pre></blockquote>
+ * <p>
+ * Unlike the signature polymorphic methods {@code invokeExact} and {@code invokeGeneric},
+ * {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI.
+ * It can therefore be used as a bridge between native or reflective code and method handles.
+ *
+ * @param arguments the arguments to pass to the target
+ * @return the result returned by the target
+ * @throws ClassCastException if an argument cannot be converted by reference casting
+ * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
+ * @throws Throwable anything thrown by the target method invocation
+ * @see MethodHandles#spreadInvoker
+ */
+ public Object invokeWithArguments(Object... arguments) throws Throwable {
+ int argc = arguments == null ? 0 : arguments.length;
+ MethodType type = type();
+ if (type.parameterCount() != argc) {
+ // simulate invokeGeneric
+ return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
+ }
+ if (argc <= 10) {
+ MethodHandle invoker = type.invokers().genericInvoker();
+ switch (argc) {
+ case 0: return invoker.invokeExact(this);
+ case 1: return invoker.invokeExact(this,
+ arguments[0]);
+ case 2: return invoker.invokeExact(this,
+ arguments[0], arguments[1]);
+ case 3: return invoker.invokeExact(this,
+ arguments[0], arguments[1], arguments[2]);
+ case 4: return invoker.invokeExact(this,
+ arguments[0], arguments[1], arguments[2],
+ arguments[3]);
+ case 5: return invoker.invokeExact(this,
+ arguments[0], arguments[1], arguments[2],
+ arguments[3], arguments[4]);
+ case 6: return invoker.invokeExact(this,
+ arguments[0], arguments[1], arguments[2],
+ arguments[3], arguments[4], arguments[5]);
+ case 7: return invoker.invokeExact(this,
+ arguments[0], arguments[1], arguments[2],
+ arguments[3], arguments[4], arguments[5],
+ arguments[6]);
+ case 8: return invoker.invokeExact(this,
+ arguments[0], arguments[1], arguments[2],
+ arguments[3], arguments[4], arguments[5],
+ arguments[6], arguments[7]);
+ case 9: return invoker.invokeExact(this,
+ arguments[0], arguments[1], arguments[2],
+ arguments[3], arguments[4], arguments[5],
+ arguments[6], arguments[7], arguments[8]);
+ case 10: return invoker.invokeExact(this,
+ arguments[0], arguments[1], arguments[2],
+ arguments[3], arguments[4], arguments[5],
+ arguments[6], arguments[7], arguments[8],
+ arguments[9]);
+ }
+ }
+
+ // more than ten arguments get boxed in a varargs list:
+ MethodHandle invoker = type.invokers().spreadInvoker(0);
+ return invoker.invokeExact(this, arguments);
+ }
+
+ /**
+ * Performs a varargs invocation, passing the arguments in the given array
+ * to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
+ * which mentions only the type {@code Object}, and whose arity is the length
+ * of the argument array.
+ * <p>
+ * This method is also equivalent to the following code:
+ * <p><blockquote><pre>
+ * {@link #invokeWithArguments(Object...) invokeWithArguments}(arguments.toArray())
+ * </pre></blockquote>
+ *
+ * @param arguments the arguments to pass to the target
+ * @return the result returned by the target
+ * @throws ClassCastException if an argument cannot be converted by reference casting
+ * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
+ * @throws Throwable anything thrown by the target method invocation
+ */
+ public Object invokeWithArguments(java.util.List<?> arguments) throws Throwable {
+ return invokeWithArguments(arguments.toArray());
+ }
+
+ /**
+ * Produces an adapter method handle which adapts the type of the
+ * current method handle to a new type.
+ * The resulting method handle is guaranteed to report a type
+ * which is equal to the desired new type.
+ * <p>
+ * If the original type and new type are equal, returns {@code this}.
+ * <p>
+ * This method provides the crucial behavioral difference between
+ * {@link #invokeExact invokeExact} and {@link #invokeGeneric invokeGeneric}. The two methods
+ * perform the same steps when the caller's type descriptor is identical
+ * with the callee's, but when the types differ, {@link #invokeGeneric invokeGeneric}
+ * also calls {@code asType} (or some internal equivalent) in order
+ * to match up the caller's and callee's types.
+ * <p>
+ * This method is equivalent to {@link MethodHandles#convertArguments convertArguments},
+ * except for variable arity method handles produced by {@link #asVarargsCollector asVarargsCollector}.
+ *
+ * @param newType the expected type of the new method handle
+ * @return a method handle which delegates to {@code this} after performing
+ * any necessary argument conversions, and arranges for any
+ * necessary return value conversions
+ * @throws WrongMethodTypeException if the conversion cannot be made
+ * @see MethodHandles#convertArguments
+ */
+ public MethodHandle asType(MethodType newType) {
+ return MethodHandles.convertArguments(this, newType);
+ }
+
+ /**
+ * Makes an adapter which accepts a trailing array argument
+ * and spreads its elements as positional arguments.
+ * The new method handle adapts, as its <i>target</i>,
+ * the current method handle. The type of the adapter will be
+ * the same as the type of the target, except that the final
+ * {@code arrayLength} parameters of the target's type are replaced
+ * by a single array parameter of type {@code arrayType}.
+ * <p>
+ * If the array element type differs from any of the corresponding
+ * argument types on the original target,
+ * the original target is adapted to take the array elements directly,
+ * as if by a call to {@link #asType asType}.
+ * <p>
+ * When called, the adapter replaces a trailing array argument
+ * by the array's elements, each as its own argument to the target.
+ * (The order of the arguments is preserved.)
+ * They are converted pairwise by casting and/or unboxing
+ * to the types of the trailing parameters of the target.
+ * Finally the target is called.
+ * What the target eventually returns is returned unchanged by the adapter.
+ * <p>
+ * Before calling the target, the adapter verifies that the array
+ * contains exactly enough elements to provide a correct argument count
+ * to the target method handle.
+ * (The array may also be null when zero elements are required.)
+ * @param arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments
+ * @param arrayLength the number of arguments to spread from an incoming array argument
+ * @return a new method handle which spreads its final array argument,
+ * before calling the original method handle
+ * @throws IllegalArgumentException if {@code arrayType} is not an array type
+ * @throws IllegalArgumentException if target does not have at least
+ * {@code arrayLength} parameter types
+ * @throws WrongMethodTypeException if the implied {@code asType} call fails
+ * @see #asCollector
+ */
+ public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
+ Class<?> arrayElement = arrayType.getComponentType();
+ if (arrayElement == null) throw newIllegalArgumentException("not an array type");
+ MethodType oldType = type();
+ int nargs = oldType.parameterCount();
+ if (nargs < arrayLength) throw newIllegalArgumentException("bad spread array length");
+ int keepPosArgs = nargs - arrayLength;
+ MethodType newType = oldType.dropParameterTypes(keepPosArgs, nargs);
+ newType = newType.insertParameterTypes(keepPosArgs, arrayType);
+ return MethodHandles.spreadArguments(this, newType);
+ }
+
+ /**
+ * Makes an adapter which accepts a given number of trailing
+ * positional arguments and collects them into an array argument.
+ * The new method handle adapts, as its <i>target</i>,
+ * the current method handle. The type of the adapter will be
+ * the same as the type of the target, except that a single trailing
+ * parameter (usually of type {@code arrayType}) is replaced by
+ * {@code arrayLength} parameters whose type is element type of {@code arrayType}.
+ * <p>
+ * If the array type differs from the final argument type on the original target,
+ * the original target is adapted to take the array type directly,
+ * as if by a call to {@link #asType asType}.
+ * <p>
+ * When called, the adapter replaces its trailing {@code arrayLength}
+ * arguments by a single new array of type {@code arrayType}, whose elements
+ * comprise (in order) the replaced arguments.
+ * Finally the target is called.
+ * What the target eventually returns is returned unchanged by the adapter.
+ * <p>
+ * (The array may also be a shared constant when {@code arrayLength} is zero.)
+ * <p>
+ * (<em>Note:</em> The {@code arrayType} is often identical to the last
+ * parameter type of the original target.
+ * It is an explicit argument for symmetry with {@code asSpreader}, and also
+ * to allow the target to use a simple {@code Object} as its last parameter type.)
+ * <p>
+ * In order to create a collecting adapter which is not restricted to a particular
+ * number of collected arguments, use {@link #asVarargsCollector asVarargsCollector} instead.
+ * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
+ * @param arrayLength the number of arguments to collect into a new array argument
+ * @return a new method handle which collects some trailing argument
+ * into an array, before calling the original method handle
+ * @throws IllegalArgumentException if {@code arrayType} is not an array type
+ * or {@code arrayType} is not assignable to this method handle's trailing parameter type,
+ * or {@code arrayLength} is not a legal array size
+ * @throws WrongMethodTypeException if the implied {@code asType} call fails
+ * @see #asSpreader
+ * @see #asVarargsCollector
+ */
+ public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
+ Class<?> arrayElement = arrayType.getComponentType();
+ if (arrayElement == null) throw newIllegalArgumentException("not an array type");
+ MethodType oldType = type();
+ int nargs = oldType.parameterCount();
+ if (nargs == 0) throw newIllegalArgumentException("no trailing argument");
+ MethodType newType = oldType.dropParameterTypes(nargs-1, nargs);
+ newType = newType.insertParameterTypes(nargs-1,
+ java.util.Collections.<Class<?>>nCopies(arrayLength, arrayElement));
+ return MethodHandles.collectArguments(this, newType);
+ }
+
+ /**
+ * Makes a <em>variable arity</em> adapter which is able to accept
+ * any number of trailing positional arguments and collect them
+ * into an array argument.
+ * <p>
+ * The type and behavior of the adapter will be the same as
+ * the type and behavior of the target, except that certain
+ * {@code invokeGeneric} and {@code asType} requests can lead to
+ * trailing positional arguments being collected into target's
+ * trailing parameter.
+ * Also, the last parameter type of the adapter will be
+ * {@code arrayType}, even if the target has a different
+ * last parameter type.
+ * <p>
+ * When called with {@link #invokeExact invokeExact}, the adapter invokes
+ * the target with no argument changes.
+ * (<em>Note:</em> This behavior is different from a
+ * {@linkplain #asCollector fixed arity collector},
+ * since it accepts a whole array of indeterminate length,
+ * rather than a fixed number of arguments.)
+ * <p>
+ * When called with {@link #invokeGeneric invokeGeneric}, if the caller
+ * type is the same as the adapter, the adapter invokes the target as with
+ * {@code invokeExact}.
+ * (This is the normal behavior for {@code invokeGeneric} when types match.)
+ * <p>
+ * Otherwise, if the caller and adapter arity are the same, and the
+ * trailing parameter type of the caller is a reference type identical to
+ * or assignable to the trailing parameter type of the adapter,
+ * the arguments and return values are converted pairwise,
+ * as if by {@link MethodHandles#convertArguments convertArguments}.
+ * (This is also normal behavior for {@code invokeGeneric} in such a case.)
+ * <p>
+ * Otherwise, the arities differ, or the adapter's trailing parameter
+ * type is not assignable from the corresponding caller type.
+ * In this case, the adapter replaces all trailing arguments from
+ * the original trailing argument position onward, by
+ * a new array of type {@code arrayType}, whose elements
+ * comprise (in order) the replaced arguments.
+ * <p>
+ * The caller type must provides as least enough arguments,
+ * and of the correct type, to satisfy the target's requirement for
+ * positional arguments before the trailing array argument.
+ * Thus, the caller must supply, at a minimum, {@code N-1} arguments,
+ * where {@code N} is the arity of the target.
+ * Also, there must exist conversions from the incoming arguments
+ * to the target's arguments.
+ * As with other uses of {@code invokeGeneric}, if these basic
+ * requirements are not fulfilled, a {@code WrongMethodTypeException}
+ * may be thrown.
+ * <p>
+ * In all cases, what the target eventually returns is returned unchanged by the adapter.
+ * <p>
+ * In the final case, it is exactly as if the target method handle were
+ * temporarily adapted with a {@linkplain #asCollector fixed arity collector}
+ * to the arity required by the caller type.
+ * (As with {@code asCollector}, if the array length is zero,
+ * a shared constant may be used instead of a new array.
+ * If the implied call to {@code asCollector} would throw
+ * an {@code IllegalArgumentException} or {@code WrongMethodTypeException},
+ * the call to the variable arity adapter must throw
+ * {@code WrongMethodTypeException}.)
+ * <p>
+ * The behavior of {@link #asType asType} is also specialized for
+ * variable arity adapters, to maintain the invariant that
+ * {@code invokeGeneric} is always equivalent to an {@code asType}
+ * call to adjust the target type, followed by {@code invokeExact}.
+ * Therefore, a variable arity adapter responds
+ * to an {@code asType} request by building a fixed arity collector,
+ * if and only if the adapter and requested type differ either
+ * in arity or trailing argument type.
+ * The resulting fixed arity collector has its type further adjusted
+ * (if necessary) to the requested type by pairwise conversion,
+ * as if by another application of {@code asType}.
+ * <p>
+ * When a method handle is obtained by executing an {@code ldc} instruction
+ * of a {@code CONSTANT_MethodHandle} constant, and the target method is marked
+ * as a variable arity method (with the modifier bit {@code 0x0080}),
+ * the method handle will accept multiple arities, as if the method handle
+ * constant were created by means of a call to {@code asVarargsCollector}.
+ * <p>
+ * In order to create a collecting adapter which collects a predetermined
+ * number of arguments, and whose type reflects this predetermined number,
+ * use {@link #asCollector asCollector} instead.
+ * <p>
+ * No method handle transformations produce new method handles with
+ * variable arity, unless they are documented as doing so.
+ * Therefore, besides {@code asVarargsCollector},
+ * all methods in {@code MethodHandle} and {@code MethodHandles}
+ * will return a method handle with fixed arity,
+ * except in the cases where they are specified to return their original
+ * operand (e.g., {@code asType} of the method handle's own type).
+ * <p>
+ * Calling {@code asVarargsCollector} on a method handle which is already
+ * of variable arity will produce a method handle with the same type and behavior.
+ * It may (or may not) return the original variable arity method handle.
+ * <p>
+ * Here is an example, of a list-making variable arity method handle:
+ * <blockquote><pre>
+MethodHandle asList = publicLookup()
+ .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
+ .asVarargsCollector(Object[].class);
+assertEquals("[]", asList.invokeGeneric().toString());
+assertEquals("[1]", asList.invokeGeneric(1).toString());
+assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString());
+Object[] argv = { "three", "thee", "tee" };
+assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString());
+List ls = (List) asList.invokeGeneric((Object)argv);
+assertEquals(1, ls.size());
+assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
+ * </pre></blockquote>
+ * <p style="font-size:smaller;">
+ * <em>Discussion:</em>
+ * These rules are designed as a dynamically-typed variation
+ * of the Java rules for variable arity methods.
+ * In both cases, callers to a variable arity method or method handle
+ * can either pass zero or more positional arguments, or else pass
+ * pre-collected arrays of any length. Users should be aware of the
+ * special role of the final argument, and of the effect of a
+ * type match on that final argument, which determines whether
+ * or not a single trailing argument is interpreted as a whole
+ * array or a single element of an array to be collected.
+ * Note that the dynamic type of the trailing argument has no
+ * effect on this decision, only a comparison between the static
+ * type descriptor of the call site and the type of the method handle.)
+ * <p style="font-size:smaller;">
+ * As a result of the previously stated rules, the variable arity behavior
+ * of a method handle may be suppressed, by binding it to the exact invoker
+ * of its own type, as follows:
+ * <blockquote><pre>
+MethodHandle vamh = publicLookup()
+ .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
+ .asVarargsCollector(Object[].class);
+MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
+assert(vamh.type().equals(mh.type()));
+assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString());
+boolean failed = false;
+try { mh.invokeGeneric(1,2,3); }
+catch (WrongMethodTypeException ex) { failed = true; }
+assert(failed);
+ * </pre></blockquote>
+ * This transformation has no behavioral effect if the method handle is
+ * not of variable arity.
+ *
+ * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
+ * @return a new method handle which can collect any number of trailing arguments
+ * into an array, before calling the original method handle
+ * @throws IllegalArgumentException if {@code arrayType} is not an array type
+ * or {@code arrayType} is not assignable to this method handle's trailing parameter type
+ * @see #asCollector
+ * @see #isVarargsCollector
+ */
+ public MethodHandle asVarargsCollector(Class<?> arrayType) {
+ Class<?> arrayElement = arrayType.getComponentType();
+ if (arrayElement == null) throw newIllegalArgumentException("not an array type");
+ return MethodHandles.asVarargsCollector(this, arrayType);
+ }
+
+ /**
+ * Determines if this method handle
+ * supports {@linkplain #asVarargsCollector variable arity} calls.
+ * Such method handles arise from the following sources:
+ * <ul>
+ * <li>a call to {@linkplain #asVarargsCollector asVarargsCollector}
+ * <li>a call to a {@linkplain java.lang.invoke.MethodHandles.Lookup lookup method}
+ * which resolves to a variable arity Java method or constructor
+ * <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
+ * which resolves to a variable arity Java method or constructor
+ * </ul>
+ * @return true if this method handle accepts more than one arity of {@code invokeGeneric} calls
+ * @see #asVarargsCollector
+ */
+ public boolean isVarargsCollector() {
+ return false;
+ }
+
+ /**
+ * Binds a value {@code x} to the first argument of a method handle, without invoking it.
+ * The new method handle adapts, as its <i>target</i>,
+ * the current method handle by binding it to the given argument.
+ * The type of the bound handle will be
+ * the same as the type of the target, except that a single leading
+ * reference parameter will be omitted.
+ * <p>
+ * When called, the bound handle inserts the given value {@code x}
+ * as a new leading argument to the target. The other arguments are
+ * also passed unchanged.
+ * What the target eventually returns is returned unchanged by the bound handle.
+ * <p>
+ * The reference {@code x} must be convertible to the first parameter
+ * type of the target.
+ * <p>
+ * (<em>Note:</em> Because method handles are immutable, the target method handle
+ * retains its original type and behavior.)
+ * @param x the value to bind to the first argument of the target
+ * @return a new method handle which prepends the given value to the incoming
+ * argument list, before calling the original method handle
+ * @throws IllegalArgumentException if the target does not have a
+ * leading parameter type that is a reference type
+ * @throws ClassCastException if {@code x} cannot be converted
+ * to the leading parameter type of the target
+ * @see MethodHandles#insertArguments
+ */
+ public MethodHandle bindTo(Object x) {
+ Class<?> ptype;
+ if (type().parameterCount() == 0 ||
+ (ptype = type().parameterType(0)).isPrimitive())
+ throw newIllegalArgumentException("no leading reference parameter", x);
+ x = MethodHandles.checkValue(ptype, x);
+ // Cf. MethodHandles.insertArguments for the following logic:
+ MethodHandle bmh = MethodHandleImpl.bindReceiver(this, x);
+ if (bmh != null) return bmh;
+ return MethodHandleImpl.bindArgument(this, 0, x);
+ }
+
+ /**
+ * Returns a string representation of the method handle,
+ * starting with the string {@code "MethodHandle"} and
+ * ending with the string representation of the method handle's type.
+ * In other words, this method returns a string equal to the value of:
+ * <blockquote><pre>
+ * "MethodHandle" + type().toString()
+ * </pre></blockquote>
+ * <p>
+ * (<em>Note:</em> Future releases of this API may add further information
+ * to the string representation.
+ * Therefore, the present syntax should not be parsed by applications.)
+ *
+ * @return a string representation of the method handle
+ */
+ @Override
+ public String toString() {
+ return getNameString(this);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,1106 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.VerifyType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import sun.invoke.empty.Empty;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
+import sun.misc.Unsafe;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Trusted implementation code for MethodHandle.
+ * @author jrose
+ */
+/*non-public*/ abstract class MethodHandleImpl {
+ /// Factory methods to create method handles:
+
+ private static final MemberName.Factory LOOKUP = MemberName.Factory.INSTANCE;
+
+ static void initStatics() {
+ // Trigger preceding sequence.
+ }
+
+ /** Look up a given method.
+ * Callable only from sun.invoke and related packages.
+ * <p>
+ * The resulting method handle type will be of the given type,
+ * with a receiver type {@code rcvc} prepended if the member is not static.
+ * <p>
+ * Access checks are made as of the given lookup class.
+ * In particular, if the method is protected and {@code defc} is in a
+ * different package from the lookup class, then {@code rcvc} must be
+ * the lookup class or a subclass.
+ * @param token Proof that the lookup class has access to this package.
+ * @param member Resolved method or constructor to call.
+ * @param name Name of the desired method.
+ * @param rcvc Receiver type of desired non-static method (else null)
+ * @param doDispatch whether the method handle will test the receiver type
+ * @param lookupClass access-check relative to this class
+ * @return a direct handle to the matching method
+ * @throws IllegalAccessException if the given method cannot be accessed by the lookup class
+ */
+ static
+ MethodHandle findMethod(MemberName method,
+ boolean doDispatch, Class<?> lookupClass) throws IllegalAccessException {
+ MethodType mtype = method.getMethodType();
+ if (!method.isStatic()) {
+ // adjust the advertised receiver type to be exactly the one requested
+ // (in the case of invokespecial, this will be the calling class)
+ Class<?> recvType = method.getDeclaringClass();
+ mtype = mtype.insertParameterTypes(0, recvType);
+ }
+ DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
+ if (!mh.isValid())
+ throw method.makeAccessException("no access", lookupClass);
+ assert(mh.type() == mtype);
+ if (!method.isVarargs())
+ return mh;
+ else
+ return mh.asVarargsCollector(mtype.parameterType(mtype.parameterCount()-1));
+ }
+
+ static
+ MethodHandle makeAllocator(MethodHandle rawConstructor) {
+ MethodType rawConType = rawConstructor.type();
+ // Wrap the raw (unsafe) constructor with the allocation of a suitable object.
+ MethodHandle allocator
+ = AllocateObject.make(rawConType.parameterType(0), rawConstructor);
+ assert(allocator.type()
+ .equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
+ return allocator;
+ }
+
+ static final class AllocateObject<C> extends BoundMethodHandle {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+ private final Class<C> allocateClass;
+ private final MethodHandle rawConstructor;
+
+ private AllocateObject(MethodHandle invoker,
+ Class<C> allocateClass, MethodHandle rawConstructor) {
+ super(invoker);
+ this.allocateClass = allocateClass;
+ this.rawConstructor = rawConstructor;
+ }
+ static MethodHandle make(Class<?> allocateClass, MethodHandle rawConstructor) {
+ MethodType rawConType = rawConstructor.type();
+ assert(rawConType.parameterType(0) == allocateClass);
+ MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass);
+ int nargs = rawConType.parameterCount() - 1;
+ if (nargs < INVOKES.length) {
+ MethodHandle invoke = INVOKES[nargs];
+ MethodType conType = CON_TYPES[nargs];
+ MethodHandle gcon = convertArguments(rawConstructor, conType, rawConType, null);
+ if (gcon == null) return null;
+ MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
+ assert(galloc.type() == newType.generic());
+ return convertArguments(galloc, newType, galloc.type(), null);
+ } else {
+ MethodHandle invoke = VARARGS_INVOKE;
+ MethodType conType = CON_TYPES[nargs];
+ MethodHandle gcon = spreadArguments(rawConstructor, conType, 1);
+ if (gcon == null) return null;
+ MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
+ return collectArguments(galloc, newType, 1, null);
+ }
+ }
+ @Override
+ public String toString() {
+ return addTypeString(allocateClass.getSimpleName(), this);
+ }
+ @SuppressWarnings("unchecked")
+ private C allocate() throws InstantiationException {
+ return (C) unsafe.allocateInstance(allocateClass);
+ }
+ private C invoke_V(Object... av) throws Throwable {
+ C obj = allocate();
+ rawConstructor.invokeExact((Object)obj, av);
+ return obj;
+ }
+ private C invoke_L0() throws Throwable {
+ C obj = allocate();
+ rawConstructor.invokeExact((Object)obj);
+ return obj;
+ }
+ private C invoke_L1(Object a0) throws Throwable {
+ C obj = allocate();
+ rawConstructor.invokeExact((Object)obj, a0);
+ return obj;
+ }
+ private C invoke_L2(Object a0, Object a1) throws Throwable {
+ C obj = allocate();
+ rawConstructor.invokeExact((Object)obj, a0, a1);
+ return obj;
+ }
+ private C invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
+ C obj = allocate();
+ rawConstructor.invokeExact((Object)obj, a0, a1, a2);
+ return obj;
+ }
+ private C invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ C obj = allocate();
+ rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3);
+ return obj;
+ }
+ private C invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
+ C obj = allocate();
+ rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4);
+ return obj;
+ }
+ private C invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
+ C obj = allocate();
+ rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5);
+ return obj;
+ }
+ private C invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
+ C obj = allocate();
+ rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6);
+ return obj;
+ }
+ private C invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ C obj = allocate();
+ rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7);
+ return obj;
+ }
+ static MethodHandle[] makeInvokes() {
+ ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
+ MethodHandles.Lookup lookup = IMPL_LOOKUP;
+ for (;;) {
+ int nargs = invokes.size();
+ String name = "invoke_L"+nargs;
+ MethodHandle invoke = null;
+ try {
+ invoke = lookup.findVirtual(AllocateObject.class, name, MethodType.genericMethodType(nargs));
+ } catch (ReflectiveOperationException ex) {
+ }
+ if (invoke == null) break;
+ invokes.add(invoke);
+ }
+ assert(invokes.size() == 9); // current number of methods
+ return invokes.toArray(new MethodHandle[0]);
+ };
+ static final MethodHandle[] INVOKES = makeInvokes();
+ // For testing use this:
+ //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
+ static final MethodHandle VARARGS_INVOKE;
+ static {
+ try {
+ VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
+ } catch (ReflectiveOperationException ex) {
+ throw uncaughtException(ex);
+ }
+ }
+ // Corresponding generic constructor types:
+ static final MethodType[] CON_TYPES = new MethodType[INVOKES.length];
+ static {
+ for (int i = 0; i < INVOKES.length; i++)
+ CON_TYPES[i] = makeConType(INVOKES[i]);
+ }
+ static final MethodType VARARGS_CON_TYPE = makeConType(VARARGS_INVOKE);
+ static MethodType makeConType(MethodHandle invoke) {
+ MethodType invType = invoke.type();
+ return invType.changeParameterType(0, Object.class).changeReturnType(void.class);
+ }
+ }
+
+ static
+ MethodHandle accessField(MemberName member, boolean isSetter,
+ Class<?> lookupClass) {
+ // Use sun. misc.Unsafe to dig up the dirt on the field.
+ MethodHandle mh = new FieldAccessor(member, isSetter);
+ return mh;
+ }
+
+ static
+ MethodHandle accessArrayElement(Class<?> arrayClass, boolean isSetter) {
+ if (!arrayClass.isArray())
+ throw newIllegalArgumentException("not an array: "+arrayClass);
+ Class<?> elemClass = arrayClass.getComponentType();
+ MethodHandle[] mhs = FieldAccessor.ARRAY_CACHE.get(elemClass);
+ if (mhs == null) {
+ if (!FieldAccessor.doCache(elemClass))
+ return FieldAccessor.ahandle(arrayClass, isSetter);
+ mhs = new MethodHandle[] {
+ FieldAccessor.ahandle(arrayClass, false),
+ FieldAccessor.ahandle(arrayClass, true)
+ };
+ if (mhs[0].type().parameterType(0) == Class.class) {
+ mhs[0] = MethodHandles.insertArguments(mhs[0], 0, elemClass);
+ mhs[1] = MethodHandles.insertArguments(mhs[1], 0, elemClass);
+ }
+ synchronized (FieldAccessor.ARRAY_CACHE) {} // memory barrier
+ FieldAccessor.ARRAY_CACHE.put(elemClass, mhs);
+ }
+ return mhs[isSetter ? 1 : 0];
+ }
+
+ static final class FieldAccessor<C,V> extends BoundMethodHandle {
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
+ final Object base; // for static refs only
+ final long offset;
+ final String name;
+
+ FieldAccessor(MemberName field, boolean isSetter) {
+ super(fhandle(field.getDeclaringClass(), field.getFieldType(), isSetter, field.isStatic()));
+ this.offset = (long) field.getVMIndex();
+ this.name = field.getName();
+ this.base = staticBase(field);
+ }
+ @Override
+ public String toString() { return addTypeString(name, this); }
+
+ int getFieldI(C obj) { return unsafe.getInt(obj, offset); }
+ void setFieldI(C obj, int x) { unsafe.putInt(obj, offset, x); }
+ long getFieldJ(C obj) { return unsafe.getLong(obj, offset); }
+ void setFieldJ(C obj, long x) { unsafe.putLong(obj, offset, x); }
+ float getFieldF(C obj) { return unsafe.getFloat(obj, offset); }
+ void setFieldF(C obj, float x) { unsafe.putFloat(obj, offset, x); }
+ double getFieldD(C obj) { return unsafe.getDouble(obj, offset); }
+ void setFieldD(C obj, double x) { unsafe.putDouble(obj, offset, x); }
+ boolean getFieldZ(C obj) { return unsafe.getBoolean(obj, offset); }
+ void setFieldZ(C obj, boolean x) { unsafe.putBoolean(obj, offset, x); }
+ byte getFieldB(C obj) { return unsafe.getByte(obj, offset); }
+ void setFieldB(C obj, byte x) { unsafe.putByte(obj, offset, x); }
+ short getFieldS(C obj) { return unsafe.getShort(obj, offset); }
+ void setFieldS(C obj, short x) { unsafe.putShort(obj, offset, x); }
+ char getFieldC(C obj) { return unsafe.getChar(obj, offset); }
+ void setFieldC(C obj, char x) { unsafe.putChar(obj, offset, x); }
+ @SuppressWarnings("unchecked")
+ V getFieldL(C obj) { return (V) unsafe.getObject(obj, offset); }
+ @SuppressWarnings("unchecked")
+ void setFieldL(C obj, V x) { unsafe.putObject(obj, offset, x); }
+ // cast (V) is OK here, since we wrap convertArguments around the MH.
+
+ static Object staticBase(MemberName field) {
+ if (!field.isStatic()) return null;
+ Class c = field.getDeclaringClass();
+ java.lang.reflect.Field f;
+ try {
+ // FIXME: Should not have to create 'f' to get this value.
+ f = c.getDeclaredField(field.getName());
+ return unsafe.staticFieldBase(f);
+ } catch (Exception ee) {
+ throw uncaughtException(ee);
+ }
+ }
+
+ int getStaticI() { return unsafe.getInt(base, offset); }
+ void setStaticI(int x) { unsafe.putInt(base, offset, x); }
+ long getStaticJ() { return unsafe.getLong(base, offset); }
+ void setStaticJ(long x) { unsafe.putLong(base, offset, x); }
+ float getStaticF() { return unsafe.getFloat(base, offset); }
+ void setStaticF(float x) { unsafe.putFloat(base, offset, x); }
+ double getStaticD() { return unsafe.getDouble(base, offset); }
+ void setStaticD(double x) { unsafe.putDouble(base, offset, x); }
+ boolean getStaticZ() { return unsafe.getBoolean(base, offset); }
+ void setStaticZ(boolean x) { unsafe.putBoolean(base, offset, x); }
+ byte getStaticB() { return unsafe.getByte(base, offset); }
+ void setStaticB(byte x) { unsafe.putByte(base, offset, x); }
+ short getStaticS() { return unsafe.getShort(base, offset); }
+ void setStaticS(short x) { unsafe.putShort(base, offset, x); }
+ char getStaticC() { return unsafe.getChar(base, offset); }
+ void setStaticC(char x) { unsafe.putChar(base, offset, x); }
+ V getStaticL() { return (V) unsafe.getObject(base, offset); }
+ void setStaticL(V x) { unsafe.putObject(base, offset, x); }
+
+ static String fname(Class<?> vclass, boolean isSetter, boolean isStatic) {
+ String stem;
+ if (!isStatic)
+ stem = (!isSetter ? "getField" : "setField");
+ else
+ stem = (!isSetter ? "getStatic" : "setStatic");
+ return stem + Wrapper.basicTypeChar(vclass);
+ }
+ static MethodType ftype(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) {
+ MethodType type;
+ if (!isStatic) {
+ if (!isSetter)
+ return MethodType.methodType(vclass, cclass);
+ else
+ return MethodType.methodType(void.class, cclass, vclass);
+ } else {
+ if (!isSetter)
+ return MethodType.methodType(vclass);
+ else
+ return MethodType.methodType(void.class, vclass);
+ }
+ }
+ static MethodHandle fhandle(Class<?> cclass, Class<?> vclass, boolean isSetter, boolean isStatic) {
+ String name = FieldAccessor.fname(vclass, isSetter, isStatic);
+ if (cclass.isPrimitive()) throw newIllegalArgumentException("primitive "+cclass);
+ Class<?> ecclass = Object.class; //erase this type
+ Class<?> evclass = vclass;
+ if (!evclass.isPrimitive()) evclass = Object.class;
+ MethodType type = FieldAccessor.ftype(ecclass, evclass, isSetter, isStatic);
+ MethodHandle mh;
+ try {
+ mh = IMPL_LOOKUP.findVirtual(FieldAccessor.class, name, type);
+ } catch (ReflectiveOperationException ex) {
+ throw uncaughtException(ex);
+ }
+ if (evclass != vclass || (!isStatic && ecclass != cclass)) {
+ MethodType strongType = FieldAccessor.ftype(cclass, vclass, isSetter, isStatic);
+ strongType = strongType.insertParameterTypes(0, FieldAccessor.class);
+ mh = MethodHandles.convertArguments(mh, strongType);
+ }
+ return mh;
+ }
+
+ /// Support for array element access
+ static final HashMap<Class<?>, MethodHandle[]> ARRAY_CACHE =
+ new HashMap<Class<?>, MethodHandle[]>();
+ // FIXME: Cache on the classes themselves, not here.
+ static boolean doCache(Class<?> elemClass) {
+ if (elemClass.isPrimitive()) return true;
+ ClassLoader cl = elemClass.getClassLoader();
+ return cl == null || cl == ClassLoader.getSystemClassLoader();
+ }
+ static int getElementI(int[] a, int i) { return a[i]; }
+ static void setElementI(int[] a, int i, int x) { a[i] = x; }
+ static long getElementJ(long[] a, int i) { return a[i]; }
+ static void setElementJ(long[] a, int i, long x) { a[i] = x; }
+ static float getElementF(float[] a, int i) { return a[i]; }
+ static void setElementF(float[] a, int i, float x) { a[i] = x; }
+ static double getElementD(double[] a, int i) { return a[i]; }
+ static void setElementD(double[] a, int i, double x) { a[i] = x; }
+ static boolean getElementZ(boolean[] a, int i) { return a[i]; }
+ static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; }
+ static byte getElementB(byte[] a, int i) { return a[i]; }
+ static void setElementB(byte[] a, int i, byte x) { a[i] = x; }
+ static short getElementS(short[] a, int i) { return a[i]; }
+ static void setElementS(short[] a, int i, short x) { a[i] = x; }
+ static char getElementC(char[] a, int i) { return a[i]; }
+ static void setElementC(char[] a, int i, char x) { a[i] = x; }
+ static Object getElementL(Object[] a, int i) { return a[i]; }
+ static void setElementL(Object[] a, int i, Object x) { a[i] = x; }
+ static <V> V getElementL(Class<V[]> aclass, V[] a, int i) { return aclass.cast(a)[i]; }
+ static <V> void setElementL(Class<V[]> aclass, V[] a, int i, V x) { aclass.cast(a)[i] = x; }
+
+ static String aname(Class<?> aclass, boolean isSetter) {
+ Class<?> vclass = aclass.getComponentType();
+ if (vclass == null) throw new IllegalArgumentException();
+ return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(vclass);
+ }
+ static MethodType atype(Class<?> aclass, boolean isSetter) {
+ Class<?> vclass = aclass.getComponentType();
+ if (!isSetter)
+ return MethodType.methodType(vclass, aclass, int.class);
+ else
+ return MethodType.methodType(void.class, aclass, int.class, vclass);
+ }
+ static MethodHandle ahandle(Class<?> aclass, boolean isSetter) {
+ Class<?> vclass = aclass.getComponentType();
+ String name = FieldAccessor.aname(aclass, isSetter);
+ Class<?> caclass = null;
+ if (!vclass.isPrimitive() && vclass != Object.class) {
+ caclass = aclass;
+ aclass = Object[].class;
+ vclass = Object.class;
+ }
+ MethodType type = FieldAccessor.atype(aclass, isSetter);
+ if (caclass != null)
+ type = type.insertParameterTypes(0, Class.class);
+ MethodHandle mh;
+ try {
+ mh = IMPL_LOOKUP.findStatic(FieldAccessor.class, name, type);
+ } catch (ReflectiveOperationException ex) {
+ throw uncaughtException(ex);
+ }
+ if (caclass != null) {
+ MethodType strongType = FieldAccessor.atype(caclass, isSetter);
+ mh = MethodHandles.insertArguments(mh, 0, caclass);
+ mh = MethodHandles.convertArguments(mh, strongType);
+ }
+ return mh;
+ }
+ }
+
+ /** Bind a predetermined first argument to the given direct method handle.
+ * Callable only from MethodHandles.
+ * @param token Proof that the caller has access to this package.
+ * @param target Any direct method handle.
+ * @param receiver Receiver (or first static method argument) to pre-bind.
+ * @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
+ */
+ static
+ MethodHandle bindReceiver(MethodHandle target, Object receiver) {
+ if (target instanceof AdapterMethodHandle &&
+ ((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY
+ ) {
+ Object info = MethodHandleNatives.getTargetInfo(target);
+ if (info instanceof DirectMethodHandle) {
+ DirectMethodHandle dmh = (DirectMethodHandle) info;
+ if (receiver == null ||
+ dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
+ MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0);
+ MethodType newType = target.type().dropParameterTypes(0, 1);
+ return convertArguments(bmh, newType, bmh.type(), null);
+ }
+ }
+ }
+ if (target instanceof DirectMethodHandle)
+ return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0);
+ return null; // let caller try something else
+ }
+
+ /** Bind a predetermined argument to the given arbitrary method handle.
+ * Callable only from MethodHandles.
+ * @param token Proof that the caller has access to this package.
+ * @param target Any method handle.
+ * @param receiver Argument (which can be a boxed primitive) to pre-bind.
+ * @return a suitable BoundMethodHandle
+ */
+ static
+ MethodHandle bindArgument(MethodHandle target, int argnum, Object receiver) {
+ return new BoundMethodHandle(target, receiver, argnum);
+ }
+
+ static MethodHandle convertArguments(MethodHandle target,
+ MethodType newType,
+ MethodType oldType,
+ int[] permutationOrNull) {
+ assert(oldType.parameterCount() == target.type().parameterCount());
+ if (permutationOrNull != null) {
+ int outargs = oldType.parameterCount(), inargs = newType.parameterCount();
+ if (permutationOrNull.length != outargs)
+ throw newIllegalArgumentException("wrong number of arguments in permutation");
+ // Make the individual outgoing argument types match up first.
+ Class<?>[] callTypeArgs = new Class<?>[outargs];
+ for (int i = 0; i < outargs; i++)
+ callTypeArgs[i] = newType.parameterType(permutationOrNull[i]);
+ MethodType callType = MethodType.methodType(oldType.returnType(), callTypeArgs);
+ target = convertArguments(target, callType, oldType, null);
+ assert(target != null);
+ oldType = target.type();
+ List<Integer> goal = new ArrayList<Integer>(); // i*TOKEN
+ List<Integer> state = new ArrayList<Integer>(); // i*TOKEN
+ List<Integer> drops = new ArrayList<Integer>(); // not tokens
+ List<Integer> dups = new ArrayList<Integer>(); // not tokens
+ final int TOKEN = 10; // to mark items which are symbolic only
+ // state represents the argument values coming into target
+ for (int i = 0; i < outargs; i++) {
+ state.add(permutationOrNull[i] * TOKEN);
+ }
+ // goal represents the desired state
+ for (int i = 0; i < inargs; i++) {
+ if (state.contains(i * TOKEN)) {
+ goal.add(i * TOKEN);
+ } else {
+ // adapter must initially drop all unused arguments
+ drops.add(i);
+ }
+ }
+ // detect duplications
+ while (state.size() > goal.size()) {
+ for (int i2 = 0; i2 < state.size(); i2++) {
+ int arg1 = state.get(i2);
+ int i1 = state.indexOf(arg1);
+ if (i1 != i2) {
+ // found duplicate occurrence at i2
+ int arg2 = (inargs++) * TOKEN;
+ state.set(i2, arg2);
+ dups.add(goal.indexOf(arg1));
+ goal.add(arg2);
+ }
+ }
+ }
+ assert(state.size() == goal.size());
+ int size = goal.size();
+ while (!state.equals(goal)) {
+ // Look for a maximal sequence of adjacent misplaced arguments,
+ // and try to rotate them into place.
+ int bestRotArg = -10 * TOKEN, bestRotLen = 0;
+ int thisRotArg = -10 * TOKEN, thisRotLen = 0;
+ for (int i = 0; i < size; i++) {
+ int arg = state.get(i);
+ // Does this argument match the current run?
+ if (arg == thisRotArg + TOKEN) {
+ thisRotArg = arg;
+ thisRotLen += 1;
+ if (bestRotLen < thisRotLen) {
+ bestRotLen = thisRotLen;
+ bestRotArg = thisRotArg;
+ }
+ } else {
+ // The old sequence (if any) stops here.
+ thisRotLen = 0;
+ thisRotArg = -10 * TOKEN;
+ // But maybe a new one starts here also.
+ int wantArg = goal.get(i);
+ final int MAX_ARG_ROTATION = AdapterMethodHandle.MAX_ARG_ROTATION;
+ if (arg != wantArg &&
+ arg >= wantArg - TOKEN * MAX_ARG_ROTATION &&
+ arg <= wantArg + TOKEN * MAX_ARG_ROTATION) {
+ thisRotArg = arg;
+ thisRotLen = 1;
+ }
+ }
+ }
+ if (bestRotLen >= 2) {
+ // Do a rotation if it can improve argument positioning
+ // by at least 2 arguments. This is not always optimal,
+ // but it seems to catch common cases.
+ int dstEnd = state.indexOf(bestRotArg);
+ int srcEnd = goal.indexOf(bestRotArg);
+ int rotBy = dstEnd - srcEnd;
+ int dstBeg = dstEnd - (bestRotLen - 1);
+ int srcBeg = srcEnd - (bestRotLen - 1);
+ assert((dstEnd | dstBeg | srcEnd | srcBeg) >= 0); // no negs
+ // Make a span which covers both source and destination.
+ int rotBeg = Math.min(dstBeg, srcBeg);
+ int rotEnd = Math.max(dstEnd, srcEnd);
+ int score = 0;
+ for (int i = rotBeg; i <= rotEnd; i++) {
+ if ((int)state.get(i) != (int)goal.get(i))
+ score += 1;
+ }
+ List<Integer> rotSpan = state.subList(rotBeg, rotEnd+1);
+ Collections.rotate(rotSpan, -rotBy); // reverse direction
+ for (int i = rotBeg; i <= rotEnd; i++) {
+ if ((int)state.get(i) != (int)goal.get(i))
+ score -= 1;
+ }
+ if (score >= 2) {
+ // Improved at least two argument positions. Do it.
+ List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray());
+ Collections.rotate(ptypes.subList(rotBeg, rotEnd+1), -rotBy);
+ MethodType rotType = MethodType.methodType(oldType.returnType(), ptypes);
+ MethodHandle nextTarget
+ = AdapterMethodHandle.makeRotateArguments(rotType, target,
+ rotBeg, rotSpan.size(), rotBy);
+ if (nextTarget != null) {
+ //System.out.println("Rot: "+rotSpan+" by "+rotBy);
+ target = nextTarget;
+ oldType = rotType;
+ continue;
+ }
+ }
+ // Else de-rotate, and drop through to the swap-fest.
+ Collections.rotate(rotSpan, rotBy);
+ }
+
+ // Now swap like the wind!
+ List<Class<?>> ptypes = Arrays.asList(oldType.parameterArray());
+ for (int i = 0; i < size; i++) {
+ // What argument do I want here?
+ int arg = goal.get(i);
+ if (arg != state.get(i)) {
+ // Where is it now?
+ int j = state.indexOf(arg);
+ Collections.swap(ptypes, i, j);
+ MethodType swapType = MethodType.methodType(oldType.returnType(), ptypes);
+ target = AdapterMethodHandle.makeSwapArguments(swapType, target, i, j);
+ if (target == null) throw newIllegalArgumentException("cannot swap");
+ assert(target.type() == swapType);
+ oldType = swapType;
+ Collections.swap(state, i, j);
+ }
+ }
+ // One pass of swapping must finish the job.
+ assert(state.equals(goal));
+ }
+ while (!dups.isEmpty()) {
+ // Grab a contiguous trailing sequence of dups.
+ int grab = dups.size() - 1;
+ int dupArgPos = dups.get(grab), dupArgCount = 1;
+ while (grab - 1 >= 0) {
+ int dup0 = dups.get(grab - 1);
+ if (dup0 != dupArgPos - 1) break;
+ dupArgPos -= 1;
+ dupArgCount += 1;
+ grab -= 1;
+ }
+ //if (dupArgCount > 1) System.out.println("Dup: "+dups.subList(grab, dups.size()));
+ dups.subList(grab, dups.size()).clear();
+ // In the new target type drop that many args from the tail:
+ List<Class<?>> ptypes = oldType.parameterList();
+ ptypes = ptypes.subList(0, ptypes.size() - dupArgCount);
+ MethodType dupType = MethodType.methodType(oldType.returnType(), ptypes);
+ target = AdapterMethodHandle.makeDupArguments(dupType, target, dupArgPos, dupArgCount);
+ if (target == null)
+ throw newIllegalArgumentException("cannot dup");
+ oldType = target.type();
+ }
+ while (!drops.isEmpty()) {
+ // Grab a contiguous initial sequence of drops.
+ int dropArgPos = drops.get(0), dropArgCount = 1;
+ while (dropArgCount < drops.size()) {
+ int drop1 = drops.get(dropArgCount);
+ if (drop1 != dropArgPos + dropArgCount) break;
+ dropArgCount += 1;
+ }
+ //if (dropArgCount > 1) System.out.println("Drop: "+drops.subList(0, dropArgCount));
+ drops.subList(0, dropArgCount).clear();
+ List<Class<?>> dropTypes = newType.parameterList()
+ .subList(dropArgPos, dropArgPos + dropArgCount);
+ MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes);
+ target = AdapterMethodHandle.makeDropArguments(dropType, target, dropArgPos, dropArgCount);
+ if (target == null) throw newIllegalArgumentException("cannot drop");
+ oldType = target.type();
+ }
+ }
+ if (newType == oldType)
+ return target;
+ if (oldType.parameterCount() != newType.parameterCount())
+ throw newIllegalArgumentException("mismatched parameter count");
+ MethodHandle res = AdapterMethodHandle.makePairwiseConvert(newType, target);
+ if (res != null)
+ return res;
+ int argc = oldType.parameterCount();
+ // The JVM can't do it directly, so fill in the gap with a Java adapter.
+ // TO DO: figure out what to put here from case-by-case experience
+ // Use a heavier method: Convert all the arguments to Object,
+ // then back to the desired types. We might have to use Java-based
+ // method handles to do this.
+ MethodType objType = MethodType.genericMethodType(argc);
+ MethodHandle objTarget = AdapterMethodHandle.makePairwiseConvert(objType, target);
+ if (objTarget == null)
+ objTarget = FromGeneric.make(target);
+ res = AdapterMethodHandle.makePairwiseConvert(newType, objTarget);
+ if (res != null)
+ return res;
+ return ToGeneric.make(newType, objTarget);
+ }
+
+ static MethodHandle spreadArguments(MethodHandle target,
+ MethodType newType,
+ int spreadArg) {
+ // TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
+ MethodType oldType = target.type();
+ // spread the last argument of newType to oldType
+ int spreadCount = oldType.parameterCount() - spreadArg;
+ Class<Object[]> spreadArgType = Object[].class;
+ MethodHandle res = AdapterMethodHandle.makeSpreadArguments(newType, target, spreadArgType, spreadArg, spreadCount);
+ if (res != null)
+ return res;
+ // try an intermediate adapter
+ Class<?> spreadType = null;
+ if (spreadArg < 0 || spreadArg >= newType.parameterCount()
+ || !VerifyType.isSpreadArgType(spreadType = newType.parameterType(spreadArg)))
+ throw newIllegalArgumentException("no restarg in "+newType);
+ Class<?>[] ptypes = oldType.parameterArray();
+ for (int i = 0; i < spreadCount; i++)
+ ptypes[spreadArg + i] = VerifyType.spreadArgElementType(spreadType, i);
+ MethodType midType = MethodType.methodType(newType.returnType(), ptypes);
+ // after spreading, some arguments may need further conversion
+ MethodHandle target2 = convertArguments(target, midType, oldType, null);
+ if (target2 == null)
+ throw new UnsupportedOperationException("NYI: convert "+midType+" =calls=> "+oldType);
+ res = AdapterMethodHandle.makeSpreadArguments(newType, target2, spreadArgType, spreadArg, spreadCount);
+ if (res != null)
+ return res;
+ res = SpreadGeneric.make(target2, spreadCount);
+ if (res != null)
+ res = convertArguments(res, newType, res.type(), null);
+ return res;
+ }
+
+ static MethodHandle collectArguments(MethodHandle target,
+ MethodType newType,
+ int collectArg,
+ MethodHandle collector) {
+ MethodType oldType = target.type(); // (a...,c)=>r
+ if (collector == null) {
+ int numCollect = newType.parameterCount() - oldType.parameterCount() + 1;
+ collector = ValueConversions.varargsArray(numCollect);
+ }
+ // newType // (a..., b...)=>r
+ MethodType colType = collector.type(); // (b...)=>c
+ // oldType // (a..., b...)=>r
+ assert(newType.parameterCount() == collectArg + colType.parameterCount());
+ assert(oldType.parameterCount() == collectArg + 1);
+ MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, null);
+ MethodHandle gcollector = convertArguments(collector, colType.generic(), colType, null);
+ if (gtarget == null || gcollector == null) return null;
+ MethodHandle gresult = FilterGeneric.makeArgumentCollector(gcollector, gtarget);
+ MethodHandle result = convertArguments(gresult, newType, gresult.type(), null);
+ return result;
+ }
+
+ static MethodHandle filterArgument(MethodHandle target,
+ int pos,
+ MethodHandle filter) {
+ MethodType ttype = target.type(), gttype = ttype.generic();
+ if (ttype != gttype) {
+ target = convertArguments(target, gttype, ttype, null);
+ ttype = gttype;
+ }
+ MethodType ftype = filter.type(), gftype = ftype.generic();
+ if (ftype.parameterCount() != 1)
+ throw new InternalError();
+ if (ftype != gftype) {
+ filter = convertArguments(filter, gftype, ftype, null);
+ ftype = gftype;
+ }
+ if (ftype == ttype) {
+ // simple unary case
+ return FilterOneArgument.make(filter, target);
+ }
+ return FilterGeneric.makeArgumentFilter(pos, filter, target);
+ }
+
+ static MethodHandle foldArguments(MethodHandle target,
+ MethodType newType,
+ MethodHandle combiner) {
+ MethodType oldType = target.type();
+ MethodType ctype = combiner.type();
+ MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, null);
+ MethodHandle gcombiner = convertArguments(combiner, ctype.generic(), ctype, null);
+ if (gtarget == null || gcombiner == null) return null;
+ MethodHandle gresult = FilterGeneric.makeArgumentFolder(gcombiner, gtarget);
+ MethodHandle result = convertArguments(gresult, newType, gresult.type(), null);
+ return result;
+ }
+
+ static
+ MethodHandle dropArguments(MethodHandle target,
+ MethodType newType, int argnum) {
+ int drops = newType.parameterCount() - target.type().parameterCount();
+ MethodHandle res = AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops);
+ if (res != null)
+ return res;
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ private static class GuardWithTest extends BoundMethodHandle {
+ private final MethodHandle test, target, fallback;
+ private GuardWithTest(MethodHandle invoker,
+ MethodHandle test, MethodHandle target, MethodHandle fallback) {
+ super(invoker);
+ this.test = test;
+ this.target = target;
+ this.fallback = fallback;
+ }
+ static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) {
+ MethodType type = target.type();
+ int nargs = type.parameterCount();
+ if (nargs < INVOKES.length) {
+ MethodHandle invoke = INVOKES[nargs];
+ MethodType gtype = type.generic();
+ assert(invoke.type().dropParameterTypes(0,1) == gtype);
+ MethodHandle gtest = convertArguments(test, gtype.changeReturnType(boolean.class), test.type(), null);
+ MethodHandle gtarget = convertArguments(target, gtype, type, null);
+ MethodHandle gfallback = convertArguments(fallback, gtype, type, null);
+ if (gtest == null || gtarget == null || gfallback == null) return null;
+ MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
+ return convertArguments(gguard, type, gtype, null);
+ } else {
+ MethodHandle invoke = VARARGS_INVOKE;
+ MethodType gtype = MethodType.genericMethodType(1);
+ assert(invoke.type().dropParameterTypes(0,1) == gtype);
+ MethodHandle gtest = spreadArguments(test, gtype.changeReturnType(boolean.class), 0);
+ MethodHandle gtarget = spreadArguments(target, gtype, 0);
+ MethodHandle gfallback = spreadArguments(fallback, gtype, 0);
+ MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
+ if (gtest == null || gtarget == null || gfallback == null) return null;
+ return collectArguments(gguard, type, 0, null);
+ }
+ }
+ @Override
+ public String toString() {
+ return addTypeString(target, this);
+ }
+ private Object invoke_V(Object... av) throws Throwable {
+ if ((boolean) test.invokeExact(av))
+ return target.invokeExact(av);
+ return fallback.invokeExact(av);
+ }
+ private Object invoke_L0() throws Throwable {
+ if ((boolean) test.invokeExact())
+ return target.invokeExact();
+ return fallback.invokeExact();
+ }
+ private Object invoke_L1(Object a0) throws Throwable {
+ if ((boolean) test.invokeExact(a0))
+ return target.invokeExact(a0);
+ return fallback.invokeExact(a0);
+ }
+ private Object invoke_L2(Object a0, Object a1) throws Throwable {
+ if ((boolean) test.invokeExact(a0, a1))
+ return target.invokeExact(a0, a1);
+ return fallback.invokeExact(a0, a1);
+ }
+ private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
+ if ((boolean) test.invokeExact(a0, a1, a2))
+ return target.invokeExact(a0, a1, a2);
+ return fallback.invokeExact(a0, a1, a2);
+ }
+ private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ if ((boolean) test.invokeExact(a0, a1, a2, a3))
+ return target.invokeExact(a0, a1, a2, a3);
+ return fallback.invokeExact(a0, a1, a2, a3);
+ }
+ private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
+ if ((boolean) test.invokeExact(a0, a1, a2, a3, a4))
+ return target.invokeExact(a0, a1, a2, a3, a4);
+ return fallback.invokeExact(a0, a1, a2, a3, a4);
+ }
+ private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
+ if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5))
+ return target.invokeExact(a0, a1, a2, a3, a4, a5);
+ return fallback.invokeExact(a0, a1, a2, a3, a4, a5);
+ }
+ private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
+ if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6))
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
+ return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6);
+ }
+ private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ if ((boolean) test.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7))
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
+ return fallback.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
+ }
+ static MethodHandle[] makeInvokes() {
+ ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
+ MethodHandles.Lookup lookup = IMPL_LOOKUP;
+ for (;;) {
+ int nargs = invokes.size();
+ String name = "invoke_L"+nargs;
+ MethodHandle invoke = null;
+ try {
+ invoke = lookup.findVirtual(GuardWithTest.class, name, MethodType.genericMethodType(nargs));
+ } catch (ReflectiveOperationException ex) {
+ }
+ if (invoke == null) break;
+ invokes.add(invoke);
+ }
+ assert(invokes.size() == 9); // current number of methods
+ return invokes.toArray(new MethodHandle[0]);
+ };
+ static final MethodHandle[] INVOKES = makeInvokes();
+ // For testing use this:
+ //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
+ static final MethodHandle VARARGS_INVOKE;
+ static {
+ try {
+ VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithTest.class, "invoke_V", MethodType.genericMethodType(0, true));
+ } catch (ReflectiveOperationException ex) {
+ throw uncaughtException(ex);
+ }
+ }
+ }
+
+ static
+ MethodHandle makeGuardWithTest(MethodHandle test,
+ MethodHandle target,
+ MethodHandle fallback) {
+ return GuardWithTest.make(test, target, fallback);
+ }
+
+ private static class GuardWithCatch extends BoundMethodHandle {
+ private final MethodHandle target;
+ private final Class<? extends Throwable> exType;
+ private final MethodHandle catcher;
+ GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
+ this(INVOKES[target.type().parameterCount()], target, exType, catcher);
+ }
+ GuardWithCatch(MethodHandle invoker,
+ MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
+ super(invoker);
+ this.target = target;
+ this.exType = exType;
+ this.catcher = catcher;
+ }
+ @Override
+ public String toString() {
+ return addTypeString(target, this);
+ }
+ private Object invoke_V(Object... av) throws Throwable {
+ try {
+ return target.invokeExact(av);
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.invokeExact(t, av);
+ }
+ }
+ private Object invoke_L0() throws Throwable {
+ try {
+ return target.invokeExact();
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.invokeExact(t);
+ }
+ }
+ private Object invoke_L1(Object a0) throws Throwable {
+ try {
+ return target.invokeExact(a0);
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.invokeExact(t, a0);
+ }
+ }
+ private Object invoke_L2(Object a0, Object a1) throws Throwable {
+ try {
+ return target.invokeExact(a0, a1);
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.invokeExact(t, a0, a1);
+ }
+ }
+ private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
+ try {
+ return target.invokeExact(a0, a1, a2);
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.invokeExact(t, a0, a1, a2);
+ }
+ }
+ private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
+ try {
+ return target.invokeExact(a0, a1, a2, a3);
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.invokeExact(t, a0, a1, a2, a3);
+ }
+ }
+ private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
+ try {
+ return target.invokeExact(a0, a1, a2, a3, a4);
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.invokeExact(t, a0, a1, a2, a3, a4);
+ }
+ }
+ private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
+ try {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5);
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5);
+ }
+ }
+ private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
+ try {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
+ }
+ }
+ private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
+ try {
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
+ } catch (Throwable t) {
+ if (!exType.isInstance(t)) throw t;
+ return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
+ }
+ }
+ static MethodHandle[] makeInvokes() {
+ ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
+ MethodHandles.Lookup lookup = IMPL_LOOKUP;
+ for (;;) {
+ int nargs = invokes.size();
+ String name = "invoke_L"+nargs;
+ MethodHandle invoke = null;
+ try {
+ invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
+ } catch (ReflectiveOperationException ex) {
+ }
+ if (invoke == null) break;
+ invokes.add(invoke);
+ }
+ assert(invokes.size() == 9); // current number of methods
+ return invokes.toArray(new MethodHandle[0]);
+ };
+ static final MethodHandle[] INVOKES = makeInvokes();
+ // For testing use this:
+ //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
+ static final MethodHandle VARARGS_INVOKE;
+ static {
+ try {
+ VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
+ } catch (ReflectiveOperationException ex) {
+ throw uncaughtException(ex);
+ }
+ }
+ }
+
+
+ static
+ MethodHandle makeGuardWithCatch(MethodHandle target,
+ Class<? extends Throwable> exType,
+ MethodHandle catcher) {
+ MethodType type = target.type();
+ MethodType ctype = catcher.type();
+ int nargs = type.parameterCount();
+ if (nargs < GuardWithCatch.INVOKES.length) {
+ MethodType gtype = type.generic();
+ MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
+ MethodHandle gtarget = convertArguments(target, gtype, type, null);
+ MethodHandle gcatcher = convertArguments(catcher, gcatchType, ctype, null);
+ MethodHandle gguard = new GuardWithCatch(gtarget, exType, gcatcher);
+ if (gtarget == null || gcatcher == null || gguard == null) return null;
+ return convertArguments(gguard, type, gtype, null);
+ } else {
+ MethodType gtype = MethodType.genericMethodType(0, true);
+ MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
+ MethodHandle gtarget = spreadArguments(target, gtype, 0);
+ MethodHandle gcatcher = spreadArguments(catcher, gcatchType, 1);
+ MethodHandle gguard = new GuardWithCatch(GuardWithCatch.VARARGS_INVOKE, gtarget, exType, gcatcher);
+ if (gtarget == null || gcatcher == null || gguard == null) return null;
+ return collectArguments(gguard, type, 0, null);
+ }
+ }
+
+ static
+ MethodHandle throwException(MethodType type) {
+ return AdapterMethodHandle.makeRetypeRaw(type, throwException());
+ }
+
+ static MethodHandle THROW_EXCEPTION;
+ static MethodHandle throwException() {
+ if (THROW_EXCEPTION != null) return THROW_EXCEPTION;
+ try {
+ THROW_EXCEPTION
+ = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
+ MethodType.methodType(Empty.class, Throwable.class));
+ } catch (ReflectiveOperationException ex) {
+ throw new RuntimeException(ex);
+ }
+ return THROW_EXCEPTION;
+ }
+ static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
+
+ // Linkage support:
+ static void registerBootstrap(Class<?> callerClass, MethodHandle bootstrapMethod) {
+ MethodHandleNatives.registerBootstrap(callerClass, bootstrapMethod);
+ }
+ static MethodHandle getBootstrap(Class<?> callerClass) {
+ return MethodHandleNatives.getBootstrap(callerClass);
+ }
+
+ static MethodHandle asVarargsCollector(MethodHandle target, Class<?> arrayType) {
+ return AdapterMethodHandle.makeVarargsCollector(target, arrayType);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * The JVM interface for the method handles package is all here.
+ * This is an interface internal and private to an implemetantion of JSR 292.
+ * <em>This class is not part of the JSR 292 standard.</em>
+ * @author jrose
+ */
+class MethodHandleNatives {
+
+ private MethodHandleNatives() { } // static only
+
+ /// MethodName support
+
+ static native void init(MemberName self, Object ref);
+ static native void expand(MemberName self);
+ static native void resolve(MemberName self, Class<?> caller);
+ static native int getMembers(Class<?> defc, String matchName, String matchSig,
+ int matchFlags, Class<?> caller, int skip, MemberName[] results);
+
+ /// MethodHandle support
+
+ /** Initialize the method handle to adapt the call. */
+ static native void init(AdapterMethodHandle self, MethodHandle target, int argnum);
+ /** Initialize the method handle to call the correct method, directly. */
+ static native void init(BoundMethodHandle self, Object target, int argnum);
+ /** Initialize the method handle to call as if by an invoke* instruction. */
+ static native void init(DirectMethodHandle self, Object ref, boolean doDispatch, Class<?> caller);
+
+ /** Initialize a method type, once per form. */
+ static native void init(MethodType self);
+
+ /** Tell the JVM about a class's bootstrap method. */
+ static native void registerBootstrap(Class<?> caller, MethodHandle bootstrapMethod);
+
+ /** Ask the JVM about a class's bootstrap method. */
+ static native MethodHandle getBootstrap(Class<?> caller);
+
+ /** Tell the JVM that we need to change the target of an invokedynamic. */
+ static native void setCallSiteTarget(CallSite site, MethodHandle target);
+
+ /** Fetch the vmtarget field.
+ * It will be sanitized as necessary to avoid exposing non-Java references.
+ * This routine is for debugging and reflection.
+ */
+ static native Object getTarget(MethodHandle self, int format);
+
+ /** Fetch the name of the handled method, if available.
+ * This routine is for debugging and reflection.
+ */
+ static MemberName getMethodName(MethodHandle self) {
+ return (MemberName) getTarget(self, ETF_METHOD_NAME);
+ }
+
+ /** Fetch the reflective version of the handled method, if available.
+ */
+ static AccessibleObject getTargetMethod(MethodHandle self) {
+ return (AccessibleObject) getTarget(self, ETF_REFLECT_METHOD);
+ }
+
+ /** Fetch the target of this method handle.
+ * If it directly targets a method, return a MemberName for the method.
+ * If it is chained to another method handle, return that handle.
+ */
+ static Object getTargetInfo(MethodHandle self) {
+ return getTarget(self, ETF_HANDLE_OR_METHOD_NAME);
+ }
+
+ static Object[] makeTarget(Class<?> defc, String name, String sig, int mods, Class<?> refc) {
+ return new Object[] { defc, name, sig, mods, refc };
+ }
+
+ /** Fetch MH-related JVM parameter.
+ * which=0 retrieves MethodHandlePushLimit
+ * which=1 retrieves stack slot push size (in address units)
+ */
+ static native int getConstant(int which);
+
+ /** Java copy of MethodHandlePushLimit in range 2..255. */
+ static final int JVM_PUSH_LIMIT;
+ /** JVM stack motion (in words) after one slot is pushed, usually -1.
+ */
+ static final int JVM_STACK_MOVE_UNIT;
+
+ /** Which conv-ops are implemented by the JVM? */
+ static final int CONV_OP_IMPLEMENTED_MASK;
+
+ private static native void registerNatives();
+ static {
+ int JVM_PUSH_LIMIT_;
+ int JVM_STACK_MOVE_UNIT_;
+ int CONV_OP_IMPLEMENTED_MASK_;
+ try {
+ registerNatives();
+ JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT);
+ JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_UNIT);
+ CONV_OP_IMPLEMENTED_MASK_ = getConstant(Constants.GC_CONV_OP_IMPLEMENTED_MASK);
+ //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
+ } catch (UnsatisfiedLinkError ee) {
+ // ignore; if we use init() methods later we'll see linkage errors
+ JVM_PUSH_LIMIT_ = 3; // arbitrary
+ JVM_STACK_MOVE_UNIT_ = -1; // arbitrary
+ CONV_OP_IMPLEMENTED_MASK_ = 0;
+ JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
+ JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
+ throw ee; // just die; hopeless to try to run with an older JVM
+ }
+ JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
+ JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
+ if (CONV_OP_IMPLEMENTED_MASK_ == 0)
+ CONV_OP_IMPLEMENTED_MASK_ = DEFAULT_CONV_OP_IMPLEMENTED_MASK;
+ CONV_OP_IMPLEMENTED_MASK = CONV_OP_IMPLEMENTED_MASK_;
+ }
+
+ // All compile-time constants go here.
+ // There is an opportunity to check them against the JVM's idea of them.
+ static class Constants {
+ Constants() { } // static only
+ // MethodHandleImpl
+ static final int // for getConstant
+ GC_JVM_PUSH_LIMIT = 0,
+ GC_JVM_STACK_MOVE_UNIT = 1,
+ GC_CONV_OP_IMPLEMENTED_MASK = 2;
+ static final int
+ ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
+ ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self)
+ ETF_METHOD_NAME = 2, // ultimate method as MemberName
+ ETF_REFLECT_METHOD = 3; // ultimate method as java.lang.reflect object (sans refClass)
+
+ // MemberName
+ // The JVM uses values of -2 and above for vtable indexes.
+ // Field values are simple positive offsets.
+ // Ref: src/share/vm/oops/methodOop.hpp
+ // This value is negative enough to avoid such numbers,
+ // but not too negative.
+ static final int
+ MN_IS_METHOD = 0x00010000, // method (not constructor)
+ MN_IS_CONSTRUCTOR = 0x00020000, // constructor
+ MN_IS_FIELD = 0x00040000, // field
+ MN_IS_TYPE = 0x00080000, // nested type
+ MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
+ MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers
+ VM_INDEX_UNINITIALIZED = -99;
+
+ // BoundMethodHandle
+ /** Constants for decoding the vmargslot field, which contains 2 values. */
+ static final int
+ ARG_SLOT_PUSH_SHIFT = 16,
+ ARG_SLOT_MASK = (1<<ARG_SLOT_PUSH_SHIFT)-1;
+
+ // AdapterMethodHandle
+ /** Conversions recognized by the JVM.
+ * They must align with the constants in java.lang.invoke.AdapterMethodHandle,
+ * in the JVM file hotspot/src/share/vm/classfile/javaClasses.hpp.
+ */
+ static final int
+ OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
+ OP_RETYPE_RAW = 0x1, // no argument changes; straight retype
+ OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument
+ OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another
+ OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive
+ OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper (NYI)
+ OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg)
+ OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg)
+ OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS)
+ OP_DROP_ARGS = 0x9, // remove one or more argument slots
+ OP_COLLECT_ARGS = 0xA, // combine one or more arguments into a varargs (NYI)
+ OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size)
+ OP_FLYBY = 0xC, // operate first on reified argument list (NYI)
+ OP_RICOCHET = 0xD, // run an adapter chain on the return value (NYI)
+ CONV_OP_LIMIT = 0xE; // limit of CONV_OP enumeration
+ /** Shift and mask values for decoding the AMH.conversion field.
+ * These numbers are shared with the JVM for creating AMHs.
+ */
+ static final int
+ CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
+ CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
+ CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK
+ CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK
+ CONV_DEST_TYPE_SHIFT = 12, // byte 2 has the adapter BasicType (if needed)
+ CONV_SRC_TYPE_SHIFT = 16, // byte 2 has the source BasicType (if needed)
+ CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
+ CONV_STACK_MOVE_MASK = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1;
+
+ /** Which conv-ops are implemented by the JVM? */
+ static final int DEFAULT_CONV_OP_IMPLEMENTED_MASK =
+ // Value to use if the corresponding JVM query fails.
+ ((1<<OP_RETYPE_ONLY)
+ |(1<<OP_RETYPE_RAW)
+ |(1<<OP_CHECK_CAST)
+ |(1<<OP_PRIM_TO_PRIM)
+ |(1<<OP_REF_TO_PRIM)
+ |(1<<OP_SWAP_ARGS)
+ |(1<<OP_ROT_ARGS)
+ |(1<<OP_DUP_ARGS)
+ |(1<<OP_DROP_ARGS)
+ //|(1<<OP_SPREAD_ARGS)
+ );
+
+ /**
+ * Basic types as encoded in the JVM. These code values are not
+ * intended for use outside this class. They are used as part of
+ * a private interface between the JVM and this class.
+ */
+ static final int
+ T_BOOLEAN = 4,
+ T_CHAR = 5,
+ T_FLOAT = 6,
+ T_DOUBLE = 7,
+ T_BYTE = 8,
+ T_SHORT = 9,
+ T_INT = 10,
+ T_LONG = 11,
+ T_OBJECT = 12,
+ //T_ARRAY = 13
+ T_VOID = 14;
+ //T_ADDRESS = 15
+
+ /**
+ * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries.
+ */
+ static final int
+ REF_getField = 1,
+ REF_getStatic = 2,
+ REF_putField = 3,
+ REF_putStatic = 4,
+ REF_invokeVirtual = 5,
+ REF_invokeStatic = 6,
+ REF_invokeSpecial = 7,
+ REF_newInvokeSpecial = 8,
+ REF_invokeInterface = 9;
+ }
+
+ private static native int getNamedCon(int which, Object[] name);
+ static boolean verifyConstants() {
+ Object[] box = { null };
+ for (int i = 0; ; i++) {
+ box[0] = null;
+ int vmval = getNamedCon(i, box);
+ if (box[0] == null) break;
+ String name = (String) box[0];
+ try {
+ Field con = Constants.class.getDeclaredField(name);
+ int jval = con.getInt(null);
+ if (jval != vmval)
+ throw new InternalError(name+": JVM has "+vmval+" while Java has "+jval);
+ } catch (Exception ex) {
+ throw new InternalError(name+": access failed, got "+ex);
+ }
+ }
+ return true;
+ }
+ static {
+ verifyConstants();
+ }
+
+ // Up-calls from the JVM.
+ // These must NOT be public.
+
+ /**
+ * The JVM is linking an invokedynamic instruction. Create a reified call site for it.
+ */
+ static CallSite makeDynamicCallSite(MethodHandle bootstrapMethod,
+ String name, MethodType type,
+ Object info,
+ MemberName callerMethod, int callerBCI) {
+ return CallSite.makeSite(bootstrapMethod, name, type, info, callerMethod, callerBCI);
+ }
+
+ /**
+ * Called by the JVM to check the length of a spread array.
+ */
+ static void checkSpreadArgument(Object av, int n) {
+ MethodHandleStatics.checkSpreadArgument(av, n);
+ }
+
+ /**
+ * The JVM wants a pointer to a MethodType. Oblige it by finding or creating one.
+ */
+ static MethodType findMethodHandleType(Class<?> rtype, Class<?>[] ptypes) {
+ return MethodType.makeImpl(rtype, ptypes, true);
+ }
+
+ /**
+ * The JVM wants to use a MethodType with invokeGeneric. Give the runtime fair warning.
+ */
+ static void notifyGenericMethodType(MethodType type) {
+ type.form().notifyGenericMethodType();
+ }
+
+ /**
+ * The JVM wants to raise an exception. Here's the path.
+ */
+ static void raiseException(int code, Object actual, Object required) {
+ String message;
+ // disregard the identity of the actual object, if it is not a class:
+ if (!(actual instanceof Class) && !(actual instanceof MethodType))
+ actual = actual.getClass();
+ if (actual != null)
+ message = "required "+required+" but encountered "+actual;
+ else
+ message = "required "+required;
+ switch (code) {
+ case 192: // checkcast
+ throw new ClassCastException(message);
+ default:
+ throw new InternalError("unexpected code "+code+": "+message);
+ }
+ }
+
+ /**
+ * The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help.
+ * It will make an up-call to this method. (Do not change the name or signature.)
+ */
+ static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
+ Class<?> defc, String name, Object type) {
+ try {
+ Lookup lookup = IMPL_LOOKUP.in(callerClass);
+ switch (refKind) {
+ case REF_getField: return lookup.findGetter( defc, name, (Class<?>) type );
+ case REF_getStatic: return lookup.findStaticGetter( defc, name, (Class<?>) type );
+ case REF_putField: return lookup.findSetter( defc, name, (Class<?>) type );
+ case REF_putStatic: return lookup.findStaticSetter( defc, name, (Class<?>) type );
+ case REF_invokeVirtual: return lookup.findVirtual( defc, name, (MethodType) type );
+ case REF_invokeStatic: return lookup.findStatic( defc, name, (MethodType) type );
+ case REF_invokeSpecial: return lookup.findSpecial( defc, name, (MethodType) type, callerClass );
+ case REF_newInvokeSpecial: return lookup.findConstructor( defc, (MethodType) type );
+ case REF_invokeInterface: return lookup.findVirtual( defc, name, (MethodType) type );
+ }
+ throw new IllegalArgumentException("bad MethodHandle constant "+name+" : "+type);
+ } catch (ReflectiveOperationException ex) {
+ Error err = new IncompatibleClassChangeError();
+ err.initCause(ex);
+ throw err;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * This class consists exclusively of static names internal to the
+ * method handle implementation.
+ * Usage: {@code import static java.lang.invoke.MethodHandleStatics.*}
+ * @author John Rose, JSR 292 EG
+ */
+/*non-public*/ class MethodHandleStatics {
+
+ private MethodHandleStatics() { } // do not instantiate
+
+ /*non-public*/ static String getNameString(MethodHandle target, MethodType type) {
+ if (type == null)
+ type = target.type();
+ MemberName name = null;
+ if (target != null)
+ name = MethodHandleNatives.getMethodName(target);
+ if (name == null)
+ return "invoke" + type;
+ return name.getName() + type;
+ }
+
+ /*non-public*/ static String getNameString(MethodHandle target, MethodHandle typeHolder) {
+ return getNameString(target, typeHolder == null ? (MethodType) null : typeHolder.type());
+ }
+
+ /*non-public*/ static String getNameString(MethodHandle target) {
+ return getNameString(target, (MethodType) null);
+ }
+
+ /*non-public*/ static String addTypeString(Object obj, MethodHandle target) {
+ String str = String.valueOf(obj);
+ if (target == null) return str;
+ int paren = str.indexOf('(');
+ if (paren >= 0) str = str.substring(0, paren);
+ return str + target.type();
+ }
+
+ static void checkSpreadArgument(Object av, int n) {
+ if (av == null ? n != 0 : ((Object[])av).length != n)
+ throw newIllegalArgumentException("Array is not of length "+n);
+ }
+
+ // handy shared exception makers (they simplify the common case code)
+ /*non-public*/ static RuntimeException newIllegalStateException(String message) {
+ return new IllegalStateException(message);
+ }
+ /*non-public*/ static RuntimeException newIllegalStateException(String message, Object obj) {
+ return new IllegalStateException(message(message, obj));
+ }
+ /*non-public*/ static RuntimeException newIllegalArgumentException(String message) {
+ return new IllegalArgumentException(message);
+ }
+ /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj) {
+ return new IllegalArgumentException(message(message, obj));
+ }
+ /*non-public*/ static Error uncaughtException(Exception ex) {
+ Error err = new InternalError("uncaught exception");
+ err.initCause(ex);
+ return err;
+ }
+ private static String message(String message, Object obj) {
+ if (obj != null) message = message + ": " + obj;
+ return message;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,2357 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.lang.reflect.*;
+import sun.invoke.WrapperInstance;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.VerifyAccess;
+import sun.invoke.util.Wrapper;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import sun.reflect.Reflection;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * This class consists exclusively of static methods that operate on or return
+ * method handles. They fall into several categories:
+ * <ul>
+ * <li>Lookup methods which help create method handles for methods and fields.
+ * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
+ * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
+ * <li>Wrapper methods which can convert between method handles and interface types.
+ * </ul>
+ * <p>
+ * @author John Rose, JSR 292 EG
+ */
+public class MethodHandles {
+
+ private MethodHandles() { } // do not instantiate
+
+ private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
+ static { MethodHandleImpl.initStatics(); }
+ // See IMPL_LOOKUP below.
+
+ //// Method handle creation from ordinary methods.
+
+ /**
+ * Returns a {@link Lookup lookup object} on the caller,
+ * which has the capability to access any method handle that the caller has access to,
+ * including direct method handles to private fields and methods.
+ * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
+ * Do not store it in place where untrusted code can access it.
+ */
+ public static Lookup lookup() {
+ return new Lookup();
+ }
+
+ /**
+ * Returns a {@link Lookup lookup object} which is trusted minimally.
+ * It can only be used to create method handles to
+ * publicly accessible fields and methods.
+ * <p>
+ * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
+ * of this lookup object will be {@link java.lang.Object}.
+ * <p>
+ * The lookup class can be changed to any other class {@code C} using an expression of the form
+ * {@linkplain Lookup#in <code>publicLookup().in(C.class)</code>}.
+ * Since all classes have equal access to public names,
+ * such a change would confer no new access rights.
+ */
+ public static Lookup publicLookup() {
+ return Lookup.PUBLIC_LOOKUP;
+ }
+
+ /**
+ * A <em>lookup object</em> is a factory for creating method handles,
+ * when the creation requires access checking.
+ * Method handles do not perform
+ * access checks when they are called, but rather when they are created.
+ * Therefore, method handle access
+ * restrictions must be enforced when a method handle is created.
+ * The caller class against which those restrictions are enforced
+ * is known as the {@linkplain #lookupClass lookup class}.
+ * <p>
+ * A lookup class which needs to create method handles will call
+ * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
+ * When the {@code Lookup} factory object is created, the identity of the lookup class is
+ * determined, and securely stored in the {@code Lookup} object.
+ * The lookup class (or its delegates) may then use factory methods
+ * on the {@code Lookup} object to create method handles for access-checked members.
+ * This includes all methods, constructors, and fields which are allowed to the lookup class,
+ * even private ones.
+ * <p>
+ * The factory methods on a {@code Lookup} object correspond to all major
+ * use cases for methods, constructors, and fields.
+ * Here is a summary of the correspondence between these factory methods and
+ * the behavior the resulting method handles:
+ * <code>
+ * <table border=1 cellpadding=5 summary="lookup method behaviors">
+ * <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
+ * <td>FT f;</td><td>(T) this.f;</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
+ * <td>static<br>FT f;</td><td>(T) C.f;</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
+ * <td>FT f;</td><td>this.f = x;</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
+ * <td>static<br>FT f;</td><td>C.f = arg;</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
+ * <td>T m(A*);</td><td>(T) this.m(arg*);</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
+ * <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
+ * <td>T m(A*);</td><td>(T) super.m(arg*);</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
+ * <td>C(A*);</td><td>(T) new C(arg*);</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
+ * <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
+ * <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
+ * <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
+ * <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td>
+ * </tr>
+ * <tr>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
+ * <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
+ * </tr>
+ * </table>
+ * </code>
+ * Here, the type {@code C} is the class or interface being searched for a member,
+ * documented as a parameter named {@code refc} in the lookup methods.
+ * The method or constructor type {@code MT} is composed from the return type {@code T}
+ * and the sequence of argument types {@code A*}.
+ * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}.
+ * The formal parameter {@code this} stands for the self-reference of type {@code C};
+ * if it is present, it is always the leading argument to the method handle invocation.
+ * The name {@code arg} stands for all the other method handle arguments.
+ * In the code examples for the Core Reflection API, the name {@code thisOrNull}
+ * stands for a null reference if the accessed method or field is static,
+ * and {@code this} otherwise.
+ * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand
+ * for reflective objects corresponding to the given members.
+ * <p>
+ * The equivalence between looked-up method handles and underlying
+ * class members can break down in a few ways:
+ * <ul>
+ * <li>If {@code C} is not symbolically accessible from the lookup class's loader,
+ * the lookup can still succeed, even when there is no equivalent
+ * Java expression or bytecoded constant.
+ * <li>Likewise, if {@code T} or {@code MT}
+ * is not symbolically accessible from the lookup class's loader,
+ * the lookup can still succeed.
+ * For example, lookups for {@code MethodHandle.invokeExact} and
+ * {@code MethodHandle.invokeGeneric} will always succeed, regardless of requested type.
+ * <li>If there is a security manager installed, it can forbid the lookup
+ * on various grounds (<a href="#secmgr">see below</a>).
+ * By contrast, the {@code ldc} instruction is not subject to
+ * security manager checks.
+ * </ul>
+ *
+ * <h3><a name="access"></a>Access checking</h3>
+ * Access checks are applied in the factory methods of {@code Lookup},
+ * when a method handle is created.
+ * This is a key difference from the Core Reflection API, since
+ * {@link java.lang.reflect.Method#invoke Method.invoke}
+ * performs access checking against every caller, on every call.
+ * <p>
+ * All access checks start from a {@code Lookup} object, which
+ * compares its recorded lookup class against all requests to
+ * create method handles.
+ * A single {@code Lookup} object can be used to create any number
+ * of access-checked method handles, all checked against a single
+ * lookup class.
+ * <p>
+ * A {@code Lookup} object can be shared with other trusted code,
+ * such as a metaobject protocol.
+ * A shared {@code Lookup} object delegates the capability
+ * to create method handles on private members of the lookup class.
+ * Even if privileged code uses the {@code Lookup} object,
+ * the access checking is confined to the privileges of the
+ * original lookup class.
+ * <p>
+ * A lookup can fail, because
+ * the containing class is not accessible to the lookup class, or
+ * because the desired class member is missing, or because the
+ * desired class member is not accessible to the lookup class.
+ * In any of these cases, a {@code ReflectiveOperationException} will be
+ * thrown from the attempted lookup. The exact class will be one of
+ * the following:
+ * <ul>
+ * <li>NoSuchMethodException — if a method is requested but does not exist
+ * <li>NoSuchFieldException — if a field is requested but does not exist
+ * <li>IllegalAccessException — if the member exists but an access check fails
+ * </ul>
+ * <p>
+ * In general, the conditions under which a method handle may be
+ * looked up for a method {@code M} are exactly equivalent to the conditions
+ * under which the lookup class could have compiled and resolved a call to {@code M}.
+ * And the effect of invoking the method handle resulting from the lookup
+ * is exactly equivalent to executing the compiled and resolved call to {@code M}.
+ * The same point is true of fields and constructors.
+ * <p>
+ * In some cases, access between nested classes is obtained by the Java compiler by creating
+ * an wrapper method to access a private method of another class
+ * in the same top-level declaration.
+ * For example, a nested class {@code C.D}
+ * can access private members within other related classes such as
+ * {@code C}, {@code C.D.E}, or {@code C.B},
+ * but the Java compiler may need to generate wrapper methods in
+ * those related classes. In such cases, a {@code Lookup} object on
+ * {@code C.E} would be unable to those private members.
+ * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
+ * which can transform a lookup on {@code C.E} into one on any of those other
+ * classes, without special elevation of privilege.
+ * <p>
+ * Although bytecode instructions can only refer to classes in
+ * a related class loader, this API can search for methods in any
+ * class, as long as a reference to its {@code Class} object is
+ * available. Such cross-loader references are also possible with the
+ * Core Reflection API, and are impossible to bytecode instructions
+ * such as {@code invokestatic} or {@code getfield}.
+ * There is a {@linkplain java.lang.SecurityManager security manager API}
+ * to allow applications to check such cross-loader references.
+ * These checks apply to both the {@code MethodHandles.Lookup} API
+ * and the Core Reflection API
+ * (as found on {@link java.lang.Class Class}).
+ * <p>
+ * Access checks only apply to named and reflected methods,
+ * constructors, and fields.
+ * Other method handle creation methods, such as
+ * {@link #convertArguments MethodHandles.convertArguments},
+ * do not require any access checks, and are done
+ * with static methods of {@link MethodHandles},
+ * independently of any {@code Lookup} object.
+ *
+ * <h3>Security manager interactions</h3>
+ * <a name="secmgr"></a>
+ * If a security manager is present, member lookups are subject to
+ * additional checks.
+ * From one to four calls are made to the security manager.
+ * Any of these calls can refuse access by throwing a
+ * {@link java.lang.SecurityException SecurityException}.
+ * Define {@code smgr} as the security manager,
+ * {@code refc} as the containing class in which the member
+ * is being sought, and {@code defc} as the class in which the
+ * member is actually defined.
+ * The calls are made according to the following rules:
+ * <ul>
+ * <li>In all cases, {@link SecurityManager#checkMemberAccess
+ * smgr.checkMemberAccess(refc, Member.PUBLIC)} is called.
+ * <li>If the class loader of the lookup class is not
+ * the same as or an ancestor of the class loader of {@code refc},
+ * then {@link SecurityManager#checkPackageAccess
+ * smgr.checkPackageAccess(refcPkg)} is called,
+ * where {@code refcPkg} is the package of {@code refc}.
+ * <li>If the retrieved member is not public,
+ * {@link SecurityManager#checkMemberAccess
+ * smgr.checkMemberAccess(defc, Member.DECLARED)} is called.
+ * (Note that {@code defc} might be the same as {@code refc}.)
+ * <li>If the retrieved member is not public,
+ * and if {@code defc} and {@code refc} are in different class loaders,
+ * and if the class loader of the lookup class is not
+ * the same as or an ancestor of the class loader of {@code defc},
+ * then {@link SecurityManager#checkPackageAccess
+ * smgr.checkPackageAccess(defcPkg)} is called,
+ * where {@code defcPkg} is the package of {@code defc}.
+ * </ul>
+ * In all cases, the requesting class presented to the security
+ * manager will be the lookup class from the current {@code Lookup} object.
+ */
+ public static final
+ class Lookup {
+ /** The class on behalf of whom the lookup is being performed. */
+ private final Class<?> lookupClass;
+
+ /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
+ private final int allowedModes;
+
+ /** A single-bit mask representing {@code public} access,
+ * which may contribute to the result of {@link #lookupModes lookupModes}.
+ * The value, {@code 0x01}, happens to be the same as the value of the
+ * {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}.
+ */
+ public static final int PUBLIC = Modifier.PUBLIC;
+
+ /** A single-bit mask representing {@code private} access,
+ * which may contribute to the result of {@link #lookupModes lookupModes}.
+ * The value, {@code 0x02}, happens to be the same as the value of the
+ * {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}.
+ */
+ public static final int PRIVATE = Modifier.PRIVATE;
+
+ /** A single-bit mask representing {@code protected} access,
+ * which may contribute to the result of {@link #lookupModes lookupModes}.
+ * The value, {@code 0x04}, happens to be the same as the value of the
+ * {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}.
+ */
+ public static final int PROTECTED = Modifier.PROTECTED;
+
+ /** A single-bit mask representing {@code package} access (default access),
+ * which may contribute to the result of {@link #lookupModes lookupModes}.
+ * The value is {@code 0x08}, which does not correspond meaningfully to
+ * any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
+ */
+ public static final int PACKAGE = Modifier.STATIC;
+
+ private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
+ private static final int TRUSTED = -1;
+
+ private static int fixmods(int mods) {
+ mods &= (ALL_MODES - PACKAGE);
+ return (mods != 0) ? mods : PACKAGE;
+ }
+
+ /** Tells which class is performing the lookup. It is this class against
+ * which checks are performed for visibility and access permissions.
+ * <p>
+ * The class implies a maximum level of access permission,
+ * but the permissions may be additionally limited by the bitmask
+ * {@link #lookupModes lookupModes}, which controls whether non-public members
+ * can be accessed.
+ */
+ public Class<?> lookupClass() {
+ return lookupClass;
+ }
+
+ // This is just for calling out to MethodHandleImpl.
+ private Class<?> lookupClassOrNull() {
+ return (allowedModes == TRUSTED) ? null : lookupClass;
+ }
+
+ /** Tells which access-protection classes of members this lookup object can produce.
+ * The result is a bit-mask of the bits
+ * {@linkplain #PUBLIC PUBLIC (0x01)},
+ * {@linkplain #PRIVATE PRIVATE (0x02)},
+ * {@linkplain #PROTECTED PROTECTED (0x04)},
+ * and {@linkplain #PACKAGE PACKAGE (0x08)}.
+ * <p>
+ * A freshly-created lookup object
+ * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class}
+ * has all possible bits set, since the caller class can access all its own members.
+ * A lookup object on a new lookup class
+ * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
+ * may have some mode bits set to zero.
+ * The purpose of this is to restrict access via the new lookup object,
+ * so that it can access only names which can be reached by the original
+ * lookup object, and also by the new lookup class.
+ */
+ public int lookupModes() {
+ return allowedModes & ALL_MODES;
+ }
+
+ /** Embody the current class (the lookupClass) as a lookup class
+ * for method handle creation.
+ * Must be called by from a method in this package,
+ * which in turn is called by a method not in this package.
+ * <p>
+ * Also, don't make it private, lest javac interpose
+ * an access$N method.
+ */
+ Lookup() {
+ this(getCallerClassAtEntryPoint(), ALL_MODES);
+ // make sure we haven't accidentally picked up a privileged class:
+ checkUnprivilegedlookupClass(lookupClass);
+ }
+
+ Lookup(Class<?> lookupClass) {
+ this(lookupClass, ALL_MODES);
+ }
+
+ private Lookup(Class<?> lookupClass, int allowedModes) {
+ this.lookupClass = lookupClass;
+ this.allowedModes = allowedModes;
+ }
+
+ /**
+ * Creates a lookup on the specified new lookup class.
+ * The resulting object will report the specified
+ * class as its own {@link #lookupClass lookupClass}.
+ * <p>
+ * However, the resulting {@code Lookup} object is guaranteed
+ * to have no more access capabilities than the original.
+ * In particular, access capabilities can be lost as follows:<ul>
+ * <li>If the new lookup class differs from the old one,
+ * protected members will not be accessible by virtue of inheritance.
+ * (Protected members may continue to be accessible because of package sharing.)
+ * <li>If the new lookup class is in a different package
+ * than the old one, protected and default (package) members will not be accessible.
+ * <li>If the new lookup class is not within the same package member
+ * as the old one, private members will not be accessible.
+ * <li>If the new lookup class is not accessible to the old lookup class,
+ * then no members, not even public members, will be accessible.
+ * (In all other cases, public members will continue to be accessible.)
+ * </ul>
+ *
+ * @param requestedLookupClass the desired lookup class for the new lookup object
+ * @return a lookup object which reports the desired lookup class
+ * @throws NullPointerException if the argument is null
+ */
+ public Lookup in(Class<?> requestedLookupClass) {
+ requestedLookupClass.getClass(); // null check
+ if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all
+ return new Lookup(requestedLookupClass, ALL_MODES);
+ if (requestedLookupClass == this.lookupClass)
+ return this; // keep same capabilities
+ int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
+ if ((newModes & PACKAGE) != 0
+ && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
+ newModes &= ~(PACKAGE|PRIVATE);
+ }
+ // Allow nestmate lookups to be created without special privilege:
+ if ((newModes & PRIVATE) != 0
+ && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
+ newModes &= ~PRIVATE;
+ }
+ if (newModes == PUBLIC
+ && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass)) {
+ // The requested class it not accessible from the lookup class.
+ // No permissions.
+ newModes = 0;
+ }
+ checkUnprivilegedlookupClass(requestedLookupClass);
+ return new Lookup(requestedLookupClass, newModes);
+ }
+
+ // Make sure outer class is initialized first.
+ static { IMPL_NAMES.getClass(); }
+
+ /** Version of lookup which is trusted minimally.
+ * It can only be used to create method handles to
+ * publicly accessible members.
+ */
+ static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
+
+ /** Package-private version of lookup which is trusted. */
+ static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
+
+ private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
+ String name = lookupClass.getName();
+ if (name.startsWith("java.lang.invoke."))
+ throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
+ }
+
+ /**
+ * Displays the name of the class from which lookups are to be made.
+ * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.)
+ * If there are restrictions on the access permitted to this lookup,
+ * this is indicated by adding a suffix to the class name, consisting
+ * of a slash and a keyword. The keyword represents the strongest
+ * allowed access, and is chosen as follows:
+ * <ul>
+ * <li>If no access is allowed, the suffix is "/noaccess".
+ * <li>If only public access is allowed, the suffix is "/public".
+ * <li>If only public and package access are allowed, the suffix is "/package".
+ * <li>If only public, package, and private access are allowed, the suffix is "/private".
+ * </ul>
+ * If none of the above cases apply, it is the case that full
+ * access (public, package, private, and protected) is allowed.
+ * In this case, no suffix is added.
+ * This is true only of an object obtained originally from
+ * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
+ * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in}
+ * always have restricted access, and will display a suffix.
+ * <p>
+ * (It may seem strange that protected access should be
+ * stronger than private access. Viewed independently from
+ * package access, protected access is the first to be lost,
+ * because it requires a direct subclass relationship between
+ * caller and callee.)
+ * @see #in
+ */
+ @Override
+ public String toString() {
+ String cname = lookupClass.getName();
+ switch (allowedModes) {
+ case 0: // no privileges
+ return cname + "/noaccess";
+ case PUBLIC:
+ return cname + "/public";
+ case PUBLIC|PACKAGE:
+ return cname + "/package";
+ case ALL_MODES & ~PROTECTED:
+ return cname + "/private";
+ case ALL_MODES:
+ return cname;
+ case TRUSTED:
+ return "/trusted"; // internal only; not exported
+ default: // Should not happen, but it's a bitfield...
+ cname = cname + "/" + Integer.toHexString(allowedModes);
+ assert(false) : cname;
+ return cname;
+ }
+ }
+
+ // call this from an entry point method in Lookup with extraFrames=0.
+ private static Class<?> getCallerClassAtEntryPoint() {
+ final int CALLER_DEPTH = 4;
+ // 0: Reflection.getCC, 1: getCallerClassAtEntryPoint,
+ // 2: Lookup.<init>, 3: MethodHandles.*, 4: caller
+ // Note: This should be the only use of getCallerClass in this file.
+ assert(Reflection.getCallerClass(CALLER_DEPTH-1) == MethodHandles.class);
+ return Reflection.getCallerClass(CALLER_DEPTH);
+ }
+
+ /**
+ * Produces a method handle for a static method.
+ * The type of the method handle will be that of the method.
+ * (Since static methods do not take receivers, there is no
+ * additional receiver argument inserted into the method handle type,
+ * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.)
+ * The method and all its argument types must be accessible to the lookup class.
+ * If the method's class has not yet been initialized, that is done
+ * immediately, before the method handle is returned.
+ * <p>
+ * The returned method handle will have
+ * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+ * the method's variable arity modifier bit ({@code 0x0080}) is set.
+ * @param refc the class from which the method is accessed
+ * @param name the name of the method
+ * @param type the type of the method
+ * @return the desired method handle
+ * @throws NoSuchMethodException if the method does not exist
+ * @throws IllegalAccessException if access checking fails, or if the method is not {@code static}
+ * @exception SecurityException if a security manager is present and it
+ * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+ * @throws NullPointerException if any argument is null
+ */
+ public
+ MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+ MemberName method = resolveOrFail(refc, name, type, true);
+ checkMethod(refc, method, true);
+ return MethodHandleImpl.findMethod(method, false, lookupClassOrNull());
+ }
+
+ /**
+ * Produces a method handle for a virtual method.
+ * The type of the method handle will be that of the method,
+ * with the receiver type (usually {@code refc}) prepended.
+ * The method and all its argument types must be accessible to the lookup class.
+ * <p>
+ * When called, the handle will treat the first argument as a receiver
+ * and dispatch on the receiver's type to determine which method
+ * implementation to enter.
+ * (The dispatching action is identical with that performed by an
+ * {@code invokevirtual} or {@code invokeinterface} instruction.)
+ * <p>
+ * The returned method handle will have
+ * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+ * the method's variable arity modifier bit ({@code 0x0080}) is set.
+ * <p>
+ * Because of the general equivalence between {@code invokevirtual}
+ * instructions and method handles produced by {@code findVirtual},
+ * if the class is {@code MethodHandle} and the name string is
+ * {@code invokeExact} or {@code invokeGeneric}, the resulting
+ * method handle is equivalent to one produced by
+ * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
+ * {@link java.lang.invoke.MethodHandles#genericInvoker MethodHandles.genericInvoker}
+ * with the same {@code type} argument.
+ *
+ * @param refc the class or interface from which the method is accessed
+ * @param name the name of the method
+ * @param type the type of the method, with the receiver argument omitted
+ * @return the desired method handle
+ * @throws NoSuchMethodException if the method does not exist
+ * @throws IllegalAccessException if access checking fails, or if the method is {@code static}
+ * @exception SecurityException if a security manager is present and it
+ * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+ * @throws NullPointerException if any argument is null
+ */
+ public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+ MemberName method = resolveOrFail(refc, name, type, false);
+ checkMethod(refc, method, false);
+ MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
+ return restrictProtectedReceiver(method, mh);
+ }
+
+ /**
+ * Produces a method handle which creates an object and initializes it, using
+ * the constructor of the specified type.
+ * The parameter types of the method handle will be those of the constructor,
+ * while the return type will be a reference to the constructor's class.
+ * The constructor and all its argument types must be accessible to the lookup class.
+ * If the constructor's class has not yet been initialized, that is done
+ * immediately, before the method handle is returned.
+ * <p>
+ * Note: The requested type must have a return type of {@code void}.
+ * This is consistent with the JVM's treatment of constructor type descriptors.
+ * <p>
+ * The returned method handle will have
+ * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+ * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
+ * @param refc the class or interface from which the method is accessed
+ * @param type the type of the method, with the receiver argument omitted, and a void return type
+ * @return the desired method handle
+ * @throws NoSuchMethodException if the constructor does not exist
+ * @throws IllegalAccessException if access checking fails
+ * @exception SecurityException if a security manager is present and it
+ * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+ * @throws NullPointerException if any argument is null
+ */
+ public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+ String name = "<init>";
+ MemberName ctor = resolveOrFail(refc, name, type, false, false, lookupClassOrNull());
+ assert(ctor.isConstructor());
+ checkAccess(refc, ctor);
+ MethodHandle rawMH = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
+ MethodHandle allocMH = MethodHandleImpl.makeAllocator(rawMH);
+ return fixVarargs(allocMH, rawMH);
+ }
+
+ /** Return a version of MH which matches matchMH w.r.t. isVarargsCollector. */
+ private static MethodHandle fixVarargs(MethodHandle mh, MethodHandle matchMH) {
+ boolean va1 = mh.isVarargsCollector();
+ boolean va2 = matchMH.isVarargsCollector();
+ if (va1 == va2) {
+ return mh;
+ } else if (va2) {
+ MethodType type = mh.type();
+ int arity = type.parameterCount();
+ return mh.asVarargsCollector(type.parameterType(arity-1));
+ } else {
+ throw new InternalError("already varargs, but template is not: "+mh);
+ }
+ }
+
+ /**
+ * Produces an early-bound method handle for a virtual method,
+ * as if called from an {@code invokespecial}
+ * instruction from {@code caller}.
+ * The type of the method handle will be that of the method,
+ * with a suitably restricted receiver type (such as {@code caller}) prepended.
+ * The method and all its argument types must be accessible
+ * to the caller.
+ * <p>
+ * When called, the handle will treat the first argument as a receiver,
+ * but will not dispatch on the receiver's type.
+ * (This direct invocation action is identical with that performed by an
+ * {@code invokespecial} instruction.)
+ * <p>
+ * If the explicitly specified caller class is not identical with the
+ * lookup class, or if this lookup object does not have private access
+ * privileges, the access fails.
+ * <p>
+ * The returned method handle will have
+ * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+ * the method's variable arity modifier bit ({@code 0x0080}) is set.
+ * @param refc the class or interface from which the method is accessed
+ * @param name the name of the method (which must not be "<init>")
+ * @param type the type of the method, with the receiver argument omitted
+ * @param specialCaller the proposed calling class to perform the {@code invokespecial}
+ * @return the desired method handle
+ * @throws NoSuchMethodException if the method does not exist
+ * @throws IllegalAccessException if access checking fails
+ * @exception SecurityException if a security manager is present and it
+ * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+ * @throws NullPointerException if any argument is null
+ */
+ public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
+ Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
+ checkSpecialCaller(specialCaller);
+ MemberName method = resolveOrFail(refc, name, type, false, false, specialCaller);
+ checkMethod(refc, method, false);
+ MethodHandle mh = MethodHandleImpl.findMethod(method, false, specialCaller);
+ return restrictReceiver(method, mh, specialCaller);
+ }
+
+ /**
+ * Produces a method handle giving read access to a non-static field.
+ * The type of the method handle will have a return type of the field's
+ * value type.
+ * The method handle's single argument will be the instance containing
+ * the field.
+ * Access checking is performed immediately on behalf of the lookup class.
+ * @param refc the class or interface from which the method is accessed
+ * @param name the field's name
+ * @param type the field's type
+ * @return a method handle which can load values from the field
+ * @throws NoSuchFieldException if the field does not exist
+ * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
+ * @exception SecurityException if a security manager is present and it
+ * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+ * @throws NullPointerException if any argument is null
+ */
+ public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+ return makeAccessor(refc, name, type, false, false);
+ }
+
+ /**
+ * Produces a method handle giving write access to a non-static field.
+ * The type of the method handle will have a void return type.
+ * The method handle will take two arguments, the instance containing
+ * the field, and the value to be stored.
+ * The second argument will be of the field's value type.
+ * Access checking is performed immediately on behalf of the lookup class.
+ * @param refc the class or interface from which the method is accessed
+ * @param name the field's name
+ * @param type the field's type
+ * @return a method handle which can store values into the field
+ * @throws NoSuchFieldException if the field does not exist
+ * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
+ * @exception SecurityException if a security manager is present and it
+ * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+ * @throws NullPointerException if any argument is null
+ */
+ public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+ return makeAccessor(refc, name, type, false, true);
+ }
+
+ /**
+ * Produces a method handle giving read access to a static field.
+ * The type of the method handle will have a return type of the field's
+ * value type.
+ * The method handle will take no arguments.
+ * Access checking is performed immediately on behalf of the lookup class.
+ * @param refc the class or interface from which the method is accessed
+ * @param name the field's name
+ * @param type the field's type
+ * @return a method handle which can load values from the field
+ * @throws NoSuchFieldException if the field does not exist
+ * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
+ * @exception SecurityException if a security manager is present and it
+ * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+ * @throws NullPointerException if any argument is null
+ */
+ public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+ return makeAccessor(refc, name, type, true, false);
+ }
+
+ /**
+ * Produces a method handle giving write access to a static field.
+ * The type of the method handle will have a void return type.
+ * The method handle will take a single
+ * argument, of the field's value type, the value to be stored.
+ * Access checking is performed immediately on behalf of the lookup class.
+ * @param refc the class or interface from which the method is accessed
+ * @param name the field's name
+ * @param type the field's type
+ * @return a method handle which can store values into the field
+ * @throws NoSuchFieldException if the field does not exist
+ * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
+ * @exception SecurityException if a security manager is present and it
+ * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+ * @throws NullPointerException if any argument is null
+ */
+ public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+ return makeAccessor(refc, name, type, true, true);
+ }
+
+ /**
+ * Produces an early-bound method handle for a non-static method.
+ * The receiver must have a supertype {@code defc} in which a method
+ * of the given name and type is accessible to the lookup class.
+ * The method and all its argument types must be accessible to the lookup class.
+ * The type of the method handle will be that of the method,
+ * without any insertion of an additional receiver parameter.
+ * The given receiver will be bound into the method handle,
+ * so that every call to the method handle will invoke the
+ * requested method on the given receiver.
+ * <p>
+ * The returned method handle will have
+ * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+ * the method's variable arity modifier bit ({@code 0x0080}) is set
+ * <em>and</em> the trailing array argument is not the only argument.
+ * (If the trailing array argument is the only argument,
+ * the given receiver value will be bound to it.)
+ * <p>
+ * This is equivalent to the following code:
+ * <blockquote><pre>
+MethodHandle mh0 = {@link #findVirtual findVirtual}(defc, name, type);
+MethodHandle mh1 = mh0.{@link MethodHandle#bindTo bindTo}(receiver);
+MethodType mt1 = mh1.type();
+if (mh0.isVarargsCollector() && mt1.parameterCount() > 0) {
+ mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
+return mh1;
+ * </pre></blockquote>
+ * where {@code defc} is either {@code receiver.getClass()} or a super
+ * type of that class, in which the requested method is accessible
+ * to the lookup class.
+ * (Note that {@code bindTo} does not preserve variable arity.)
+ * @param receiver the object from which the method is accessed
+ * @param name the name of the method
+ * @param type the type of the method, with the receiver argument omitted
+ * @return the desired method handle
+ * @throws NoSuchMethodException if the method does not exist
+ * @throws IllegalAccessException if access checking fails
+ * @exception SecurityException if a security manager is present and it
+ * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+ * @throws NullPointerException if any argument is null
+ */
+ public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+ Class<? extends Object> refc = receiver.getClass(); // may get NPE
+ MemberName method = resolveOrFail(refc, name, type, false);
+ checkMethod(refc, method, false);
+ MethodHandle dmh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
+ MethodHandle bmh = MethodHandleImpl.bindReceiver(dmh, receiver);
+ if (bmh == null)
+ throw method.makeAccessException("no access", this);
+ if (dmh.type().parameterCount() == 0)
+ return dmh; // bound the trailing parameter; no varargs possible
+ return fixVarargs(bmh, dmh);
+ }
+
+ /**
+ * Makes a direct method handle to <i>m</i>, if the lookup class has permission.
+ * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
+ * If <i>m</i> is virtual, overriding is respected on every call.
+ * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
+ * The type of the method handle will be that of the method,
+ * with the receiver type prepended (but only if it is non-static).
+ * If the method's {@code accessible} flag is not set,
+ * access checking is performed immediately on behalf of the lookup class.
+ * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
+ * <p>
+ * The returned method handle will have
+ * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+ * the method's variable arity modifier bit ({@code 0x0080}) is set.
+ * @param m the reflected method
+ * @return a method handle which can invoke the reflected method
+ * @throws IllegalAccessException if access checking fails
+ * @throws NullPointerException if the argument is null
+ */
+ public MethodHandle unreflect(Method m) throws IllegalAccessException {
+ MemberName method = new MemberName(m);
+ assert(method.isMethod());
+ if (!m.isAccessible()) checkMethod(method.getDeclaringClass(), method, method.isStatic());
+ MethodHandle mh = MethodHandleImpl.findMethod(method, true, lookupClassOrNull());
+ if (!m.isAccessible()) mh = restrictProtectedReceiver(method, mh);
+ return mh;
+ }
+
+ /**
+ * Produces a method handle for a reflected method.
+ * It will bypass checks for overriding methods on the receiver,
+ * as if by a {@code invokespecial} instruction from within the {@code specialCaller}.
+ * The type of the method handle will be that of the method,
+ * with the special caller type prepended (and <em>not</em> the receiver of the method).
+ * If the method's {@code accessible} flag is not set,
+ * access checking is performed immediately on behalf of the lookup class,
+ * as if {@code invokespecial} instruction were being linked.
+ * <p>
+ * The returned method handle will have
+ * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+ * the method's variable arity modifier bit ({@code 0x0080}) is set.
+ * @param m the reflected method
+ * @param specialCaller the class nominally calling the method
+ * @return a method handle which can invoke the reflected method
+ * @throws IllegalAccessException if access checking fails
+ * @throws NullPointerException if any argument is null
+ */
+ public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
+ checkSpecialCaller(specialCaller);
+ MemberName method = new MemberName(m);
+ assert(method.isMethod());
+ // ignore m.isAccessible: this is a new kind of access
+ checkMethod(m.getDeclaringClass(), method, false);
+ MethodHandle mh = MethodHandleImpl.findMethod(method, false, lookupClassOrNull());
+ return restrictReceiver(method, mh, specialCaller);
+ }
+
+ /**
+ * Produces a method handle for a reflected constructor.
+ * The type of the method handle will be that of the constructor,
+ * with the return type changed to the declaring class.
+ * The method handle will perform a {@code newInstance} operation,
+ * creating a new instance of the constructor's class on the
+ * arguments passed to the method handle.
+ * <p>
+ * If the constructor's {@code accessible} flag is not set,
+ * access checking is performed immediately on behalf of the lookup class.
+ * <p>
+ * The returned method handle will have
+ * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
+ * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
+ * @param c the reflected constructor
+ * @return a method handle which can invoke the reflected constructor
+ * @throws IllegalAccessException if access checking fails
+ * @throws NullPointerException if the argument is null
+ */
+ public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException {
+ MemberName ctor = new MemberName(c);
+ assert(ctor.isConstructor());
+ if (!c.isAccessible()) checkAccess(c.getDeclaringClass(), ctor);
+ MethodHandle rawCtor = MethodHandleImpl.findMethod(ctor, false, lookupClassOrNull());
+ MethodHandle allocator = MethodHandleImpl.makeAllocator(rawCtor);
+ return fixVarargs(allocator, rawCtor);
+ }
+
+ /**
+ * Produces a method handle giving read access to a reflected field.
+ * The type of the method handle will have a return type of the field's
+ * value type.
+ * If the field is static, the method handle will take no arguments.
+ * Otherwise, its single argument will be the instance containing
+ * the field.
+ * If the field's {@code accessible} flag is not set,
+ * access checking is performed immediately on behalf of the lookup class.
+ * @param f the reflected field
+ * @return a method handle which can load values from the reflected field
+ * @throws IllegalAccessException if access checking fails
+ * @throws NullPointerException if the argument is null
+ */
+ public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
+ return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), false);
+ }
+
+ /**
+ * Produces a method handle giving write access to a reflected field.
+ * The type of the method handle will have a void return type.
+ * If the field is static, the method handle will take a single
+ * argument, of the field's value type, the value to be stored.
+ * Otherwise, the two arguments will be the instance containing
+ * the field, and the value to be stored.
+ * If the field's {@code accessible} flag is not set,
+ * access checking is performed immediately on behalf of the lookup class.
+ * @param f the reflected field
+ * @return a method handle which can store values into the reflected field
+ * @throws IllegalAccessException if access checking fails
+ * @throws NullPointerException if the argument is null
+ */
+ public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
+ return makeAccessor(f.getDeclaringClass(), new MemberName(f), f.isAccessible(), true);
+ }
+
+ /// Helper methods, all package-private.
+
+ MemberName resolveOrFail(Class<?> refc, String name, Class<?> type, boolean isStatic) throws NoSuchFieldException, IllegalAccessException {
+ checkSymbolicClass(refc); // do this before attempting to resolve
+ name.getClass(); type.getClass(); // NPE
+ int mods = (isStatic ? Modifier.STATIC : 0);
+ return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(),
+ NoSuchFieldException.class);
+ }
+
+ MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic) throws NoSuchMethodException, IllegalAccessException {
+ checkSymbolicClass(refc); // do this before attempting to resolve
+ name.getClass(); type.getClass(); // NPE
+ int mods = (isStatic ? Modifier.STATIC : 0);
+ return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), true, lookupClassOrNull(),
+ NoSuchMethodException.class);
+ }
+
+ MemberName resolveOrFail(Class<?> refc, String name, MethodType type, boolean isStatic,
+ boolean searchSupers, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
+ checkSymbolicClass(refc); // do this before attempting to resolve
+ name.getClass(); type.getClass(); // NPE
+ int mods = (isStatic ? Modifier.STATIC : 0);
+ return IMPL_NAMES.resolveOrFail(new MemberName(refc, name, type, mods), searchSupers, specialCaller,
+ NoSuchMethodException.class);
+ }
+
+ void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
+ Class<?> caller = lookupClassOrNull();
+ if (caller != null && !VerifyAccess.isClassAccessible(refc, caller))
+ throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
+ }
+
+ void checkMethod(Class<?> refc, MemberName m, boolean wantStatic) throws IllegalAccessException {
+ String message;
+ if (m.isConstructor())
+ message = "expected a method, not a constructor";
+ else if (!m.isMethod())
+ message = "expected a method";
+ else if (wantStatic != m.isStatic())
+ message = wantStatic ? "expected a static method" : "expected a non-static method";
+ else
+ { checkAccess(refc, m); return; }
+ throw m.makeAccessException(message, this);
+ }
+
+ void checkAccess(Class<?> refc, MemberName m) throws IllegalAccessException {
+ int allowedModes = this.allowedModes;
+ if (allowedModes == TRUSTED) return;
+ int mods = m.getModifiers();
+ if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
+ return; // common case
+ int requestedModes = fixmods(mods); // adjust 0 => PACKAGE
+ if ((requestedModes & allowedModes) != 0
+ && VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
+ mods, lookupClass()))
+ return;
+ if (((requestedModes & ~allowedModes) & PROTECTED) != 0
+ && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
+ // Protected members can also be checked as if they were package-private.
+ return;
+ throw m.makeAccessException(accessFailedMessage(refc, m), this);
+ }
+
+ String accessFailedMessage(Class<?> refc, MemberName m) {
+ Class<?> defc = m.getDeclaringClass();
+ int mods = m.getModifiers();
+ // check the class first:
+ boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
+ (defc == refc ||
+ Modifier.isPublic(refc.getModifiers())));
+ if (!classOK && (allowedModes & PACKAGE) != 0) {
+ classOK = (VerifyAccess.isClassAccessible(defc, lookupClass()) &&
+ (defc == refc ||
+ VerifyAccess.isClassAccessible(refc, lookupClass())));
+ }
+ if (!classOK)
+ return "class is not public";
+ if (Modifier.isPublic(mods))
+ return "access to public member failed"; // (how?)
+ if (Modifier.isPrivate(mods))
+ return "member is private";
+ if (Modifier.isProtected(mods))
+ return "member is protected";
+ return "member is private to package";
+ }
+
+ private static final boolean ALLOW_NESTMATE_ACCESS = false;
+
+ void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
+ if (allowedModes == TRUSTED) return;
+ if ((allowedModes & PRIVATE) == 0
+ || (specialCaller != lookupClass()
+ && !(ALLOW_NESTMATE_ACCESS &&
+ VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
+ throw new MemberName(specialCaller).
+ makeAccessException("no private access for invokespecial", this);
+ }
+
+ MethodHandle restrictProtectedReceiver(MemberName method, MethodHandle mh) throws IllegalAccessException {
+ // The accessing class only has the right to use a protected member
+ // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc.
+ if (!method.isProtected() || method.isStatic()
+ || allowedModes == TRUSTED
+ || method.getDeclaringClass() == lookupClass()
+ || (ALLOW_NESTMATE_ACCESS &&
+ VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
+ return mh;
+ else
+ return restrictReceiver(method, mh, lookupClass());
+ }
+ MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException {
+ assert(!method.isStatic());
+ Class<?> defc = method.getDeclaringClass(); // receiver type of mh is too wide
+ if (defc.isInterface() || !defc.isAssignableFrom(caller)) {
+ throw method.makeAccessException("caller class must be a subclass below the method", caller);
+ }
+ MethodType rawType = mh.type();
+ if (rawType.parameterType(0) == caller) return mh;
+ MethodType narrowType = rawType.changeParameterType(0, caller);
+ MethodHandle narrowMH = MethodHandleImpl.convertArguments(mh, narrowType, rawType, null);
+ return fixVarargs(narrowMH, mh);
+ }
+
+ MethodHandle makeAccessor(Class<?> refc, String name, Class<?> type,
+ boolean isStatic, boolean isSetter) throws NoSuchFieldException, IllegalAccessException {
+ MemberName field = resolveOrFail(refc, name, type, isStatic);
+ if (isStatic != field.isStatic())
+ throw field.makeAccessException(isStatic
+ ? "expected a static field"
+ : "expected a non-static field", this);
+ return makeAccessor(refc, field, false, isSetter);
+ }
+
+ MethodHandle makeAccessor(Class<?> refc, MemberName field,
+ boolean trusted, boolean isSetter) throws IllegalAccessException {
+ assert(field.isField());
+ if (trusted)
+ return MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
+ checkAccess(refc, field);
+ MethodHandle mh = MethodHandleImpl.accessField(field, isSetter, lookupClassOrNull());
+ return restrictProtectedReceiver(field, mh);
+ }
+ }
+
+ /**
+ * Produces a method handle giving read access to elements of an array.
+ * The type of the method handle will have a return type of the array's
+ * element type. Its first argument will be the array type,
+ * and the second will be {@code int}.
+ * @param arrayClass an array type
+ * @return a method handle which can load values from the given array type
+ * @throws NullPointerException if the argument is null
+ * @throws IllegalArgumentException if arrayClass is not an array type
+ */
+ public static
+ MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
+ return MethodHandleImpl.accessArrayElement(arrayClass, false);
+ }
+
+ /**
+ * Produces a method handle giving write access to elements of an array.
+ * The type of the method handle will have a void return type.
+ * Its last argument will be the array's element type.
+ * The first and second arguments will be the array type and int.
+ * @return a method handle which can store values into the array type
+ * @throws NullPointerException if the argument is null
+ * @throws IllegalArgumentException if arrayClass is not an array type
+ */
+ public static
+ MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
+ return MethodHandleImpl.accessArrayElement(arrayClass, true);
+ }
+
+ /// method handle invocation (reflective style)
+
+ /**
+ * Produces a method handle which will invoke any method handle of the
+ * given {@code type} on a standard set of {@code Object} type arguments
+ * and a single trailing {@code Object[]} array.
+ * The resulting invoker will be a method handle with the following
+ * arguments:
+ * <ul>
+ * <li>a single {@code MethodHandle} target
+ * <li>zero or more {@code Object} values (counted by {@code objectArgCount})
+ * <li>an {@code Object[]} array containing more arguments
+ * </ul>
+ * <p>
+ * The invoker will behave like a call to {@link MethodHandle#invokeGeneric invokeGeneric} with
+ * the indicated {@code type}.
+ * That is, if the target is exactly of the given {@code type}, it will behave
+ * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType}
+ * is used to convert the target to the required {@code type}.
+ * <p>
+ * The type of the returned invoker will not be the given {@code type}, but rather
+ * will have all parameter and return types replaced by {@code Object}, except for
+ * the last parameter type, which will be the array type {@code Object[]}.
+ * <p>
+ * Before invoking its target, the invoker will spread the varargs array, apply
+ * reference casts as necessary, and unbox and widen primitive arguments.
+ * The return value of the invoker will be an {@code Object} reference,
+ * boxing a primitive value if the original type returns a primitive,
+ * and always null if the original type returns void.
+ * <p>
+ * This method is equivalent to the following code (though it may be more efficient):
+ * <p><blockquote><pre>
+MethodHandle invoker = MethodHandles.genericInvoker(type);
+int spreadArgCount = type.parameterCount - objectArgCount;
+invoker = invoker.asSpreader(Object[].class, spreadArgCount);
+return invoker;
+ * </pre></blockquote>
+ * <p>
+ * This method throws no reflective or security exceptions.
+ * @param type the desired target type
+ * @param objectArgCount number of fixed (non-varargs) {@code Object} arguments
+ * @return a method handle suitable for invoking any method handle of the given type
+ */
+ static public
+ MethodHandle spreadInvoker(MethodType type, int objectArgCount) {
+ if (objectArgCount < 0 || objectArgCount > type.parameterCount())
+ throw new IllegalArgumentException("bad argument count "+objectArgCount);
+ return type.invokers().spreadInvoker(objectArgCount);
+ }
+
+ /**
+ * Produces a special <em>invoker method handle</em> which can be used to
+ * invoke any method handle of the given type, as if by {@code invokeExact}.
+ * The resulting invoker will have a type which is
+ * exactly equal to the desired type, except that it will accept
+ * an additional leading argument of type {@code MethodHandle}.
+ * <p>
+ * This method is equivalent to the following code (though it may be more efficient):
+ * <p><blockquote><pre>
+publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
+ * </pre></blockquote>
+ *
+ * <p style="font-size:smaller;">
+ * <em>Discussion:</em>
+ * Invoker method handles can be useful when working with variable method handles
+ * of unknown types.
+ * For example, to emulate an {@code invokeExact} call to a variable method
+ * handle {@code M}, extract its type {@code T},
+ * look up the invoker method {@code X} for {@code T},
+ * and call the invoker method, as {@code X.invokeGeneric(T, A...)}.
+ * (It would not work to call {@code X.invokeExact}, since the type {@code T}
+ * is unknown.)
+ * If spreading, collecting, or other argument transformations are required,
+ * they can be applied once to the invoker {@code X} and reused on many {@code M}
+ * method handle values, as long as they are compatible with the type of {@code X}.
+ * <p>
+ * <em>(Note: The invoker method is not available via the Core Reflection API.
+ * An attempt to call {@linkplain java.lang.reflect.Method#invoke Method.invoke}
+ * on the declared {@code invokeExact} or {@code invokeGeneric} method will raise an
+ * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
+ * <p>
+ * This method throws no reflective or security exceptions.
+ * @param type the desired target type
+ * @return a method handle suitable for invoking any method handle of the given type
+ */
+ static public
+ MethodHandle exactInvoker(MethodType type) {
+ return type.invokers().exactInvoker();
+ }
+
+ /**
+ * Produces a special <em>invoker method handle</em> which can be used to
+ * invoke any method handle of the given type, as if by {@code invokeGeneric}.
+ * The resulting invoker will have a type which is
+ * exactly equal to the desired type, except that it will accept
+ * an additional leading argument of type {@code MethodHandle}.
+ * <p>
+ * Before invoking its target, the invoker will apply reference casts as
+ * necessary and unbox and widen primitive arguments, as if by {@link #convertArguments convertArguments}.
+ * The return value of the invoker will be an {@code Object} reference,
+ * boxing a primitive value if the original type returns a primitive,
+ * and always null if the original type returns void.
+ * <p>
+ * This method is equivalent to the following code (though it may be more efficient):
+ * <p><blockquote><pre>
+publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
+ * </pre></blockquote>
+ * <p>
+ * This method throws no reflective or security exceptions.
+ * @param type the desired target type
+ * @return a method handle suitable for invoking any method handle convertible to the given type
+ */
+ static public
+ MethodHandle genericInvoker(MethodType type) {
+ return type.invokers().genericInvoker();
+ }
+
+ /**
+ * Perform value checking, exactly as if for an adapted method handle.
+ * It is assumed that the given value is either null, of type T0,
+ * or (if T0 is primitive) of the wrapper type corresponding to T0.
+ * The following checks and conversions are made:
+ * <ul>
+ * <li>If T0 and T1 are references, then a cast to T1 is applied.
+ * (The types do not need to be related in any particular way.)
+ * <li>If T0 and T1 are primitives, then a widening or narrowing
+ * conversion is applied, if one exists.
+ * <li>If T0 is a primitive and T1 a reference, and
+ * T0 has a wrapper type TW, a boxing conversion to TW is applied,
+ * possibly followed by a reference conversion.
+ * T1 must be TW or a supertype.
+ * <li>If T0 is a reference and T1 a primitive, and
+ * T1 has a wrapper type TW, an unboxing conversion is applied,
+ * possibly preceded by a reference conversion.
+ * T0 must be TW or a supertype.
+ * <li>If T1 is void, the return value is discarded
+ * <li>If T0 is void and T1 a reference, a null value is introduced.
+ * <li>If T0 is void and T1 a primitive, a zero value is introduced.
+ * </ul>
+ * If the value is discarded, null will be returned.
+ * @param valueType
+ * @param value
+ * @return the value, converted if necessary
+ * @throws java.lang.ClassCastException if a cast fails
+ */
+ static
+ <T0, T1> T1 checkValue(Class<T0> t0, Class<T1> t1, Object value)
+ throws ClassCastException
+ {
+ if (t0 == t1) {
+ // no conversion needed; just reassert the same type
+ if (t0.isPrimitive())
+ return Wrapper.asPrimitiveType(t1).cast(value);
+ else
+ return Wrapper.OBJECT.convert(value, t1);
+ }
+ boolean prim0 = t0.isPrimitive(), prim1 = t1.isPrimitive();
+ if (!prim0) {
+ // check contract with caller
+ Wrapper.OBJECT.convert(value, t0);
+ if (!prim1) {
+ return Wrapper.OBJECT.convert(value, t1);
+ }
+ // convert reference to primitive by unboxing
+ Wrapper w1 = Wrapper.forPrimitiveType(t1);
+ return w1.convert(value, t1);
+ }
+ // check contract with caller:
+ Wrapper.asWrapperType(t0).cast(value);
+ Wrapper w1 = Wrapper.forPrimitiveType(t1);
+ return w1.convert(value, t1);
+ }
+
+ static
+ Object checkValue(Class<?> T1, Object value)
+ throws ClassCastException
+ {
+ Class<?> T0;
+ if (value == null)
+ T0 = Object.class;
+ else
+ T0 = value.getClass();
+ return checkValue(T0, T1, value);
+ }
+
+ /// method handle modification (creation from other method handles)
+
+ /**
+ * Produces a method handle which adapts the type of the
+ * given method handle to a new type by pairwise argument conversion.
+ * The original type and new type must have the same number of arguments.
+ * The resulting method handle is guaranteed to report a type
+ * which is equal to the desired new type.
+ * <p>
+ * If the original type and new type are equal, returns target.
+ * <p>
+ * The following conversions are applied as needed both to
+ * arguments and return types. Let T0 and T1 be the differing
+ * new and old parameter types (or old and new return types)
+ * for corresponding values passed by the new and old method types.
+ * Given those types T0, T1, one of the following conversions is applied
+ * if possible:
+ * <ul>
+ * <li>If T0 and T1 are references, then a cast to T1 is applied.
+ * (The types do not need to be related in any particular way.)
+ * <li>If T0 and T1 are primitives, then a Java method invocation
+ * conversion (JLS 5.3) is applied, if one exists.
+ * <li>If T0 is a primitive and T1 a reference, a boxing
+ * conversion is applied if one exists, possibly followed by
+ * a reference conversion to a superclass.
+ * T1 must be a wrapper class or a supertype of one.
+ * <li>If T0 is a reference and T1 a primitive, an unboxing
+ * conversion will be applied at runtime, possibly followed
+ * by a Java method invocation conversion (JLS 5.3)
+ * on the primitive value. (These are the widening conversions.)
+ * T0 must be a wrapper class or a supertype of one.
+ * (In the case where T0 is Object, these are the conversions
+ * allowed by java.lang.reflect.Method.invoke.)
+ * <li>If the return type T1 is void, any returned value is discarded
+ * <li>If the return type T0 is void and T1 a reference, a null value is introduced.
+ * <li>If the return type T0 is void and T1 a primitive, a zero value is introduced.
+ * </ul>
+ * @param target the method handle to invoke after arguments are retyped
+ * @param newType the expected type of the new method handle
+ * @return a method handle which delegates to {@code target} after performing
+ * any necessary argument conversions, and arranges for any
+ * necessary return value conversions
+ * @throws NullPointerException if either argument is null
+ * @throws WrongMethodTypeException if the conversion cannot be made
+ * @see MethodHandle#asType
+ * @see MethodHandles#explicitCastArguments
+ */
+ public static
+ MethodHandle convertArguments(MethodHandle target, MethodType newType) {
+ MethodType oldType = target.type();
+ if (oldType.equals(newType))
+ return target;
+ MethodHandle res = null;
+ try {
+ res = MethodHandleImpl.convertArguments(target,
+ newType, oldType, null);
+ } catch (IllegalArgumentException ex) {
+ }
+ if (res == null)
+ throw new WrongMethodTypeException("cannot convert to "+newType+": "+target);
+ return res;
+ }
+
+ /**
+ * Produces a method handle which adapts the type of the
+ * given method handle to a new type by pairwise argument conversion.
+ * The original type and new type must have the same number of arguments.
+ * The resulting method handle is guaranteed to report a type
+ * which is equal to the desired new type.
+ * <p>
+ * If the original type and new type are equal, returns target.
+ * <p>
+ * The same conversions are allowed as for {@link #convertArguments convertArguments},
+ * and some additional conversions are also applied if those conversions fail.
+ * Given types T0, T1, one of the following conversions is applied
+ * in addition, if the conversions specified for {@code convertArguments}
+ * would be insufficient:
+ * <ul>
+ * <li>If T0 and T1 are references, and T1 is an interface type,
+ * then the value of type T0 is passed as a T1 without a cast.
+ * (This treatment of interfaces follows the usage of the bytecode verifier.)
+ * <li>If T0 and T1 are primitives and one is boolean,
+ * the boolean is treated as a one-bit unsigned integer.
+ * (This treatment follows the usage of the bytecode verifier.)
+ * A conversion from another primitive type behaves as if
+ * it first converts to byte, and then masks all but the low bit.
+ * <li>If a primitive value would be converted by {@code convertArguments}
+ * using Java method invocation conversion (JLS 5.3),
+ * Java casting conversion (JLS 5.5) may be used also.
+ * This allows primitives to be narrowed as well as widened.
+ * </ul>
+ * @param target the method handle to invoke after arguments are retyped
+ * @param newType the expected type of the new method handle
+ * @return a method handle which delegates to {@code target} after performing
+ * any necessary argument conversions, and arranges for any
+ * necessary return value conversions
+ * @throws NullPointerException if either argument is null
+ * @throws WrongMethodTypeException if the conversion cannot be made
+ * @see MethodHandle#asType
+ * @see MethodHandles#convertArguments
+ */
+ public static
+ MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
+ return convertArguments(target, newType); // FIXME!
+ }
+
+ /*
+ FIXME: Reconcile javadoc with 10/22/2010 EG notes on conversion:
+
+ Both converters arrange for their method handles to convert arguments
+ and return values. The conversion rules are the same for arguments
+ and return values, and depend only on source and target types, S and
+ T. The conversions allowed by castConvertArguments are a strict
+ superset of those performed by convertArguments.
+
+ In all cases, if S and T are references, a simple checkcast is done.
+ If neither S nor T is a primitive, no attempt is made to unbox and
+ box. A failed conversion throws ClassCastException.
+
+ If T is void, the value is dropped.
+
+ For compatibility with reflection, if S is void and T is a reference,
+ a null value is produced.
+
+ For compatibility with reflection, if S is a reference and T is a
+ primitive, S is first unboxed and then undergoes primitive conversion.
+ In the case of 'convertArguments', only assignment conversion is
+ performed (no narrowing primitive conversion).
+
+ If S is a primitive, S is boxed, and then the above rules are applied.
+ If S and T are both primitives, the boxing will be undetectable; only
+ the primitive conversions will be apparent to the user. The key point
+ is that if S is a primitive type, the implementation may box it and
+ treat is as Object, without loss of information, or it may use a "fast
+ path" which does not use boxing.
+
+ Notwithstanding the rules above, for compatibility with the verifier,
+ if T is an interface, it is treated as if it were Object. [KEEP THIS?]
+
+ Also, for compatibility with the verifier, a boolean may be undergo
+ widening or narrowing conversion to any other primitive type. [KEEP THIS?]
+ */
+
+ /**
+ * Produces a method handle which adapts the calling sequence of the
+ * given method handle to a new type, by reordering the arguments.
+ * The resulting method handle is guaranteed to report a type
+ * which is equal to the desired new type.
+ * <p>
+ * The given array controls the reordering.
+ * Call {@code #I} the number of incoming parameters (the value
+ * {@code newType.parameterCount()}, and call {@code #O} the number
+ * of outgoing parameters (the value {@code target.type().parameterCount()}).
+ * Then the length of the reordering array must be {@code #O},
+ * and each element must be a non-negative number less than {@code #I}.
+ * For every {@code N} less than {@code #O}, the {@code N}-th
+ * outgoing argument will be taken from the {@code I}-th incoming
+ * argument, where {@code I} is {@code reorder[N]}.
+ * <p>
+ * No argument or return value conversions are applied.
+ * The type of each incoming argument, as determined by {@code newType},
+ * must be identical to the type of the corresponding outgoing argument
+ * or arguments in the target method handle.
+ * The return type of {@code newType} must be identical to the return
+ * type of the original target.
+ * <p>
+ * The reordering array need not specify an actual permutation.
+ * An incoming argument will be duplicated if its index appears
+ * more than once in the array, and an incoming argument will be dropped
+ * if its index does not appear in the array.
+ * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
+ * incoming arguments which are not mentioned in the reordering array
+ * are may be any type, as determined only by {@code newType}.
+ * <blockquote><pre>
+MethodType intfn1 = MethodType.methodType(int.class, int.class);
+MethodType intfn2 = MethodType.methodType(int.class, int.class, int.class);
+MethodHandle sub = ... {int x, int y => x-y} ...;
+assert(sub.type().equals(intfn2));
+MethodHandle sub1 = MethodHandles.permuteArguments(sub, intfn2, 0, 1);
+MethodHandle rsub = MethodHandles.permuteArguments(sub, intfn2, 1, 0);
+assert((int)rsub.invokeExact(1, 100) == 99);
+MethodHandle add = ... {int x, int y => x+y} ...;
+assert(add.type().equals(intfn2));
+MethodHandle twice = MethodHandles.permuteArguments(add, intfn1, 0, 0);
+assert(twice.type().equals(intfn1));
+assert((int)twice.invokeExact(21) == 42);
+ * </pre></blockquote>
+ * @param target the method handle to invoke after arguments are reordered
+ * @param newType the expected type of the new method handle
+ * @param reorder a string which controls the reordering
+ * @return a method handle which delegates to {@code target} after it
+ * drops unused arguments and moves and/or duplicates the other arguments
+ * @throws NullPointerException if any argument is null
+ */
+ public static
+ MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
+ MethodType oldType = target.type();
+ checkReorder(reorder, newType, oldType);
+ return MethodHandleImpl.convertArguments(target,
+ newType, oldType,
+ reorder);
+ }
+
+ private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
+ if (reorder.length == oldType.parameterCount()) {
+ int limit = newType.parameterCount();
+ boolean bad = false;
+ for (int i : reorder) {
+ if (i < 0 || i >= limit) {
+ bad = true; break;
+ }
+ }
+ if (!bad) return;
+ }
+ throw newIllegalArgumentException("bad reorder array");
+ }
+
+ /**
+ * Equivalent to the following code:
+ * <p><blockquote><pre>
+ * int spreadPos = newType.parameterCount() - 1;
+ * Class<?> spreadType = newType.parameterType(spreadPos);
+ * int spreadCount = target.type().parameterCount() - spreadPos;
+ * MethodHandle adapter = target.asSpreader(spreadType, spreadCount);
+ * adapter = adapter.asType(newType);
+ * return adapter;
+ * </pre></blockquote>
+ * @param target the method handle to invoke after argument spreading
+ * @param newType the expected type of the new method handle
+ * @return a method handle which spreads its final argument,
+ * before calling the original method handle
+ */
+ /*non-public*/ static
+ MethodHandle spreadArguments(MethodHandle target, MethodType newType) {
+ MethodType oldType = target.type();
+ int inargs = newType.parameterCount();
+ int outargs = oldType.parameterCount();
+ int spreadPos = inargs - 1;
+ int numSpread = (outargs - spreadPos);
+ MethodHandle res = null;
+ if (spreadPos >= 0 && numSpread >= 0) {
+ res = MethodHandleImpl.spreadArguments(target, newType, spreadPos);
+ }
+ if (res == null) {
+ throw newIllegalArgumentException("cannot spread "+newType+" to " +oldType);
+ }
+ return res;
+ }
+
+ /**
+ * Equivalent to the following code:
+ * <p><blockquote><pre>
+ * int collectPos = target.type().parameterCount() - 1;
+ * Class<?> collectType = target.type().parameterType(collectPos);
+ * if (!collectType.isArray()) collectType = Object[].class;
+ * int collectCount = newType.parameterCount() - collectPos;
+ * MethodHandle adapter = target.asCollector(collectType, collectCount);
+ * adapter = adapter.asType(newType);
+ * return adapter;
+ * </pre></blockquote>
+ * @param target the method handle to invoke after argument collection
+ * @param newType the expected type of the new method handle
+ * @return a method handle which collects some trailing argument
+ * into an array, before calling the original method handle
+ */
+ /*non-public*/ static
+ MethodHandle collectArguments(MethodHandle target, MethodType newType) {
+ MethodType oldType = target.type();
+ int inargs = newType.parameterCount();
+ int outargs = oldType.parameterCount();
+ int collectPos = outargs - 1;
+ int numCollect = (inargs - collectPos);
+ if (collectPos < 0 || numCollect < 0)
+ throw newIllegalArgumentException("wrong number of arguments");
+ MethodHandle res = MethodHandleImpl.collectArguments(target, newType, collectPos, null);
+ if (res == null) {
+ throw newIllegalArgumentException("cannot collect from "+newType+" to " +oldType);
+ }
+ return res;
+ }
+
+ /**
+ * Produces a method handle of the requested return type which returns the given
+ * constant value every time it is invoked.
+ * <p>
+ * Before the method handle is returned, the passed-in value is converted to the requested type.
+ * If the requested type is primitive, widening primitive conversions are attempted,
+ * else reference conversions are attempted.
+ * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)},
+ * unless the type is {@code void}, in which case it is {@code identity(type)}.
+ * @param type the return type of the desired method handle
+ * @param value the value to return
+ * @return a method handle of the given return type and no arguments, which always returns the given value
+ * @throws NullPointerException if the {@code type} argument is null
+ * @throws ClassCastException if the value cannot be converted to the required return type
+ * @throws IllegalArgumentException if the given type is {@code void.class}
+ */
+ public static
+ MethodHandle constant(Class<?> type, Object value) {
+ if (type.isPrimitive()) {
+ if (type == void.class)
+ throw newIllegalArgumentException("void type");
+ Wrapper w = Wrapper.forPrimitiveType(type);
+ return identity(type).bindTo(w.convert(value, type));
+ } else {
+ return identity(type).bindTo(type.cast(value));
+ }
+ }
+
+ /**
+ * Produces a method handle which returns its sole argument when invoked.
+ * <p>The identity function for {@code void} takes no arguments and returns no values.
+ * @param type the type of the sole parameter and return value of the desired method handle
+ * @return a unary method handle which accepts and returns the given type
+ * @throws NullPointerException if the argument is null
+ * @throws IllegalArgumentException if the given type is {@code void.class}
+ */
+ public static
+ MethodHandle identity(Class<?> type) {
+ if (type == void.class)
+ throw newIllegalArgumentException("void type");
+ else if (type == Object.class)
+ return ValueConversions.identity();
+ else if (type.isPrimitive())
+ return ValueConversions.identity(Wrapper.forPrimitiveType(type));
+ else
+ return AdapterMethodHandle.makeRetypeRaw(
+ MethodType.methodType(type, type), ValueConversions.identity());
+ }
+
+ /**
+ * Produces a method handle which calls the original method handle {@code target},
+ * after inserting the given argument(s) at the given position.
+ * The formal parameters to {@code target} which will be supplied by those
+ * arguments are called <em>bound parameters</em>, because the new method
+ * will contain bindings for those parameters take from {@code values}.
+ * The type of the new method handle will drop the types for the bound
+ * parameters from the original target type, since the new method handle
+ * will no longer require those arguments to be supplied by its callers.
+ * <p>
+ * Each given argument object must match the corresponding bound parameter type.
+ * If a bound parameter type is a primitive, the argument object
+ * must be a wrapper, and will be unboxed to produce the primitive value.
+ * <p>
+ * The <i>pos</i> may range between zero and <i>N</i> (inclusively),
+ * where <i>N</i> is the number of argument types in resulting method handle
+ * (after bound parameter types are dropped).
+ * @param target the method handle to invoke after the argument is inserted
+ * @param pos where to insert the argument (zero for the first)
+ * @param values the series of arguments to insert
+ * @return a method handle which inserts an additional argument,
+ * before calling the original method handle
+ * @throws NullPointerException if the {@code target} argument or the {@code values} array is null
+ * @see MethodHandle#bindTo
+ */
+ public static
+ MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
+ int insCount = values.length;
+ MethodType oldType = target.type();
+ int outargs = oldType.parameterCount();
+ int inargs = outargs - insCount;
+ if (inargs < 0)
+ throw newIllegalArgumentException("too many values to insert");
+ if (pos < 0 || pos > inargs)
+ throw newIllegalArgumentException("no argument type to append");
+ MethodHandle result = target;
+ for (int i = 0; i < insCount; i++) {
+ Object value = values[i];
+ Class<?> valueType = oldType.parameterType(pos+i);
+ value = checkValue(valueType, value);
+ if (pos == 0 && !valueType.isPrimitive()) {
+ // At least for now, make bound method handles a special case.
+ MethodHandle bmh = MethodHandleImpl.bindReceiver(result, value);
+ if (bmh != null) {
+ result = bmh;
+ continue;
+ }
+ // else fall through to general adapter machinery
+ }
+ result = MethodHandleImpl.bindArgument(result, pos, value);
+ }
+ return result;
+ }
+
+ /**
+ * Produces a method handle which calls the original method handle,
+ * after dropping the given argument(s) at the given position.
+ * The type of the new method handle will insert the given argument
+ * type(s), at that position, into the original handle's type.
+ * <p>
+ * The <i>pos</i> may range between zero and <i>N</i>,
+ * where <i>N</i> is the number of argument types in <i>target</i>,
+ * meaning to drop the first or last argument (respectively),
+ * or an argument somewhere in between.
+ * <p>
+ * <b>Example:</b>
+ * <p><blockquote><pre>
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
+MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
+assertEquals(bigType, d0.type());
+assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
+ * </pre></blockquote>
+ * <p>
+ * This method is also equivalent to the following code:
+ * <p><blockquote><pre>
+ * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}(target, pos, valueTypes.toArray(new Class[0]))
+ * </pre></blockquote>
+ * @param target the method handle to invoke after the arguments are dropped
+ * @param valueTypes the type(s) of the argument(s) to drop
+ * @param pos position of first argument to drop (zero for the leftmost)
+ * @return a method handle which drops arguments of the given types,
+ * before calling the original method handle
+ * @throws NullPointerException if the {@code target} argument is null,
+ * or if the {@code valueTypes} list or any of its elements is null
+ * @throws IllegalArgumentException if any of the {@code valueTypes} is {@code void.class}
+ */
+ public static
+ MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
+ if (valueTypes.size() == 0) return target;
+ MethodType oldType = target.type();
+ int outargs = oldType.parameterCount();
+ int inargs = outargs + valueTypes.size();
+ if (pos < 0 || pos >= inargs)
+ throw newIllegalArgumentException("no argument type to remove");
+ ArrayList<Class<?>> ptypes =
+ new ArrayList<Class<?>>(oldType.parameterList());
+ ptypes.addAll(pos, valueTypes);
+ MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
+ return MethodHandleImpl.dropArguments(target, newType, pos);
+ }
+
+ /**
+ * Produces a method handle which calls the original method handle,
+ * after dropping the given argument(s) at the given position.
+ * The type of the new method handle will insert the given argument
+ * type(s), at that position, into the original handle's type.
+ * <p>
+ * The <i>pos</i> may range between zero and <i>N</i>,
+ * where <i>N</i> is the number of argument types in <i>target</i>,
+ * meaning to drop the first or last argument (respectively),
+ * or an argument somewhere in between.
+ * <p>
+ * <b>Example:</b>
+ * <p><blockquote><pre>
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle d0 = dropArguments(cat, 0, String.class);
+assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
+MethodHandle d1 = dropArguments(cat, 1, String.class);
+assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
+MethodHandle d2 = dropArguments(cat, 2, String.class);
+assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
+MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
+ * </pre></blockquote>
+ * <p>
+ * This method is also equivalent to the following code:
+ * <p><blockquote><pre>
+ * {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
+ * </pre></blockquote>
+ * @param target the method handle to invoke after the arguments are dropped
+ * @param valueTypes the type(s) of the argument(s) to drop
+ * @param pos position of first argument to drop (zero for the leftmost)
+ * @return a method handle which drops arguments of the given types,
+ * before calling the original method handle
+ * @throws NullPointerException if the {@code target} argument is null,
+ * or if the {@code valueTypes} array or any of its elements is null
+ * @throws IllegalArgumentException if any of the {@code valueTypes} is {@code void.class}
+ */
+ public static
+ MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
+ return dropArguments(target, pos, Arrays.asList(valueTypes));
+ }
+
+ /**
+ * Adapts a target method handle {@code target} by pre-processing
+ * one or more of its arguments, each with its own unary filter function,
+ * and then calling the target with each pre-processed argument
+ * replaced by the result of its corresponding filter function.
+ * <p>
+ * The pre-processing is performed by one or more method handles,
+ * specified in the elements of the {@code filters} array.
+ * Null arguments in the array are ignored, and the corresponding arguments left unchanged.
+ * (If there are no non-null elements in the array, the original target is returned.)
+ * Each filter is applied to the corresponding argument of the adapter.
+ * <p>
+ * If a filter {@code F} applies to the {@code N}th argument of
+ * the method handle, then {@code F} must be a method handle which
+ * takes exactly one argument. The type of {@code F}'s sole argument
+ * replaces the corresponding argument type of the target
+ * in the resulting adapted method handle.
+ * The return type of {@code F} must be identical to the corresponding
+ * parameter type of the target.
+ * <p>
+ * It is an error if there are elements of {@code filters}
+ * which do not correspond to argument positions in the target.
+ * <b>Example:</b>
+ * <p><blockquote><pre>
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+MethodHandle upcase = lookup().findVirtual(String.class,
+ "toUpperCase", methodType(String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle f0 = filterArguments(cat, 0, upcase);
+assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
+MethodHandle f1 = filterArguments(cat, 1, upcase);
+assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
+MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
+assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
+ * </pre></blockquote>
+ *
+ * @param target the method handle to invoke after arguments are filtered
+ * @param pos the position of the first argument to filter
+ * @param filters method handles to call initially on filtered arguments
+ * @return method handle which incorporates the specified argument filtering logic
+ * @throws NullPointerException if the {@code target} argument is null
+ * or if the {@code filters} array is null
+ * @throws IllegalArgumentException if a non-null element of {@code filters}
+ * does not match a corresponding argument type of {@code target} as described above,
+ * or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()}
+ */
+ public static
+ MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
+ MethodType targetType = target.type();
+ MethodHandle adapter = target;
+ MethodType adapterType = targetType;
+ int maxPos = targetType.parameterCount();
+ if (pos + filters.length > maxPos)
+ throw newIllegalArgumentException("too many filters");
+ int curPos = pos-1; // pre-incremented
+ for (MethodHandle filter : filters) {
+ curPos += 1;
+ if (filter == null) continue; // ignore null elements of filters
+ MethodType filterType = filter.type();
+ if (filterType.parameterCount() != 1
+ || filterType.returnType() != targetType.parameterType(curPos))
+ throw newIllegalArgumentException("target and filter types do not match");
+ adapterType = adapterType.changeParameterType(curPos, filterType.parameterType(0));
+ adapter = MethodHandleImpl.filterArgument(adapter, curPos, filter);
+ }
+ MethodType midType = adapter.type();
+ if (midType != adapterType)
+ adapter = MethodHandleImpl.convertArguments(adapter, adapterType, midType, null);
+ return adapter;
+ }
+
+ /**
+ * Adapts a target method handle {@code target} by post-processing
+ * its return value with a unary filter function.
+ * <p>
+ * If a filter {@code F} applies to the return value of
+ * the target method handle, then {@code F} must be a method handle which
+ * takes exactly one argument. The return type of {@code F}
+ * replaces the return type of the target
+ * in the resulting adapted method handle.
+ * The argument type of {@code F} must be identical to the
+ * return type of the target.
+ * <b>Example:</b>
+ * <p><blockquote><pre>
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+...
+MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+MethodHandle length = lookup().findVirtual(String.class,
+ "length", methodType(int.class));
+System.out.println((String) cat.invokeExact("x", "y")); // xy
+MethodHandle f0 = filterReturnValue(cat, length);
+System.out.println((int) f0.invokeExact("x", "y")); // 2
+ * </pre></blockquote>
+ * @param target the method handle to invoke before filtering the return value
+ * @param filter method handle to call on the return value
+ * @return method handle which incorporates the specified return value filtering logic
+ * @throws NullPointerException if either argument is null
+ * @throws IllegalArgumentException if {@code filter}
+ * does not match the return type of {@code target} as described above
+ */
+ public static
+ MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
+ MethodType targetType = target.type();
+ MethodType filterType = filter.type();
+ if (filterType.parameterCount() != 1
+ || filterType.parameterType(0) != targetType.returnType())
+ throw newIllegalArgumentException("target and filter types do not match");
+ // result = fold( lambda(retval, arg...) { filter(retval) },
+ // lambda( arg...) { target(arg...) } )
+ // FIXME: Too many nodes here.
+ MethodHandle returner = dropArguments(filter, 1, targetType.parameterList());
+ return foldArguments(returner, target);
+ }
+
+ /**
+ * Adapts a target method handle {@code target} by pre-processing
+ * some of its arguments, and then calling the target with
+ * the result of the pre-processing, plus all original arguments.
+ * <p>
+ * The pre-processing is performed by a second method handle, the {@code combiner}.
+ * The first {@code N} arguments passed to the adapter,
+ * are copied to the combiner, which then produces a result.
+ * (Here, {@code N} is defined as the parameter count of the adapter.)
+ * After this, control passes to the {@code target}, with both the result
+ * of the combiner, and all the original incoming arguments.
+ * <p>
+ * The first argument type of the target must be identical with the
+ * return type of the combiner.
+ * The resulting adapter is the same type as the target, except that the
+ * initial argument type of the target is dropped.
+ * <p>
+ * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments
+ * that either the {@code combiner} or {@code target} does not wish to receive.
+ * If some of the incoming arguments are destined only for the combiner,
+ * consider using {@link MethodHandle#asCollector asCollector} instead, since those
+ * arguments will not need to be live on the stack on entry to the
+ * target.)
+ * <p>
+ * The first argument of the target must be identical with the
+ * return value of the combiner.
+ * <p> Here is pseudocode for the resulting adapter:
+ * <blockquote><pre>
+ * // there are N arguments in the A sequence
+ * T target(V, A[N]..., B...);
+ * V combiner(A...);
+ * T adapter(A... a, B... b) {
+ * V v = combiner(a...);
+ * return target(v, a..., b...);
+ * }
+ * </pre></blockquote>
+ * @param target the method handle to invoke after arguments are combined
+ * @param combiner method handle to call initially on the incoming arguments
+ * @return method handle which incorporates the specified argument folding logic
+ * @throws NullPointerException if either argument is null
+ * @throws IllegalArgumentException if the first argument type of
+ * {@code target} is not the same as {@code combiner}'s return type,
+ * or if the following argument types of {@code target}
+ * are not identical with the argument types of {@code combiner}
+ */
+ public static
+ MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
+ MethodType targetType = target.type();
+ MethodType combinerType = combiner.type();
+ int foldArgs = combinerType.parameterCount();
+ boolean ok = (targetType.parameterCount() >= 1 + foldArgs);
+ if (ok && !combinerType.parameterList().equals(targetType.parameterList().subList(1, foldArgs+1)))
+ ok = false;
+ if (ok && !combinerType.returnType().equals(targetType.parameterType(0)))
+ ok = false;
+ if (!ok)
+ throw misMatchedTypes("target and combiner types", targetType, combinerType);
+ MethodType newType = targetType.dropParameterTypes(0, 1);
+ return MethodHandleImpl.foldArguments(target, newType, combiner);
+ }
+
+ /**
+ * Makes a method handle which adapts a target method handle,
+ * by guarding it with a test, a boolean-valued method handle.
+ * If the guard fails, a fallback handle is called instead.
+ * All three method handles must have the same corresponding
+ * argument and return types, except that the return type
+ * of the test must be boolean, and the test is allowed
+ * to have fewer arguments than the other two method handles.
+ * <p> Here is pseudocode for the resulting adapter:
+ * <blockquote><pre>
+ * boolean test(A...);
+ * T target(A...,B...);
+ * T fallback(A...,B...);
+ * T adapter(A... a,B... b) {
+ * if (test(a...))
+ * return target(a..., b...);
+ * else
+ * return fallback(a..., b...);
+ * }
+ * </pre></blockquote>
+ * Note that the test arguments ({@code a...} in the pseudocode) cannot
+ * be modified by execution of the test, and so are passed unchanged
+ * from the caller to the target or fallback as appropriate.
+ * @param test method handle used for test, must return boolean
+ * @param target method handle to call if test passes
+ * @param fallback method handle to call if test fails
+ * @return method handle which incorporates the specified if/then/else logic
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if {@code test} does not return boolean,
+ * or if all three method types do not match (with the return
+ * type of {@code test} changed to match that of {@code target}).
+ */
+ public static
+ MethodHandle guardWithTest(MethodHandle test,
+ MethodHandle target,
+ MethodHandle fallback) {
+ MethodType gtype = test.type();
+ MethodType ttype = target.type();
+ MethodType ftype = fallback.type();
+ if (!ttype.equals(ftype))
+ throw misMatchedTypes("target and fallback types", ttype, ftype);
+ if (gtype.returnType() != boolean.class)
+ throw newIllegalArgumentException("guard type is not a predicate "+gtype);
+ List<Class<?>> targs = ttype.parameterList();
+ List<Class<?>> gargs = gtype.parameterList();
+ if (!targs.equals(gargs)) {
+ int gpc = gargs.size(), tpc = targs.size();
+ if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
+ throw misMatchedTypes("target and test types", ttype, gtype);
+ test = dropArguments(test, gpc, targs.subList(gpc, tpc));
+ gtype = test.type();
+ }
+ return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
+ }
+
+ static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
+ return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
+ }
+
+ /**
+ * Makes a method handle which adapts a target method handle,
+ * by running it inside an exception handler.
+ * If the target returns normally, the adapter returns that value.
+ * If an exception matching the specified type is thrown, the fallback
+ * handle is called instead on the exception, plus the original arguments.
+ * <p>
+ * The target and handler must have the same corresponding
+ * argument and return types, except that handler may omit trailing arguments
+ * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
+ * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
+ * <p> Here is pseudocode for the resulting adapter:
+ * <blockquote><pre>
+ * T target(A..., B...);
+ * T handler(ExType, A...);
+ * T adapter(A... a, B... b) {
+ * try {
+ * return target(a..., b...);
+ * } catch (ExType ex) {
+ * return handler(ex, a...);
+ * }
+ * }
+ * </pre></blockquote>
+ * Note that the saved arguments ({@code a...} in the pseudocode) cannot
+ * be modified by execution of the target, and so are passed unchanged
+ * from the caller to the handler, if the handler is invoked.
+ * <p>
+ * The target and handler must return the same type, even if the handler
+ * always throws. (This might happen, for instance, because the handler
+ * is simulating a {@code finally} clause).
+ * To create such a throwing handler, compose the handler creation logic
+ * with {@link #throwException throwException},
+ * in order to create a method handle of the correct return type.
+ * @param target method handle to call
+ * @param exType the type of exception which the handler will catch
+ * @param handler method handle to call if a matching exception is thrown
+ * @return method handle which incorporates the specified try/catch logic
+ * @throws NullPointerException if any argument is null
+ * @throws IllegalArgumentException if {@code handler} does not accept
+ * the given exception type, or if the method handle types do
+ * not match in their return types and their
+ * corresponding parameters
+ */
+ public static
+ MethodHandle catchException(MethodHandle target,
+ Class<? extends Throwable> exType,
+ MethodHandle handler) {
+ MethodType ttype = target.type();
+ MethodType htype = handler.type();
+ if (htype.parameterCount() < 1 ||
+ !htype.parameterType(0).isAssignableFrom(exType))
+ throw newIllegalArgumentException("handler does not accept exception type "+exType);
+ if (htype.returnType() != ttype.returnType())
+ throw misMatchedTypes("target and handler return types", ttype, htype);
+ List<Class<?>> targs = ttype.parameterList();
+ List<Class<?>> hargs = htype.parameterList();
+ hargs = hargs.subList(1, hargs.size()); // omit leading parameter from handler
+ if (!targs.equals(hargs)) {
+ int hpc = hargs.size(), tpc = targs.size();
+ if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
+ throw misMatchedTypes("target and handler types", ttype, htype);
+ handler = dropArguments(handler, hpc, hargs.subList(hpc, tpc));
+ htype = handler.type();
+ }
+ return MethodHandleImpl.makeGuardWithCatch(target, exType, handler);
+ }
+
+ /**
+ * Produces a method handle which will throw exceptions of the given {@code exType}.
+ * The method handle will accept a single argument of {@code exType},
+ * and immediately throw it as an exception.
+ * The method type will nominally specify a return of {@code returnType}.
+ * The return type may be anything convenient: It doesn't matter to the
+ * method handle's behavior, since it will never return normally.
+ * @return method handle which can throw the given exceptions
+ * @throws NullPointerException if either argument is null
+ */
+ public static
+ MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
+ return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType));
+ }
+
+ /**
+ * Produces an instance of the given single-method interface which redirects
+ * its calls to the given method handle.
+ * <p>
+ * A single-method interface is an interface which declares a unique method.
+ * When determining the unique method of a single-method interface,
+ * the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
+ * are disregarded. For example, {@link java.util.Comparator} is a single-method interface,
+ * even though it re-declares the {@code Object.equals} method.
+ * <p>
+ * The type must be public. No additional access checks are performed.
+ * <p>
+ * The resulting instance of the required type will respond to
+ * invocation of the type's single abstract method by calling
+ * the given {@code target} on the incoming arguments,
+ * and returning or throwing whatever the {@code target}
+ * returns or throws. The invocation will be as if by
+ * {@code target.invokeGeneric}.
+ * The target's type will be checked before the
+ * instance is created, as if by a call to {@code asType},
+ * which may result in a {@code WrongMethodTypeException}.
+ * <p>
+ * The wrapper instance will implement the requested interface
+ * and its super-types, but no other single-method interfaces.
+ * This means that the instance will not unexpectedly
+ * pass an {@code instanceof} test for any unrequested type.
+ * <p style="font-size:smaller;">
+ * <em>Implementation Note:</em>
+ * Therefore, each instance must implement a unique single-method interface.
+ * Implementations may not bundle together
+ * multiple single-method interfaces onto single implementation classes
+ * in the style of {@link java.awt.AWTEventMulticaster}.
+ * <p>
+ * The method handle may throw an <em>undeclared exception</em>,
+ * which means any checked exception (or other checked throwable)
+ * not declared by the requested type's single abstract method.
+ * If this happens, the throwable will be wrapped in an instance of
+ * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
+ * and thrown in that wrapped form.
+ * <p>
+ * Like {@link java.lang.Integer#valueOf Integer.valueOf},
+ * {@code asInstance} is a factory method whose results are defined
+ * by their behavior.
+ * It is not guaranteed to return a new instance for every call.
+ * <p>
+ * Because of the possibility of {@linkplain java.lang.reflect.Method#isBridge bridge methods}
+ * and other corner cases, the interface may also have several abstract methods
+ * with the same name but having distinct descriptors (types of returns and parameters).
+ * In this case, all the methods are bound in common to the one given {@code target}.
+ * The type check and effective {@code asType} conversion is applied to each
+ * method type descriptor, and all abstract methods are bound to the {@code target} in common.
+ * Beyond this type check, no further checks are made to determine that the
+ * abstract methods are related in any way.
+ * <p>
+ * Future versions of this API may accept additional types,
+ * such as abstract classes with single abstract methods.
+ * Future versions of this API may also equip wrapper instances
+ * with one or more additional public "marker" interfaces.
+ *
+ * @param target the method handle to invoke from the wrapper
+ * @param smType the desired type of the wrapper, a single-method interface
+ * @return a correctly-typed wrapper for the given {@code target}
+ * @throws NullPointerException if either argument is null
+ * @throws IllegalArgumentException if the {@code smType} is not a
+ * valid argument to this method
+ * @throws WrongMethodTypeException if the {@code target} cannot
+ * be converted to the type required by the requested interface
+ */
+ // Other notes to implementors:
+ // <p>
+ // No stable mapping is promised between the single-method interface and
+ // the implementation class C. Over time, several implementation
+ // classes might be used for the same type.
+ // <p>
+ // If the implementation is able
+ // to prove that a wrapper of the required type
+ // has already been created for a given
+ // method handle, or for another method handle with the
+ // same behavior, the implementation may return that wrapper in place of
+ // a new wrapper.
+ // <p>
+ // This method is designed to apply to common use cases
+ // where a single method handle must interoperate with
+ // an interface that implements a function-like
+ // API. Additional variations, such as single-abstract-method classes with
+ // private constructors, or interfaces with multiple but related
+ // entry points, must be covered by hand-written or automatically
+ // generated adapter classes.
+ //
+ public static
+ <T> T asInstance(final MethodHandle target, final Class<T> smType) {
+ // POC implementation only; violates the above contract several ways
+ final Method sm = getSingleMethod(smType);
+ if (sm == null)
+ throw new IllegalArgumentException("not a single-method interface: "+smType.getName());
+ MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
+ MethodHandle checkTarget = target.asType(smMT); // make throw WMT
+ checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
+ final MethodHandle vaTarget = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
+ return smType.cast(Proxy.newProxyInstance(
+ smType.getClassLoader(),
+ new Class[]{ smType, WrapperInstance.class },
+ new InvocationHandler() {
+ private Object getArg(String name) {
+ if ((Object)name == "getWrapperInstanceTarget") return target;
+ if ((Object)name == "getWrapperInstanceType") return smType;
+ throw new AssertionError();
+ }
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (method.getDeclaringClass() == WrapperInstance.class)
+ return getArg(method.getName());
+ if (method.equals(sm))
+ return vaTarget.invokeExact(args);
+ if (isObjectMethod(method))
+ return callObjectMethod(this, method, args);
+ throw new InternalError();
+ }
+ }));
+ }
+
+ /**
+ * Determines if the given object was produced by a call to {@link #asInstance asInstance}.
+ * @param x any reference
+ * @return true if the reference is not null and points to an object produced by {@code asInstance}
+ */
+ public static
+ boolean isWrapperInstance(Object x) {
+ return x instanceof WrapperInstance;
+ }
+
+ private static WrapperInstance asWrapperInstance(Object x) {
+ try {
+ if (x != null)
+ return (WrapperInstance) x;
+ } catch (ClassCastException ex) {
+ }
+ throw new IllegalArgumentException("not a wrapper instance");
+ }
+
+ /**
+ * Produces or recovers a target method handle which is behaviorally
+ * equivalent to the unique method of this wrapper instance.
+ * The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
+ * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
+ * @param x any reference
+ * @return a method handle implementing the unique method
+ * @throws IllegalArgumentException if the reference x is not to a wrapper instance
+ */
+ public static
+ MethodHandle wrapperInstanceTarget(Object x) {
+ return asWrapperInstance(x).getWrapperInstanceTarget();
+ }
+
+ /**
+ * Recovers the unique single-method interface type for which this wrapper instance was created.
+ * The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
+ * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
+ * @param x any reference
+ * @return the single-method interface type for which the wrapper was created
+ * @throws IllegalArgumentException if the reference x is not to a wrapper instance
+ */
+ public static
+ Class<?> wrapperInstanceType(Object x) {
+ return asWrapperInstance(x).getWrapperInstanceType();
+ }
+
+ private static
+ boolean isObjectMethod(Method m) {
+ switch (m.getName()) {
+ case "toString":
+ return (m.getReturnType() == String.class
+ && m.getParameterTypes().length == 0);
+ case "hashCode":
+ return (m.getReturnType() == int.class
+ && m.getParameterTypes().length == 0);
+ case "equals":
+ return (m.getReturnType() == boolean.class
+ && m.getParameterTypes().length == 1
+ && m.getParameterTypes()[0] == Object.class);
+ }
+ return false;
+ }
+
+ private static
+ Object callObjectMethod(Object self, Method m, Object[] args) {
+ assert(isObjectMethod(m)) : m;
+ switch (m.getName()) {
+ case "toString":
+ return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
+ case "hashCode":
+ return System.identityHashCode(self);
+ case "equals":
+ return (self == args[0]);
+ }
+ return null;
+ }
+
+ private static
+ Method getSingleMethod(Class<?> smType) {
+ Method sm = null;
+ for (Method m : smType.getMethods()) {
+ int mod = m.getModifiers();
+ if (Modifier.isAbstract(mod)) {
+ if (sm != null && !isObjectMethod(sm))
+ return null; // too many abstract methods
+ sm = m;
+ }
+ }
+ if (!smType.isInterface() && getSingleConstructor(smType) == null)
+ return null; // wrong kind of constructor
+ return sm;
+ }
+
+ private static
+ Constructor getSingleConstructor(Class<?> smType) {
+ for (Constructor c : smType.getDeclaredConstructors()) {
+ if (c.getParameterTypes().length == 0) {
+ int mod = c.getModifiers();
+ if (Modifier.isPublic(mod) || Modifier.isProtected(mod))
+ return c;
+ }
+ }
+ return null;
+ }
+
+ /*non-public*/
+ static MethodHandle asVarargsCollector(MethodHandle target, Class<?> arrayType) {
+ return MethodHandleImpl.asVarargsCollector(target, arrayType);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodType.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import sun.invoke.util.BytecodeDescriptor;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * A method type represents the arguments and return type accepted and
+ * returned by a method handle, or the arguments and return type passed
+ * and expected by a method handle caller. Method types must be properly
+ * matched between a method handle and all its callers,
+ * and the JVM's operations enforce this matching at, specifically
+ * during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact}
+ * and {@link MethodHandle#invokeGeneric MethodHandle.invokeGeneric}, and during execution
+ * of {@code invokedynamic} instructions.
+ * <p>
+ * The structure is a return type accompanied by any number of parameter types.
+ * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
+ * (For ease of exposition, we treat {@code void} as if it were a type.
+ * In fact, it denotes the absence of a return type.)
+ * <p>
+ * All instances of {@code MethodType} are immutable.
+ * Two instances are completely interchangeable if they compare equal.
+ * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
+ * <p>
+ * This type can be created only by factory methods.
+ * All factory methods may cache values, though caching is not guaranteed.
+ * Some factory methods are static, while others are virtual methods which
+ * modify precursor method types, e.g., by changing a selected parameter.
+ * <p>
+ * Factory methods which operate on groups of parameter types
+ * are systematically presented in two versions, so that both Java arrays and
+ * Java lists can be used to work with groups of parameter types.
+ * The query methods {@code parameterArray} and {@code parameterList}
+ * also provide a choice between arrays and lists.
+ * <p>
+ * {@code MethodType} objects are sometimes derived from bytecode instructions
+ * such as {@code invokedynamic}, specifically from the type descriptor strings associated
+ * with the instructions in a class file's constant pool.
+ * <p>
+ * Like classes and strings, method types can also be represented directly
+ * in a class file's constant pool as constants.
+ * A method type may be loaded by an {@code ldc} instruction which refers
+ * to a suitable {@code CONSTANT_MethodType} constant pool entry.
+ * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
+ * For more details, see the <a href="package-summary.html#mtcon">package summary</a>.
+ * <p>
+ * When the JVM materializes a {@code MethodType} from a descriptor string,
+ * all classes named in the descriptor must be accessible, and will be loaded.
+ * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
+ * This loading may occur at any time before the {@code MethodType} object is first derived.
+ * @author John Rose, JSR 292 EG
+ */
+public final
+class MethodType implements java.io.Serializable {
+ private static final long serialVersionUID = 292L; // {rtype, {ptype...}}
+
+ // The rtype and ptypes fields define the structural identity of the method type:
+ private final Class<?> rtype;
+ private final Class<?>[] ptypes;
+
+ // The remaining fields are caches of various sorts:
+ private MethodTypeForm form; // erased form, plus cached data about primitives
+ private MethodType wrapAlt; // alternative wrapped/unwrapped version
+ private Invokers invokers; // cache of handy higher-order adapters
+
+ /**
+ * Check the given parameters for validity and store them into the final fields.
+ */
+ private MethodType(Class<?> rtype, Class<?>[] ptypes) {
+ checkRtype(rtype);
+ checkPtypes(ptypes);
+ this.rtype = rtype;
+ this.ptypes = ptypes;
+ }
+
+ /*trusted*/ MethodTypeForm form() { return form; }
+ /*trusted*/ Class<?> rtype() { return rtype; }
+ /*trusted*/ Class<?>[] ptypes() { return ptypes; }
+
+ private static void checkRtype(Class<?> rtype) {
+ rtype.equals(rtype); // null check
+ }
+ private static int checkPtype(Class<?> ptype) {
+ ptype.getClass(); //NPE
+ if (ptype == void.class)
+ throw newIllegalArgumentException("parameter type cannot be void");
+ if (ptype == double.class || ptype == long.class) return 1;
+ return 0;
+ }
+ /** Return number of extra slots (count of long/double args). */
+ private static int checkPtypes(Class<?>[] ptypes) {
+ int slots = 0;
+ for (Class<?> ptype : ptypes) {
+ slots += checkPtype(ptype);
+ }
+ checkSlotCount(ptypes.length + slots);
+ return slots;
+ }
+ private static void checkSlotCount(int count) {
+ if ((count & 0xFF) != count)
+ throw newIllegalArgumentException("bad parameter count "+count);
+ }
+ private static IndexOutOfBoundsException newIndexOutOfBoundsException(Object num) {
+ if (num instanceof Integer) num = "bad index: "+num;
+ return new IndexOutOfBoundsException(num.toString());
+ }
+
+ static final HashMap<MethodType,MethodType> internTable
+ = new HashMap<MethodType, MethodType>();
+
+ static final Class<?>[] NO_PTYPES = {};
+
+ /**
+ * Finds or creates an instance of the given method type.
+ * @param rtype the return type
+ * @param ptypes the parameter types
+ * @return a method type with the given components
+ * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
+ * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
+ */
+ public static
+ MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
+ return makeImpl(rtype, ptypes, false);
+ }
+
+ /**
+ * Finds or creates a method type with the given components.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * @return a method type with the given components
+ * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
+ * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
+ */
+ public static
+ MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) {
+ boolean notrust = false; // random List impl. could return evil ptypes array
+ return makeImpl(rtype, ptypes.toArray(NO_PTYPES), notrust);
+ }
+
+ /**
+ * Finds or creates a method type with the given components.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * The leading parameter type is prepended to the remaining array.
+ * @return a method type with the given components
+ * @throws NullPointerException if {@code rtype} or {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is null
+ * @throws IllegalArgumentException if {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is {@code void.class}
+ */
+ public static
+ MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
+ Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
+ ptypes1[0] = ptype0;
+ System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
+ return makeImpl(rtype, ptypes1, true);
+ }
+
+ /**
+ * Finds or creates a method type with the given components.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * The resulting method has no parameter types.
+ * @return a method type with the given return value
+ * @throws NullPointerException if {@code rtype} is null
+ */
+ public static
+ MethodType methodType(Class<?> rtype) {
+ return makeImpl(rtype, NO_PTYPES, true);
+ }
+
+ /**
+ * Finds or creates a method type with the given components.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * The resulting method has the single given parameter type.
+ * @return a method type with the given return value and parameter type
+ * @throws NullPointerException if {@code rtype} or {@code ptype0} is null
+ * @throws IllegalArgumentException if {@code ptype0} is {@code void.class}
+ */
+ public static
+ MethodType methodType(Class<?> rtype, Class<?> ptype0) {
+ return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
+ }
+
+ /**
+ * Finds or creates a method type with the given components.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * The resulting method has the same parameter types as {@code ptypes},
+ * and the specified return type.
+ * @throws NullPointerException if {@code rtype} or {@code ptypes} is null
+ */
+ public static
+ MethodType methodType(Class<?> rtype, MethodType ptypes) {
+ return makeImpl(rtype, ptypes.ptypes, true);
+ }
+
+ /**
+ * Sole factory method to find or create an interned method type.
+ * @param rtype desired return type
+ * @param ptypes desired parameter types
+ * @param trusted whether the ptypes can be used without cloning
+ * @return the unique method type of the desired structure
+ */
+ /*trusted*/ static
+ MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
+ if (ptypes == null || ptypes.length == 0) {
+ ptypes = NO_PTYPES; trusted = true;
+ }
+ MethodType mt1 = new MethodType(rtype, ptypes);
+ MethodType mt0;
+ synchronized (internTable) {
+ mt0 = internTable.get(mt1);
+ if (mt0 != null)
+ return mt0;
+ }
+ if (!trusted)
+ // defensively copy the array passed in by the user
+ mt1 = new MethodType(rtype, ptypes.clone());
+ // promote the object to the Real Thing, and reprobe
+ MethodTypeForm form = MethodTypeForm.findForm(mt1);
+ mt1.form = form;
+ if (form.erasedType == mt1) {
+ // This is a principal (erased) type; show it to the JVM.
+ MethodHandleNatives.init(mt1);
+ }
+ synchronized (internTable) {
+ mt0 = internTable.get(mt1);
+ if (mt0 != null)
+ return mt0;
+ internTable.put(mt1, mt1);
+ }
+ return mt1;
+ }
+
+ private static final MethodType[] objectOnlyTypes = new MethodType[20];
+
+ /**
+ * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * All parameters and the return type will be {@code Object},
+ * except the final varargs parameter if any, which will be {@code Object[]}.
+ * @param objectArgCount number of parameters (excluding the varargs parameter if any)
+ * @param varargs whether there will be a varargs parameter, of type {@code Object[]}
+ * @return a totally generic method type, given only its count of parameters and varargs
+ * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
+ * @see #genericMethodType(int)
+ */
+ public static
+ MethodType genericMethodType(int objectArgCount, boolean varargs) {
+ MethodType mt;
+ checkSlotCount(objectArgCount);
+ int ivarargs = (!varargs ? 0 : 1);
+ int ootIndex = objectArgCount*2 + ivarargs;
+ if (ootIndex < objectOnlyTypes.length) {
+ mt = objectOnlyTypes[ootIndex];
+ if (mt != null) return mt;
+ }
+ Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
+ Arrays.fill(ptypes, Object.class);
+ if (ivarargs != 0) ptypes[objectArgCount] = Object[].class;
+ mt = makeImpl(Object.class, ptypes, true);
+ if (ootIndex < objectOnlyTypes.length) {
+ objectOnlyTypes[ootIndex] = mt; // cache it here also!
+ }
+ return mt;
+ }
+
+ /**
+ * Finds or creates a method type whose components are all {@code Object}.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * All parameters and the return type will be Object.
+ * @param objectArgCount number of parameters
+ * @return a totally generic method type, given only its count of parameters
+ * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
+ * @see #genericMethodType(int, boolean)
+ */
+ public static
+ MethodType genericMethodType(int objectArgCount) {
+ return genericMethodType(objectArgCount, false);
+ }
+
+ /**
+ * Finds or creates a method type with a single different parameter type.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * @param num the index (zero-based) of the parameter type to change
+ * @param nptype a new parameter type to replace the old one with
+ * @return the same type, except with the selected parameter changed
+ * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
+ * @throws IllegalArgumentException if {@code nptype} is {@code void.class}
+ * @throws NullPointerException if {@code nptype} is null
+ */
+ public MethodType changeParameterType(int num, Class<?> nptype) {
+ if (parameterType(num) == nptype) return this;
+ checkPtype(nptype);
+ Class<?>[] nptypes = ptypes.clone();
+ nptypes[num] = nptype;
+ return makeImpl(rtype, nptypes, true);
+ }
+
+ /**
+ * Finds or creates a method type with additional parameter types.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * @param num the position (zero-based) of the inserted parameter type(s)
+ * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
+ * @return the same type, except with the selected parameter(s) inserted
+ * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
+ * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
+ * or if the resulting method type would have more than 255 parameter slots
+ * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
+ */
+ public MethodType insertParameterTypes(int num, Class<?>... ptypesToInsert) {
+ int len = ptypes.length;
+ if (num < 0 || num > len)
+ throw newIndexOutOfBoundsException(num);
+ int ins = checkPtypes(ptypesToInsert);
+ checkSlotCount(parameterSlotCount() + ptypesToInsert.length + ins);
+ int ilen = ptypesToInsert.length;
+ if (ilen == 0) return this;
+ Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+ilen);
+ System.arraycopy(nptypes, num, nptypes, num+ilen, len-num);
+ System.arraycopy(ptypesToInsert, 0, nptypes, num, ilen);
+ return makeImpl(rtype, nptypes, true);
+ }
+
+ /**
+ * Finds or creates a method type with additional parameter types.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
+ * @return the same type, except with the selected parameter(s) appended
+ * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
+ * or if the resulting method type would have more than 255 parameter slots
+ * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
+ */
+ public MethodType appendParameterTypes(Class<?>... ptypesToInsert) {
+ return insertParameterTypes(parameterCount(), ptypesToInsert);
+ }
+
+ /**
+ * Finds or creates a method type with additional parameter types.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * @param num the position (zero-based) of the inserted parameter type(s)
+ * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
+ * @return the same type, except with the selected parameter(s) inserted
+ * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
+ * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
+ * or if the resulting method type would have more than 255 parameter slots
+ * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
+ */
+ public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
+ return insertParameterTypes(num, ptypesToInsert.toArray(NO_PTYPES));
+ }
+
+ /**
+ * Finds or creates a method type with additional parameter types.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
+ * @return the same type, except with the selected parameter(s) appended
+ * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
+ * or if the resulting method type would have more than 255 parameter slots
+ * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
+ */
+ public MethodType appendParameterTypes(List<Class<?>> ptypesToInsert) {
+ return insertParameterTypes(parameterCount(), ptypesToInsert);
+ }
+
+ /**
+ * Finds or creates a method type with some parameter types omitted.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * @param start the index (zero-based) of the first parameter type to remove
+ * @param end the index (greater than {@code start}) of the first parameter type after not to remove
+ * @return the same type, except with the selected parameter(s) removed
+ * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
+ * or if {@code end} is negative or greater than {@code parameterCount()}
+ * or if {@code start} is greater than {@code end}
+ */
+ public MethodType dropParameterTypes(int start, int end) {
+ int len = ptypes.length;
+ if (!(0 <= start && start <= end && end <= len))
+ throw newIndexOutOfBoundsException("start="+start+" end="+end);
+ if (start == end) return this;
+ Class<?>[] nptypes;
+ if (start == 0) {
+ if (end == len) {
+ // drop all parameters
+ nptypes = NO_PTYPES;
+ } else {
+ // drop initial parameter(s)
+ nptypes = Arrays.copyOfRange(ptypes, end, len);
+ }
+ } else {
+ if (end == len) {
+ // drop trailing parameter(s)
+ nptypes = Arrays.copyOfRange(ptypes, 0, start);
+ } else {
+ int tail = len - end;
+ nptypes = Arrays.copyOfRange(ptypes, 0, start + tail);
+ System.arraycopy(ptypes, end, nptypes, start, tail);
+ }
+ }
+ return makeImpl(rtype, nptypes, true);
+ }
+
+ /**
+ * Finds or creates a method type with a different return type.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * @param nrtype a return parameter type to replace the old one with
+ * @return the same type, except with the return type change
+ * @throws NullPointerException if {@code nrtype} is null
+ */
+ public MethodType changeReturnType(Class<?> nrtype) {
+ if (returnType() == nrtype) return this;
+ return makeImpl(nrtype, ptypes, true);
+ }
+
+ /**
+ * Reports if this type contains a primitive argument or return value.
+ * The return type {@code void} counts as a primitive.
+ * @return true if any of the types are primitives
+ */
+ public boolean hasPrimitives() {
+ return form.hasPrimitives();
+ }
+
+ /**
+ * Reports if this type contains a wrapper argument or return value.
+ * Wrappers are types which box primitive values, such as {@link Integer}.
+ * The reference type {@code java.lang.Void} counts as a wrapper.
+ * @return true if any of the types are wrappers
+ */
+ public boolean hasWrappers() {
+ return unwrap() != this;
+ }
+
+ /**
+ * Erases all reference types to {@code Object}.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * All primitive types (including {@code void}) will remain unchanged.
+ * @return a version of the original type with all reference types replaced
+ */
+ public MethodType erase() {
+ return form.erasedType();
+ }
+
+ /**
+ * Converts all types, both reference and primitive, to {@code Object}.
+ * Convenience method for {@link #genericMethodType(int) genericMethodType}.
+ * The expression {@code type.wrap().erase()} produces the same value
+ * as {@code type.generic()}.
+ * @return a version of the original type with all types replaced
+ */
+ public MethodType generic() {
+ return genericMethodType(parameterCount());
+ }
+
+ /**
+ * Converts all primitive types to their corresponding wrapper types.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * All reference types (including wrapper types) will remain unchanged.
+ * A {@code void} return type is changed to the type {@code java.lang.Void}.
+ * The expression {@code type.wrap().erase()} produces the same value
+ * as {@code type.generic()}.
+ * @return a version of the original type with all primitive types replaced
+ */
+ public MethodType wrap() {
+ return hasPrimitives() ? wrapWithPrims(this) : this;
+ }
+
+ /**
+ * Converts all wrapper types to their corresponding primitive types.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * All primitive types (including {@code void}) will remain unchanged.
+ * A return type of {@code java.lang.Void} is changed to {@code void}.
+ * @return a version of the original type with all wrapper types replaced
+ */
+ public MethodType unwrap() {
+ MethodType noprims = !hasPrimitives() ? this : wrapWithPrims(this);
+ return unwrapWithNoPrims(noprims);
+ }
+
+ private static MethodType wrapWithPrims(MethodType pt) {
+ assert(pt.hasPrimitives());
+ MethodType wt = pt.wrapAlt;
+ if (wt == null) {
+ // fill in lazily
+ wt = MethodTypeForm.canonicalize(pt, MethodTypeForm.WRAP, MethodTypeForm.WRAP);
+ assert(wt != null);
+ pt.wrapAlt = wt;
+ }
+ return wt;
+ }
+
+ private static MethodType unwrapWithNoPrims(MethodType wt) {
+ assert(!wt.hasPrimitives());
+ MethodType uwt = wt.wrapAlt;
+ if (uwt == null) {
+ // fill in lazily
+ uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP);
+ if (uwt == null)
+ uwt = wt; // type has no wrappers or prims at all
+ wt.wrapAlt = uwt;
+ }
+ return uwt;
+ }
+
+ /**
+ * Returns the parameter type at the specified index, within this method type.
+ * @param num the index (zero-based) of the desired parameter type
+ * @return the selected parameter type
+ * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
+ */
+ public Class<?> parameterType(int num) {
+ return ptypes[num];
+ }
+ /**
+ * Returns the number of parameter types in this method type.
+ * @return the number of parameter types
+ */
+ public int parameterCount() {
+ return ptypes.length;
+ }
+ /**
+ * Returns the return type of this method type.
+ * @return the return type
+ */
+ public Class<?> returnType() {
+ return rtype;
+ }
+
+ /**
+ * Presents the parameter types as a list (a convenience method).
+ * The list will be immutable.
+ * @return the parameter types (as an immutable list)
+ */
+ public List<Class<?>> parameterList() {
+ return Collections.unmodifiableList(Arrays.asList(ptypes));
+ }
+
+ /**
+ * Presents the parameter types as an array (a convenience method).
+ * Changes to the array will not result in changes to the type.
+ * @return the parameter types (as a fresh copy if necessary)
+ */
+ public Class<?>[] parameterArray() {
+ return ptypes.clone();
+ }
+
+ /**
+ * Compares the specified object with this type for equality.
+ * That is, it returns <tt>true</tt> if and only if the specified object
+ * is also a method type with exactly the same parameters and return type.
+ * @param x object to compare
+ * @see Object#equals(Object)
+ */
+ @Override
+ public boolean equals(Object x) {
+ return this == x || x instanceof MethodType && equals((MethodType)x);
+ }
+
+ private boolean equals(MethodType that) {
+ return this.rtype == that.rtype
+ && Arrays.equals(this.ptypes, that.ptypes);
+ }
+
+ /**
+ * Returns the hash code value for this method type.
+ * It is defined to be the same as the hashcode of a List
+ * whose elements are the return type followed by the
+ * parameter types.
+ * @return the hash code value for this method type
+ * @see Object#hashCode()
+ * @see #equals(Object)
+ * @see List#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ int hashCode = 31 + rtype.hashCode();
+ for (Class<?> ptype : ptypes)
+ hashCode = 31*hashCode + ptype.hashCode();
+ return hashCode;
+ }
+
+ /**
+ * Returns a string representation of the method type,
+ * of the form {@code "(PT0,PT1...)RT"}.
+ * The string representation of a method type is a
+ * parenthesis enclosed, comma separated list of type names,
+ * followed immediately by the return type.
+ * <p>
+ * Each type is represented by its
+ * {@link java.lang.Class#getSimpleName simple name}.
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("(");
+ for (int i = 0; i < ptypes.length; i++) {
+ if (i > 0) sb.append(",");
+ sb.append(ptypes[i].getSimpleName());
+ }
+ sb.append(")");
+ sb.append(rtype.getSimpleName());
+ return sb.toString();
+ }
+
+ /// Queries which have to do with the bytecode architecture
+
+ /** Reports the number of JVM stack slots required to invoke a method
+ * of this type. Note that (for historical reasons) the JVM requires
+ * a second stack slot to pass long and double arguments.
+ * So this method returns {@link #parameterCount() parameterCount} plus the
+ * number of long and double parameters (if any).
+ * <p>
+ * This method is included for the benfit of applications that must
+ * generate bytecodes that process method handles and invokedynamic.
+ * @return the number of JVM stack slots for this type's parameters
+ */
+ /*non-public*/ int parameterSlotCount() {
+ return form.parameterSlotCount();
+ }
+
+ /*non-public*/ Invokers invokers() {
+ Invokers inv = invokers;
+ if (inv != null) return inv;
+ invokers = inv = new Invokers(this);
+ return inv;
+ }
+
+ /** Reports the number of JVM stack slots which carry all parameters including and after
+ * the given position, which must be in the range of 0 to
+ * {@code parameterCount} inclusive. Successive parameters are
+ * more shallowly stacked, and parameters are indexed in the bytecodes
+ * according to their trailing edge. Thus, to obtain the depth
+ * in the outgoing call stack of parameter {@code N}, obtain
+ * the {@code parameterSlotDepth} of its trailing edge
+ * at position {@code N+1}.
+ * <p>
+ * Parameters of type {@code long} and {@code double} occupy
+ * two stack slots (for historical reasons) and all others occupy one.
+ * Therefore, the number returned is the number of arguments
+ * <em>including</em> and <em>after</em> the given parameter,
+ * <em>plus</em> the number of long or double arguments
+ * at or after after the argument for the given parameter.
+ * <p>
+ * This method is included for the benfit of applications that must
+ * generate bytecodes that process method handles and invokedynamic.
+ * @param num an index (zero-based, inclusive) within the parameter types
+ * @return the index of the (shallowest) JVM stack slot transmitting the
+ * given parameter
+ * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
+ */
+ /*non-public*/ int parameterSlotDepth(int num) {
+ if (num < 0 || num > ptypes.length)
+ parameterType(num); // force a range check
+ return form.parameterToArgSlot(num-1);
+ }
+
+ /** Reports the number of JVM stack slots required to receive a return value
+ * from a method of this type.
+ * If the {@link #returnType() return type} is void, it will be zero,
+ * else if the return type is long or double, it will be two, else one.
+ * <p>
+ * This method is included for the benfit of applications that must
+ * generate bytecodes that process method handles and invokedynamic.
+ * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
+ * Will be removed for PFD.
+ */
+ /*non-public*/ int returnSlotCount() {
+ return form.returnSlotCount();
+ }
+
+ /**
+ * Finds or creates an instance of a method type, given the spelling of its bytecode descriptor.
+ * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
+ * Any class or interface name embedded in the descriptor string
+ * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
+ * on the given loader (or if it is null, on the system class loader).
+ * <p>
+ * Note that it is possible to encounter method types which cannot be
+ * constructed by this method, because their component types are
+ * not all reachable from a common class loader.
+ * <p>
+ * This method is included for the benfit of applications that must
+ * generate bytecodes that process method handles and {@code invokedynamic}.
+ * @param descriptor a bytecode-level type descriptor string "(T...)T"
+ * @param loader the class loader in which to look up the types
+ * @return a method type matching the bytecode-level type descriptor
+ * @throws IllegalArgumentException if the string is not well-formed
+ * @throws TypeNotPresentException if a named type cannot be found
+ */
+ public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
+ throws IllegalArgumentException, TypeNotPresentException
+ {
+ List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
+ Class<?> rtype = types.remove(types.size() - 1);
+ Class<?>[] ptypes = types.toArray(NO_PTYPES);
+ return makeImpl(rtype, ptypes, true);
+ }
+
+ /**
+ * Produces a bytecode descriptor representation of the method type.
+ * <p>
+ * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
+ * Two distinct classes which share a common name but have different class loaders
+ * will appear identical when viewed within descriptor strings.
+ * <p>
+ * This method is included for the benfit of applications that must
+ * generate bytecodes that process method handles and {@code invokedynamic}.
+ * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
+ * because the latter requires a suitable class loader argument.
+ * @return the bytecode type descriptor representation
+ */
+ public String toMethodDescriptorString() {
+ return BytecodeDescriptor.unparse(this);
+ }
+
+ /// Serialization.
+
+ /**
+ * There are no serializable fields for {@code MethodType}.
+ */
+ private static final java.io.ObjectStreamField[] serialPersistentFields = { };
+
+ /**
+ * Save the {@code MethodType} instance to a stream.
+ *
+ * @serialData
+ * For portability, the serialized format does not refer to named fields.
+ * Instead, the return type and parameter type arrays are written directly
+ * from the {@code writeObject} method, using two calls to {@code s.writeObject}
+ * as follows:
+ * <blockquote><pre>
+s.writeObject(this.returnType());
+s.writeObject(this.parameterArray());
+ * </pre></blockquote>
+ * <p>
+ * The deserialized field values are checked as if they were
+ * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
+ * For example, null values, or {@code void} parameter types,
+ * will lead to exceptions during deserialization.
+ * @param the stream to write the object to
+ */
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
+ s.defaultWriteObject(); // requires serialPersistentFields to be an empty array
+ s.writeObject(returnType());
+ s.writeObject(parameterArray());
+ }
+
+ /**
+ * Reconstitute the {@code MethodType} instance from a stream (that is,
+ * deserialize it).
+ * This instance is a scratch object with bogus final fields.
+ * It provides the parameters to the factory method called by
+ * {@link #readResolve readResolve}.
+ * After that call it is discarded.
+ * @param the stream to read the object from
+ * @see #MethodType()
+ * @see #readResolve
+ * @see #writeObject
+ */
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
+ s.defaultReadObject(); // requires serialPersistentFields to be an empty array
+
+ Class<?> returnType = (Class<?>) s.readObject();
+ Class<?>[] parameterArray = (Class<?>[]) s.readObject();
+
+ // Probably this object will never escape, but let's check
+ // the field values now, just to be sure.
+ checkRtype(returnType);
+ checkPtypes(parameterArray);
+
+ parameterArray = parameterArray.clone(); // make sure it is unshared
+ MethodType_init(returnType, parameterArray);
+ }
+
+ /**
+ * For serialization only.
+ * Sets the final fields to null, pending {@code Unsafe.putObject}.
+ */
+ private MethodType() {
+ this.rtype = null;
+ this.ptypes = null;
+ }
+ private void MethodType_init(Class<?> rtype, Class<?>[] ptypes) {
+ // In order to communicate these values to readResolve, we must
+ // store them into the implementation-specific final fields.
+ checkRtype(rtype);
+ checkPtypes(ptypes);
+ unsafe.putObject(this, rtypeOffset, rtype);
+ unsafe.putObject(this, ptypesOffset, ptypes);
+ }
+
+ // Support for resetting final fields while deserializing
+ private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+ private static final long rtypeOffset, ptypesOffset;
+ static {
+ try {
+ rtypeOffset = unsafe.objectFieldOffset
+ (MethodType.class.getDeclaredField("rtype"));
+ ptypesOffset = unsafe.objectFieldOffset
+ (MethodType.class.getDeclaredField("ptypes"));
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
+ /**
+ * Resolves and initializes a {@code MethodType} object
+ * after serialization.
+ * @return the fully initialized {@code MethodType} object
+ */
+ private Object readResolve() {
+ // Do not use a trusted path for deserialization:
+ //return makeImpl(rtype, ptypes, true);
+ // Verify all operands, and make sure ptypes is unshared:
+ return methodType(rtype, ptypes);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.Wrapper;
+import static java.lang.invoke.MethodHandleStatics.*;
+
+/**
+ * Shared information for a group of method types, which differ
+ * only by reference types, and therefore share a common erasure
+ * and wrapping.
+ * <p>
+ * For an empirical discussion of the structure of method types,
+ * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
+ * the thread "Avoiding Boxing" on jvm-languages</a>.
+ * There are approximately 2000 distinct erased method types in the JDK.
+ * There are a little over 10 times that number of unerased types.
+ * No more than half of these are likely to be loaded at once.
+ * @author John Rose
+ */
+class MethodTypeForm {
+ final int[] argToSlotTable, slotToArgTable;
+ final long argCounts; // packed slot & value counts
+ final long primCounts; // packed prim & double counts
+ final int vmslots; // total number of parameter slots
+ final MethodType erasedType; // the canonical erasure
+
+ /*lazy*/ MethodType primsAsBoxes; // replace prims by wrappers
+ /*lazy*/ MethodType primArgsAsBoxes; // wrap args only; make raw return
+ /*lazy*/ MethodType primsAsInts; // replace prims by int/long
+ /*lazy*/ MethodType primsAsLongs; // replace prims by long
+ /*lazy*/ MethodType primsAtEnd; // reorder primitives to the end
+
+ // Cached adapter information:
+ /*lazy*/ ToGeneric toGeneric; // convert cs. with prims to w/o
+ /*lazy*/ FromGeneric fromGeneric; // convert cs. w/o prims to with
+ /*lazy*/ SpreadGeneric[] spreadGeneric; // expand one argument to many
+ /*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly
+ /*lazy*/ MethodHandle genericInvoker; // hook for invokeGeneric
+
+ public MethodType erasedType() {
+ return erasedType;
+ }
+
+ protected MethodTypeForm(MethodType erasedType) {
+ this.erasedType = erasedType;
+
+ Class<?>[] ptypes = erasedType.ptypes();
+ int ptypeCount = ptypes.length;
+ int pslotCount = ptypeCount; // temp. estimate
+ int rtypeCount = 1; // temp. estimate
+ int rslotCount = 1; // temp. estimate
+
+ int[] argToSlotTab = null, slotToArgTab = null;
+
+ // Walk the argument types, looking for primitives.
+ int pac = 0, lac = 0, prc = 0, lrc = 0;
+ Class<?> epts[] = ptypes;
+ for (int i = 0; i < epts.length; i++) {
+ Class<?> pt = epts[i];
+ if (pt != Object.class) {
+ assert(pt.isPrimitive());
+ ++pac;
+ if (hasTwoArgSlots(pt)) ++lac;
+ }
+ }
+ pslotCount += lac; // #slots = #args + #longs
+ Class<?> rt = erasedType.returnType();
+ if (rt != Object.class) {
+ ++prc; // even void.class counts as a prim here
+ if (hasTwoArgSlots(rt)) ++lrc;
+ // adjust #slots, #args
+ if (rt == void.class)
+ rtypeCount = rslotCount = 0;
+ else
+ rslotCount += lrc;
+ }
+ if (lac != 0) {
+ int slot = ptypeCount + lac;
+ slotToArgTab = new int[slot+1];
+ argToSlotTab = new int[1+ptypeCount];
+ argToSlotTab[0] = slot; // argument "-1" is past end of slots
+ for (int i = 0; i < epts.length; i++) {
+ Class<?> pt = epts[i];
+ if (hasTwoArgSlots(pt)) --slot;
+ --slot;
+ slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
+ argToSlotTab[1+i] = slot;
+ }
+ assert(slot == 0); // filled the table
+ }
+ this.primCounts = pack(lrc, prc, lac, pac);
+ this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
+ if (slotToArgTab == null) {
+ int slot = ptypeCount; // first arg is deepest in stack
+ slotToArgTab = new int[slot+1];
+ argToSlotTab = new int[1+ptypeCount];
+ argToSlotTab[0] = slot; // argument "-1" is past end of slots
+ for (int i = 0; i < ptypeCount; i++) {
+ --slot;
+ slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
+ argToSlotTab[1+i] = slot;
+ }
+ }
+ this.argToSlotTable = argToSlotTab;
+ this.slotToArgTable = slotToArgTab;
+
+ if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments");
+
+ // send a few bits down to the JVM:
+ this.vmslots = parameterSlotCount();
+
+ // short circuit some no-op canonicalizations:
+ if (!hasPrimitives()) {
+ primsAsBoxes = erasedType;
+ primArgsAsBoxes = erasedType;
+ primsAsInts = erasedType;
+ primsAsLongs = erasedType;
+ primsAtEnd = erasedType;
+ }
+ }
+
+ /** Turn all primitive types to corresponding wrapper types.
+ */
+ public MethodType primsAsBoxes() {
+ MethodType ct = primsAsBoxes;
+ if (ct != null) return ct;
+ MethodType t = erasedType;
+ ct = canonicalize(erasedType, WRAP, WRAP);
+ if (ct == null) ct = t; // no prims to box
+ return primsAsBoxes = ct;
+ }
+
+ /** Turn all primitive argument types to corresponding wrapper types.
+ * Subword and void return types are promoted to int.
+ */
+ public MethodType primArgsAsBoxes() {
+ MethodType ct = primArgsAsBoxes;
+ if (ct != null) return ct;
+ MethodType t = erasedType;
+ ct = canonicalize(erasedType, RAW_RETURN, WRAP);
+ if (ct == null) ct = t; // no prims to box
+ return primArgsAsBoxes = ct;
+ }
+
+ /** Turn all primitive types to either int or long.
+ * Floating point return types are not changed, because
+ * they may require special calling sequences.
+ * A void return value is turned to int.
+ */
+ public MethodType primsAsInts() {
+ MethodType ct = primsAsInts;
+ if (ct != null) return ct;
+ MethodType t = erasedType;
+ ct = canonicalize(t, RAW_RETURN, INTS);
+ if (ct == null) ct = t; // no prims to int-ify
+ return primsAsInts = ct;
+ }
+
+ /** Turn all primitive types to either int or long.
+ * Floating point return types are not changed, because
+ * they may require special calling sequences.
+ * A void return value is turned to int.
+ */
+ public MethodType primsAsLongs() {
+ MethodType ct = primsAsLongs;
+ if (ct != null) return ct;
+ MethodType t = erasedType;
+ ct = canonicalize(t, RAW_RETURN, LONGS);
+ if (ct == null) ct = t; // no prims to int-ify
+ return primsAsLongs = ct;
+ }
+
+ /** Stably sort parameters into 3 buckets: ref, int, long. */
+ public MethodType primsAtEnd() {
+ MethodType ct = primsAtEnd;
+ if (ct != null) return ct;
+ MethodType t = erasedType;
+
+ int pac = primitiveParameterCount();
+ if (pac == 0)
+ return primsAtEnd = t;
+
+ int argc = parameterCount();
+ int lac = longPrimitiveParameterCount();
+ if (pac == argc && (lac == 0 || lac == argc))
+ return primsAtEnd = t;
+
+ // known to have a mix of 2 or 3 of ref, int, long
+ int[] reorder = primsAtEndOrder(t);
+ ct = reorderParameters(t, reorder, null);
+ //System.out.println("t="+t+" / reorder="+java.util.Arrays.toString(reorder)+" => "+ct);
+ return primsAtEnd = ct;
+ }
+
+ /** Compute a new ordering of parameters so that all references
+ * are before all ints or longs, and all ints are before all longs.
+ * For this ordering, doubles count as longs, and all other primitive
+ * values count as ints.
+ * As a special case, if the parameters are already in the specified
+ * order, this method returns a null reference, rather than an array
+ * specifying a null permutation.
+ * <p>
+ * For example, the type {@code (int,boolean,int,Object,String)void}
+ * produces the order {@code {3,4,0,1,2}}, the type
+ * {@code (long,int,String)void} produces {@code {2,1,2}}, and
+ * the type {@code (Object,int)Object} produces {@code null}.
+ */
+ public static int[] primsAtEndOrder(MethodType mt) {
+ MethodTypeForm form = mt.form();
+ if (form.primsAtEnd == form.erasedType)
+ // quick check shows no reordering is necessary
+ return null;
+
+ int argc = form.parameterCount();
+ int[] paramOrder = new int[argc];
+
+ // 3-way bucket sort:
+ int pac = form.primitiveParameterCount();
+ int lac = form.longPrimitiveParameterCount();
+ int rfill = 0, ifill = argc - pac, lfill = argc - lac;
+
+ Class<?>[] ptypes = mt.ptypes();
+ boolean changed = false;
+ for (int i = 0; i < ptypes.length; i++) {
+ Class<?> pt = ptypes[i];
+ int ord;
+ if (!pt.isPrimitive()) ord = rfill++;
+ else if (!hasTwoArgSlots(pt)) ord = ifill++;
+ else ord = lfill++;
+ if (ord != i) changed = true;
+ assert(paramOrder[ord] == 0);
+ paramOrder[ord] = i;
+ }
+ assert(rfill == argc - pac && ifill == argc - lac && lfill == argc);
+ if (!changed) {
+ form.primsAtEnd = form.erasedType;
+ return null;
+ }
+ return paramOrder;
+ }
+
+ /** Put the existing parameters of mt into a new order, given by newParamOrder.
+ * The third argument is logically appended to mt.parameterArray,
+ * so that elements of newParamOrder can index either pre-existing or
+ * new parameter types.
+ */
+ public static MethodType reorderParameters(MethodType mt, int[] newParamOrder, Class<?>[] moreParams) {
+ if (newParamOrder == null) return mt; // no-op reordering
+ Class<?>[] ptypes = mt.ptypes();
+ Class<?>[] ntypes = new Class<?>[newParamOrder.length];
+ int maxParam = ptypes.length + (moreParams == null ? 0 : moreParams.length);
+ boolean changed = (ntypes.length != ptypes.length);
+ for (int i = 0; i < newParamOrder.length; i++) {
+ int param = newParamOrder[i];
+ if (param != i) changed = true;
+ Class<?> nt;
+ if (param < ptypes.length) nt = ptypes[param];
+ else if (param == maxParam) nt = mt.returnType();
+ else nt = moreParams[param - ptypes.length];
+ ntypes[i] = nt;
+ }
+ if (!changed) return mt;
+ return MethodType.makeImpl(mt.returnType(), ntypes, true);
+ }
+
+ private static boolean hasTwoArgSlots(Class<?> type) {
+ return type == long.class || type == double.class;
+ }
+
+ private static long pack(int a, int b, int c, int d) {
+ assert(((a|b|c|d) & ~0xFFFF) == 0);
+ long hw = ((a << 16) | b), lw = ((c << 16) | d);
+ return (hw << 32) | lw;
+ }
+ private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
+ assert(word <= 3);
+ return (char)(packed >> ((3-word) * 16));
+ }
+
+ public int parameterCount() { // # outgoing values
+ return unpack(argCounts, 3);
+ }
+ public int parameterSlotCount() { // # outgoing interpreter slots
+ return unpack(argCounts, 2);
+ }
+ public int returnCount() { // = 0 (V), or 1
+ return unpack(argCounts, 1);
+ }
+ public int returnSlotCount() { // = 0 (V), 2 (J/D), or 1
+ return unpack(argCounts, 0);
+ }
+ public int primitiveParameterCount() {
+ return unpack(primCounts, 3);
+ }
+ public int longPrimitiveParameterCount() {
+ return unpack(primCounts, 2);
+ }
+ public int primitiveReturnCount() { // = 0 (obj), or 1
+ return unpack(primCounts, 1);
+ }
+ public int longPrimitiveReturnCount() { // = 1 (J/D), or 0
+ return unpack(primCounts, 0);
+ }
+ public boolean hasPrimitives() {
+ return primCounts != 0;
+ }
+// public boolean hasNonVoidPrimitives() {
+// if (primCounts == 0) return false;
+// if (primitiveParameterCount() != 0) return true;
+// return (primitiveReturnCount() != 0 && returnCount() != 0);
+// }
+ public boolean hasLongPrimitives() {
+ return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
+ }
+ public int parameterToArgSlot(int i) {
+ return argToSlotTable[1+i];
+ }
+ public int argSlotToParameter(int argSlot) {
+ // Note: Empty slots are represented by zero in this table.
+ // Valid arguments slots contain incremented entries, so as to be non-zero.
+ // We return -1 the caller to mean an empty slot.
+ return slotToArgTable[argSlot] - 1;
+ }
+
+ static MethodTypeForm findForm(MethodType mt) {
+ MethodType erased = canonicalize(mt, ERASE, ERASE);
+ if (erased == null) {
+ // It is already erased. Make a new MethodTypeForm.
+ return new MethodTypeForm(mt);
+ } else {
+ // Share the MethodTypeForm with the erased version.
+ return erased.form();
+ }
+ }
+
+ /** Codes for {@link #canonicalize(java.lang.Class, int)}.
+ * ERASE means change every reference to {@code Object}.
+ * WRAP means convert primitives (including {@code void} to their
+ * corresponding wrapper types. UNWRAP means the reverse of WRAP.
+ * INTS means convert all non-void primitive types to int or long,
+ * according to size. LONGS means convert all non-void primitives
+ * to long, regardless of size. RAW_RETURN means convert a type
+ * (assumed to be a return type) to int if it is smaller than an int,
+ * or if it is void.
+ */
+ public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
+
+ /** Canonicalize the types in the given method type.
+ * If any types change, intern the new type, and return it.
+ * Otherwise return null.
+ */
+ public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
+ Class<?>[] ptypes = mt.ptypes();
+ Class<?>[] ptc = MethodTypeForm.canonicalizes(ptypes, howArgs);
+ Class<?> rtype = mt.returnType();
+ Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet);
+ if (ptc == null && rtc == null) {
+ // It is already canonical.
+ return null;
+ }
+ // Find the erased version of the method type:
+ if (rtc == null) rtc = rtype;
+ if (ptc == null) ptc = ptypes;
+ return MethodType.makeImpl(rtc, ptc, true);
+ }
+
+ /** Canonicalize the given return or param type.
+ * Return null if the type is already canonicalized.
+ */
+ static Class<?> canonicalize(Class<?> t, int how) {
+ Class<?> ct;
+ if (t == Object.class) {
+ // no change, ever
+ } else if (!t.isPrimitive()) {
+ switch (how) {
+ case UNWRAP:
+ ct = Wrapper.asPrimitiveType(t);
+ if (ct != t) return ct;
+ break;
+ case RAW_RETURN:
+ case ERASE:
+ return Object.class;
+ }
+ } else if (t == void.class) {
+ // no change, usually
+ switch (how) {
+ case RAW_RETURN:
+ return int.class;
+ case WRAP:
+ return Void.class;
+ }
+ } else {
+ // non-void primitive
+ switch (how) {
+ case WRAP:
+ return Wrapper.asWrapperType(t);
+ case INTS:
+ if (t == int.class || t == long.class)
+ return null; // no change
+ if (t == double.class)
+ return long.class;
+ return int.class;
+ case LONGS:
+ if (t == long.class)
+ return null; // no change
+ return long.class;
+ case RAW_RETURN:
+ if (t == int.class || t == long.class ||
+ t == float.class || t == double.class)
+ return null; // no change
+ // everything else returns as an int
+ return int.class;
+ }
+ }
+ // no change; return null to signify
+ return null;
+ }
+
+ /** Canonicalize each param type in the given array.
+ * Return null if all types are already canonicalized.
+ */
+ static Class<?>[] canonicalizes(Class<?>[] ts, int how) {
+ Class<?>[] cs = null;
+ for (int imax = ts.length, i = 0; i < imax; i++) {
+ Class<?> c = canonicalize(ts[i], how);
+ if (c != null) {
+ if (cs == null)
+ cs = ts.clone();
+ cs[i] = c;
+ }
+ }
+ return cs;
+ }
+
+ /*non-public*/ void notifyGenericMethodType() {
+ if (genericInvoker != null) return;
+ try {
+ // Trigger adapter creation.
+ genericInvoker = InvokeGeneric.genericInvokerOf(erasedType);
+ } catch (Exception ex) {
+ Error err = new InternalError("Exception while resolving invokeGeneric");
+ err.initCause(ex);
+ throw err;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Form"+erasedType;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/MutableCallSite.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A {@code MutableCallSite} is a {@link CallSite} whose target variable
+ * behaves like an ordinary field.
+ * An {@code invokedynamic} instruction linked to a {@code MutableCallSite} delegates
+ * all calls to the site's current target.
+ * The {@linkplain CallSite#dynamicInvoker dynamic invoker} of a mutable call site
+ * also delegates each call to the site's current target.
+ * <p>
+ * Here is an example of a mutable call site which introduces a
+ * state variable into a method handle chain.
+ * <blockquote><pre>
+MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
+MethodHandle MH_name = name.dynamicInvoker();
+MethodType MT_str2 = MethodType.methodType(String.class, String.class);
+MethodHandle MH_upcase = MethodHandles.lookup()
+ .findVirtual(String.class, "toUpperCase", MT_str2);
+MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
+name.setTarget(MethodHandles.constant(String.class, "Rocky"));
+assertEquals("ROCKY", (String) worker1.invokeExact());
+name.setTarget(MethodHandles.constant(String.class, "Fred"));
+assertEquals("FRED", (String) worker1.invokeExact());
+// (mutation can be continued indefinitely)
+ * </pre></blockquote>
+ * <p>
+ * The same call site may be used in several places at once.
+ * <blockquote><pre>
+MethodHandle MH_dear = MethodHandles.lookup()
+ .findVirtual(String.class, "concat", MT_str2).bindTo(", dear?");
+MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear);
+assertEquals("Fred, dear?", (String) worker2.invokeExact());
+name.setTarget(MethodHandles.constant(String.class, "Wilma"));
+assertEquals("WILMA", (String) worker1.invokeExact());
+assertEquals("Wilma, dear?", (String) worker2.invokeExact());
+ * </pre></blockquote>
+ * <p>
+ * <em>Non-synchronization of target values:</em>
+ * A write to a mutable call site's target does not force other threads
+ * to become aware of the updated value. Threads which do not perform
+ * suitable synchronization actions relative to the updated call site
+ * may cache the old target value and delay their use of the new target
+ * value indefinitely.
+ * (This is a normal consequence of the Java Memory Model as applied
+ * to object fields.)
+ * <p>
+ * The {@link #syncAll syncAll} operation provides a way to force threads
+ * to accept a new target value, even if there is no other synchronization.
+ * <p>
+ * For target values which will be frequently updated, consider using
+ * a {@linkplain VolatileCallSite volatile call site} instead.
+ * @author John Rose, JSR 292 EG
+ */
+public class MutableCallSite extends CallSite {
+ /**
+ * Creates a blank call site object with the given method type.
+ * The initial target is set to a method handle of the given type
+ * which will throw an {@link IllegalStateException} if called.
+ * <p>
+ * The type of the call site is permanently set to the given type.
+ * <p>
+ * Before this {@code CallSite} object is returned from a bootstrap method,
+ * or invoked in some other manner,
+ * it is usually provided with a more useful target method,
+ * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
+ * @param type the method type that this call site will have
+ * @throws NullPointerException if the proposed type is null
+ */
+ public MutableCallSite(MethodType type) {
+ super(type);
+ }
+
+ /**
+ * Creates a call site object with an initial target method handle.
+ * The type of the call site is permanently set to the initial target's type.
+ * @param target the method handle that will be the initial target of the call site
+ * @throws NullPointerException if the proposed target is null
+ */
+ public MutableCallSite(MethodHandle target) {
+ super(target);
+ }
+
+ /**
+ * Returns the target method of the call site, which behaves
+ * like a normal field of the {@code MutableCallSite}.
+ * <p>
+ * The interactions of {@code getTarget} with memory are the same
+ * as of a read from an ordinary variable, such as an array element or a
+ * non-volatile, non-final field.
+ * <p>
+ * In particular, the current thread may choose to reuse the result
+ * of a previous read of the target from memory, and may fail to see
+ * a recent update to the target by another thread.
+ *
+ * @return the linkage state of this call site, a method handle which can change over time
+ * @see #setTarget
+ */
+ @Override public final MethodHandle getTarget() {
+ return target;
+ }
+
+ /**
+ * Updates the target method of this call site, as a normal variable.
+ * The type of the new target must agree with the type of the old target.
+ * <p>
+ * The interactions with memory are the same
+ * as of a write to an ordinary variable, such as an array element or a
+ * non-volatile, non-final field.
+ * <p>
+ * In particular, unrelated threads may fail to see the updated target
+ * until they perform a read from memory.
+ * Stronger guarantees can be created by putting appropriate operations
+ * into the bootstrap method and/or the target methods used
+ * at any given call site.
+ *
+ * @param newTarget the new target
+ * @throws NullPointerException if the proposed new target is null
+ * @throws WrongMethodTypeException if the proposed new target
+ * has a method type that differs from the previous target
+ * @see #getTarget
+ */
+ @Override public void setTarget(MethodHandle newTarget) {
+ checkTargetChange(this.target, newTarget);
+ setTargetNormal(newTarget);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final MethodHandle dynamicInvoker() {
+ return makeDynamicInvoker();
+ }
+
+ /**
+ * Performs a synchronization operation on each call site in the given array,
+ * forcing all other threads to throw away any cached values previously
+ * loaded from the target of any of the call sites.
+ * <p>
+ * This operation does not reverse any calls that have already started
+ * on an old target value.
+ * (Java supports {@linkplain java.lang.Object#wait() forward time travel} only.)
+ * <p>
+ * The overall effect is to force all future readers of each call site's target
+ * to accept the most recently stored value.
+ * ("Most recently" is reckoned relative to the {@code syncAll} itself.)
+ * Conversely, the {@code syncAll} call may block until all readers have
+ * (somehow) decached all previous versions of each call site's target.
+ * <p>
+ * To avoid race conditions, calls to {@code setTarget} and {@code syncAll}
+ * should generally be performed under some sort of mutual exclusion.
+ * Note that reader threads may observe an updated target as early
+ * as the {@code setTarget} call that install the value
+ * (and before the {@code syncAll} that confirms the value).
+ * On the other hand, reader threads may observe previous versions of
+ * the target until the {@code syncAll} call returns
+ * (and after the {@code setTarget} that attempts to convey the updated version).
+ * <p>
+ * This operation is likely to be expensive and should be used sparingly.
+ * If possible, it should be buffered for batch processing on sets of call sites.
+ * <p>
+ * If {@code sites} contains a null element,
+ * a {@code NullPointerException} will be raised.
+ * In this case, some non-null elements in the array may be
+ * processed before the method returns abnormally.
+ * Which elements these are (if any) is implementation-dependent.
+ *
+ * <h3>Java Memory Model details</h3>
+ * In terms of the Java Memory Model, this operation performs a synchronization
+ * action which is comparable in effect to the writing of a volatile variable
+ * by the current thread, and an eventual volatile read by every other thread
+ * that may access one of the affected call sites.
+ * <p>
+ * The following effects are apparent, for each individual call site {@code S}:
+ * <ul>
+ * <li>A new volatile variable {@code V} is created, and written by the current thread.
+ * As defined by the JMM, this write is a global synchronization event.
+ * <li>As is normal with thread-local ordering of write events,
+ * every action already performed by the current thread is
+ * taken to happen before the volatile write to {@code V}.
+ * (In some implementations, this means that the current thread
+ * performs a global release operation.)
+ * <li>Specifically, the write to the current target of {@code S} is
+ * taken to happen before the volatile write to {@code V}.
+ * <li>The volatile write to {@code V} is placed
+ * (in an implementation specific manner)
+ * in the global synchronization order.
+ * <li>Consider an arbitrary thread {@code T} (other than the current thread).
+ * If {@code T} executes a synchronization action {@code A}
+ * after the volatile write to {@code V} (in the global synchronization order),
+ * it is therefore required to see either the current target
+ * of {@code S}, or a later write to that target,
+ * if it executes a read on the target of {@code S}.
+ * (This constraint is called "synchronization-order consistency".)
+ * <li>The JMM specifically allows optimizing compilers to elide
+ * reads or writes of variables that are known to be useless.
+ * Such elided reads and writes have no effect on the happens-before
+ * relation. Regardless of this fact, the volatile {@code V}
+ * will not be elided, even though its written value is
+ * indeterminate and its read value is not used.
+ * </ul>
+ * Because of the last point, the implementation behaves as if a
+ * volatile read of {@code V} were performed by {@code T}
+ * immediately after its action {@code A}. In the local ordering
+ * of actions in {@code T}, this read happens before any future
+ * read of the target of {@code S}. It is as if the
+ * implementation arbitrarily picked a read of {@code S}'s target
+ * by {@code T}, and forced a read of {@code V} to precede it,
+ * thereby ensuring communication of the new target value.
+ * <p>
+ * As long as the constraints of the Java Memory Model are obeyed,
+ * implementations may delay the completion of a {@code syncAll}
+ * operation while other threads ({@code T} above) continue to
+ * use previous values of {@code S}'s target.
+ * However, implementations are (as always) encouraged to avoid
+ * livelock, and to eventually require all threads to take account
+ * of the updated target.
+ *
+ * <p style="font-size:smaller;">
+ * <em>Discussion:</em>
+ * For performance reasons, {@code syncAll} is not a virtual method
+ * on a single call site, but rather applies to a set of call sites.
+ * Some implementations may incur a large fixed overhead cost
+ * for processing one or more synchronization operations,
+ * but a small incremental cost for each additional call site.
+ * In any case, this operation is likely to be costly, since
+ * other threads may have to be somehow interrupted
+ * in order to make them notice the updated target value.
+ * However, it may be observed that a single call to synchronize
+ * several sites has the same formal effect as many calls,
+ * each on just one of the sites.
+ *
+ * <p style="font-size:smaller;">
+ * <em>Implementation Note:</em>
+ * Simple implementations of {@code MutableCallSite} may use
+ * a volatile variable for the target of a mutable call site.
+ * In such an implementation, the {@code syncAll} method can be a no-op,
+ * and yet it will conform to the JMM behavior documented above.
+ *
+ * @param sites an array of call sites to be synchronized
+ * @throws NullPointerException if the {@code sites} array reference is null
+ * or the array contains a null
+ */
+ public static void syncAll(MutableCallSite[] sites) {
+ if (sites.length == 0) return;
+ STORE_BARRIER.lazySet(0);
+ for (int i = 0; i < sites.length; i++) {
+ sites[i].getClass(); // trigger NPE on first null
+ }
+ // FIXME: NYI
+ }
+ private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/SpreadGeneric.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,678 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import sun.invoke.util.ValueConversions;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Generic spread adapter.
+ * Expands a final argument into multiple (zero or more) arguments, keeping the others the same.
+ * @author jrose
+ */
+class SpreadGeneric {
+ // type for the outgoing call
+ private final MethodType targetType;
+ // number of arguments to spread
+ private final int spreadCount;
+ // prototype adapter (clone and customize for each new target!)
+ private final Adapter adapter;
+ // entry point for adapter (Adapter mh, a...) => ...
+ private final MethodHandle entryPoint;
+
+ /** Compute and cache information common to all spreading adapters
+ * that accept calls of the given (generic) type.
+ */
+ private SpreadGeneric(MethodType targetType, int spreadCount) {
+ assert(targetType == targetType.generic());
+ this.targetType = targetType;
+ this.spreadCount = spreadCount;
+ // the target invoker will generally need casts on reference arguments
+ MethodHandle[] ep = { null };
+ Adapter ad = findAdapter(this, ep);
+ if (ad != null) {
+ this.adapter = ad;
+ this.entryPoint = ep[0];
+ return;
+ }
+ this.adapter = buildAdapterFromBytecodes(targetType, spreadCount, ep);
+ this.entryPoint = ep[0];
+ }
+
+ /** From targetType remove the last spreadCount arguments, and instead
+ * append a simple Object argument.
+ */
+ static MethodType preSpreadType(MethodType targetType, int spreadCount) {
+ @SuppressWarnings("unchecked")
+ ArrayList<Class<?>> params = new ArrayList(targetType.parameterList());
+ int outargs = params.size();
+ params.subList(outargs - spreadCount, outargs).clear();
+ params.add(Object.class);
+ return MethodType.methodType(targetType.returnType(), params);
+ }
+
+ MethodHandle makeInstance(MethodHandle target) {
+ MethodType type = target.type();
+ if (type != targetType) {
+ throw new UnsupportedOperationException("NYI type="+type);
+ }
+ return adapter.makeInstance(this, target);
+ }
+
+ /** Build an adapter of the given generic type, which invokes typedTarget
+ * on the incoming arguments, after unboxing as necessary.
+ * The return value is boxed if necessary.
+ * @param genericType the required type of the result
+ * @param typedTarget the target
+ * @return an adapter method handle
+ */
+ public static MethodHandle make(MethodHandle target, int spreadCount) {
+ MethodType type = target.type();
+ MethodType gtype = type.generic();
+ if (type == gtype) {
+ return SpreadGeneric.of(type, spreadCount).makeInstance(target);
+ } else {
+ MethodHandle gtarget = FromGeneric.make(target);
+ assert(gtarget.type() == gtype);
+ MethodHandle gspread = SpreadGeneric.of(gtype, spreadCount).makeInstance(gtarget);
+ return ToGeneric.make(preSpreadType(type, spreadCount), gspread);
+ }
+ }
+
+ /** Return the adapter information for this type's erasure. */
+ static SpreadGeneric of(MethodType targetType, int spreadCount) {
+ if (targetType != targetType.generic())
+ throw new UnsupportedOperationException("NYI type="+targetType);
+ MethodTypeForm form = targetType.form();
+ int outcount = form.parameterCount();
+ assert(spreadCount <= outcount);
+ SpreadGeneric[] spreadGens = form.spreadGeneric;
+ if (spreadGens == null)
+ form.spreadGeneric = spreadGens = new SpreadGeneric[outcount+1];
+ SpreadGeneric spreadGen = spreadGens[spreadCount];
+ if (spreadGen == null)
+ spreadGens[spreadCount] = spreadGen = new SpreadGeneric(form.erasedType(), spreadCount);
+ return spreadGen;
+ }
+
+ public String toString() {
+ return getClass().getSimpleName()+targetType+"["+spreadCount+"]";
+ }
+
+ // This mini-api is called from an Adapter to manage the spread.
+ /** A check/coercion that happens once before any selections. */
+ protected Object check(Object av, int n) {
+ checkSpreadArgument(av, n);
+ return av;
+ }
+
+ /** The selection operator for spreading; note that it takes Object not Object[]. */
+ protected Object select(Object av, int n) {
+ return ((Object[])av)[n];
+ }
+ /*
+ protected int select_I(Object av, int n) {
+ // maybe return ((int[])select)[n]
+ throw new UnsupportedOperationException("subclass resp.");
+ }
+ protected int select_J(Object av, int n) {
+ // maybe return ((long[])select)[n]
+ throw new UnsupportedOperationException("subclass resp.");
+ }
+ // */
+
+ /* Create an adapter that handles spreading calls for the given type. */
+ static Adapter findAdapter(SpreadGeneric outer, MethodHandle[] ep) {
+ MethodType targetType = outer.targetType;
+ int spreadCount = outer.spreadCount;
+ int outargs = targetType.parameterCount();
+ int inargs = outargs - spreadCount;
+ if (inargs < 0) return null;
+ MethodType entryType = MethodType.genericMethodType(inargs + 1); // 1 for av
+ String cname1 = "S" + outargs;
+ String[] cnames = { cname1 };
+ String iname = "invoke_S"+spreadCount;
+ // e.g., D5I2, D5, L5I2, L5; invoke_D5
+ for (String cname : cnames) {
+ Class<? extends Adapter> acls = Adapter.findSubClass(cname);
+ if (acls == null) continue;
+ // see if it has the required invoke method
+ MethodHandle entryPoint = null;
+ try {
+ entryPoint = IMPL_LOOKUP.findSpecial(acls, iname, entryType, acls);
+ } catch (ReflectiveOperationException ex) {
+ }
+ if (entryPoint == null) continue;
+ Constructor<? extends Adapter> ctor = null;
+ try {
+ ctor = acls.getDeclaredConstructor(SpreadGeneric.class);
+ } catch (NoSuchMethodException ex) {
+ } catch (SecurityException ex) {
+ }
+ if (ctor == null) continue;
+ try {
+ // Produce an instance configured as a prototype.
+ Adapter ad = ctor.newInstance(outer);
+ ep[0] = entryPoint;
+ return ad;
+ } catch (IllegalArgumentException ex) {
+ } catch (InvocationTargetException wex) {
+ Throwable ex = wex.getTargetException();
+ if (ex instanceof Error) throw (Error)ex;
+ if (ex instanceof RuntimeException) throw (RuntimeException)ex;
+ } catch (InstantiationException ex) {
+ } catch (IllegalAccessException ex) {
+ }
+ }
+ return null;
+ }
+
+ static Adapter buildAdapterFromBytecodes(MethodType targetType,
+ int spreadCount, MethodHandle[] ep) {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ /**
+ * This adapter takes some untyped arguments, and returns an untyped result.
+ * Internally, it applies the invoker to the target, which causes the
+ * objects to be unboxed; the result is a raw type in L/I/J/F/D.
+ * This result is passed to convert, which is responsible for
+ * converting the raw result into a boxed object.
+ * The invoker is kept separate from the target because it can be
+ * generated once per type erasure family, and reused across adapters.
+ */
+ static abstract class Adapter extends BoundMethodHandle {
+ /*
+ * class X<<R,int M,int N>> extends Adapter {
+ * (Object**N)=>R target;
+ * static int S = N-M;
+ * Object invoke(Object**M a, Object v) = target(a..., v[0]...v[S-1]);
+ * }
+ */
+ protected final SpreadGeneric outer;
+ protected final MethodHandle target; // (any**N) => R
+
+ @Override
+ public String toString() {
+ return addTypeString(target, this);
+ }
+
+ static final MethodHandle NO_ENTRY = ValueConversions.identity();
+
+ protected boolean isPrototype() { return target == null; }
+ protected Adapter(SpreadGeneric outer) {
+ super(NO_ENTRY);
+ this.outer = outer;
+ this.target = null;
+ assert(isPrototype());
+ }
+
+ protected Adapter(SpreadGeneric outer, MethodHandle target) {
+ super(outer.entryPoint);
+ this.outer = outer;
+ this.target = target;
+ }
+
+ /** Make a copy of self, with new fields. */
+ protected abstract Adapter makeInstance(SpreadGeneric outer, MethodHandle target);
+ // { return new ThisType(outer, target); }
+
+ protected Object check(Object av, int n) {
+ return outer.check(av, n);
+ }
+ protected Object select(Object av, int n) {
+ return outer.select(av, n);
+ }
+
+ static private final String CLASS_PREFIX; // "java.lang.invoke.SpreadGeneric$"
+ static {
+ String aname = Adapter.class.getName();
+ String sname = Adapter.class.getSimpleName();
+ if (!aname.endsWith(sname)) throw new InternalError();
+ CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
+ }
+ /** Find a sibing class of Adapter. */
+ static Class<? extends Adapter> findSubClass(String name) {
+ String cname = Adapter.CLASS_PREFIX + name;
+ try {
+ return Class.forName(cname).asSubclass(Adapter.class);
+ } catch (ClassNotFoundException ex) {
+ return null;
+ } catch (ClassCastException ex) {
+ return null;
+ }
+ }
+ }
+
+ /* generated classes follow this pattern:
+ static class xS2 extends Adapter {
+ protected xS2(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected xS2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected xS2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new xS2(outer, t); }
+ protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av,0);
+ return target.invokeExact(a0, a1)); }
+ protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av,1);
+ return target.invokeExact(a0,
+ super.select(av,0)); }
+ protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av,1);
+ return target.invokeExact(
+ super.select(av,0), super.select(av,1)); }
+ }
+ // */
+
+/*
+: SHELL; n=SpreadGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
+//{{{
+import java.util.*;
+class genclasses {
+ static String[][] TEMPLATES = { {
+ "@for@ N=0..10",
+ " //@each-cat@",
+ " static class @cat@ extends Adapter {",
+ " protected @cat@(SpreadGeneric outer) { super(outer); } // to build prototype",
+ " protected @cat@(SpreadGeneric outer, MethodHandle t) { super(outer, t); }",
+ " protected @cat@ makeInstance(SpreadGeneric outer, MethodHandle t) { return new @cat@(outer, t); }",
+ " protected Object invoke_S0(@Tvav,@Object av) throws Throwable { av = super.check(av, 0);",
+ " return target.invokeExact(@av@); }",
+ " //@each-S@",
+ " protected Object invoke_S@S@(@Tvav,@Object av) throws Throwable { av = super.check(av, @S@);",
+ " return target.invokeExact(@av,@@sv@); }",
+ " //@end-S@",
+ " }",
+ } };
+ static final String NEWLINE_INDENT = "\n ";
+ enum VAR {
+ cat, N, S, av, av_, Tvav_, sv;
+ public final String pattern = "@"+toString().replace('_','.')+"@";
+ public String binding = toString();
+ static void makeBindings(boolean topLevel, int outargs, int spread) {
+ int inargs = outargs - spread;
+ VAR.cat.binding = "S"+outargs;
+ VAR.N.binding = String.valueOf(outargs); // outgoing arg count
+ VAR.S.binding = String.valueOf(spread); // spread count
+ String[] av = new String[inargs];
+ String[] Tvav = new String[inargs];
+ for (int i = 0; i < inargs; i++) {
+ av[i] = arg(i);
+ Tvav[i] = param("Object", av[i]);
+ }
+ VAR.av.binding = comma(av);
+ VAR.av_.binding = comma(av, ", ");
+ VAR.Tvav_.binding = comma(Tvav, ", ");
+ String[] sv = new String[spread];
+ for (int i = 0; i < spread; i++) {
+ String spc = "";
+ if (i % 4 == 0) spc = NEWLINE_INDENT;
+ sv[i] = spc+"super.select(av,"+i+")";
+ }
+ VAR.sv.binding = comma(sv);
+ }
+ static String arg(int i) { return "a"+i; }
+ static String param(String t, String a) { return t+" "+a; }
+ static String comma(String[] v) { return comma(v, ""); }
+ static String comma(String[] v, String sep) {
+ if (v.length == 0) return "";
+ String res = v[0];
+ for (int i = 1; i < v.length; i++) res += ", "+v[i];
+ return res + sep;
+ }
+ static String transform(String string) {
+ for (VAR var : values())
+ string = string.replaceAll(var.pattern, var.binding);
+ return string;
+ }
+ }
+ static String[] stringsIn(String[] strings, int beg, int end) {
+ return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
+ }
+ static String[] stringsBefore(String[] strings, int pos) {
+ return stringsIn(strings, 0, pos);
+ }
+ static String[] stringsAfter(String[] strings, int pos) {
+ return stringsIn(strings, pos, strings.length);
+ }
+ static int indexAfter(String[] strings, int pos, String tag) {
+ return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
+ }
+ static int indexBefore(String[] strings, int pos, String tag) {
+ for (int i = pos, end = strings.length; ; i++) {
+ if (i == end || strings[i].endsWith(tag)) return i;
+ }
+ }
+ static int MIN_ARITY, MAX_ARITY;
+ public static void main(String... av) {
+ for (String[] template : TEMPLATES) {
+ int forLinesLimit = indexBefore(template, 0, "@each-cat@");
+ String[] forLines = stringsBefore(template, forLinesLimit);
+ template = stringsAfter(template, forLinesLimit);
+ for (String forLine : forLines)
+ expandTemplate(forLine, template);
+ }
+ }
+ static void expandTemplate(String forLine, String[] template) {
+ String[] params = forLine.split("[^0-9]+");
+ if (params[0].length() == 0) params = stringsAfter(params, 1);
+ System.out.println("//params="+Arrays.asList(params));
+ int pcur = 0;
+ MIN_ARITY = Integer.valueOf(params[pcur++]);
+ MAX_ARITY = Integer.valueOf(params[pcur++]);
+ if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
+ for (int outargs = MIN_ARITY; outargs <= MAX_ARITY; outargs++) {
+ expandTemplate(template, true, outargs, 0);
+ }
+ }
+ static void expandTemplate(String[] template, boolean topLevel, int outargs, int spread) {
+ VAR.makeBindings(topLevel, outargs, spread);
+ for (int i = 0; i < template.length; i++) {
+ String line = template[i];
+ if (line.endsWith("@each-cat@")) {
+ // ignore
+ } else if (line.endsWith("@each-S@")) {
+ int blockEnd = indexAfter(template, i, "@end-S@");
+ String[] block = stringsIn(template, i+1, blockEnd-1);
+ for (int spread1 = spread+1; spread1 <= outargs; spread1++)
+ expandTemplate(block, false, outargs, spread1);
+ VAR.makeBindings(topLevel, outargs, spread);
+ i = blockEnd-1; continue;
+ } else {
+ System.out.println(VAR.transform(line));
+ }
+ }
+ }
+}
+//}}} */
+//params=[0, 10]
+ static class S0 extends Adapter {
+ protected S0(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S0(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S0 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S0(outer, t); }
+ protected Object invoke_S0(Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(); }
+ }
+ static class S1 extends Adapter {
+ protected S1(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S1(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S1 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S1(outer, t); }
+ protected Object invoke_S0(Object a0, Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(a0); }
+ protected Object invoke_S1(Object av) throws Throwable { av = super.check(av, 1);
+ return target.invokeExact(
+ super.select(av,0)); }
+ }
+ static class S2 extends Adapter {
+ protected S2(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S2(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S2 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S2(outer, t); }
+ protected Object invoke_S0(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(a0, a1); }
+ protected Object invoke_S1(Object a0, Object av) throws Throwable { av = super.check(av, 1);
+ return target.invokeExact(a0,
+ super.select(av,0)); }
+ protected Object invoke_S2(Object av) throws Throwable { av = super.check(av, 2);
+ return target.invokeExact(
+ super.select(av,0), super.select(av,1)); }
+ }
+ static class S3 extends Adapter {
+ protected S3(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S3(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S3 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S3(outer, t); }
+ protected Object invoke_S0(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(a0, a1, a2); }
+ protected Object invoke_S1(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 1);
+ return target.invokeExact(a0, a1,
+ super.select(av,0)); }
+ protected Object invoke_S2(Object a0, Object av) throws Throwable { av = super.check(av, 2);
+ return target.invokeExact(a0,
+ super.select(av,0), super.select(av,1)); }
+ protected Object invoke_S3(Object av) throws Throwable { av = super.check(av, 3);
+ return target.invokeExact(
+ super.select(av,0), super.select(av,1), super.select(av,2)); }
+ }
+ static class S4 extends Adapter {
+ protected S4(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S4(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S4 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S4(outer, t); }
+ protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(a0, a1, a2, a3); }
+ protected Object invoke_S1(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 1);
+ return target.invokeExact(a0, a1, a2,
+ super.select(av,0)); }
+ protected Object invoke_S2(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 2);
+ return target.invokeExact(a0, a1,
+ super.select(av,0), super.select(av,1)); }
+ protected Object invoke_S3(Object a0, Object av) throws Throwable { av = super.check(av, 3);
+ return target.invokeExact(a0,
+ super.select(av,0), super.select(av,1), super.select(av,2)); }
+ protected Object invoke_S4(Object av) throws Throwable { av = super.check(av, 4);
+ return target.invokeExact(
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+ }
+ static class S5 extends Adapter {
+ protected S5(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S5(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S5 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S5(outer, t); }
+ protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(a0, a1, a2, a3, a4); }
+ protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 1);
+ return target.invokeExact(a0, a1, a2, a3,
+ super.select(av,0)); }
+ protected Object invoke_S2(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 2);
+ return target.invokeExact(a0, a1, a2,
+ super.select(av,0), super.select(av,1)); }
+ protected Object invoke_S3(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 3);
+ return target.invokeExact(a0, a1,
+ super.select(av,0), super.select(av,1), super.select(av,2)); }
+ protected Object invoke_S4(Object a0, Object av) throws Throwable { av = super.check(av, 4);
+ return target.invokeExact(a0,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+ protected Object invoke_S5(Object av) throws Throwable { av = super.check(av, 5);
+ return target.invokeExact(
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4)); }
+ }
+ static class S6 extends Adapter {
+ protected S6(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S6(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S6 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S6(outer, t); }
+ protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5); }
+ protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 1);
+ return target.invokeExact(a0, a1, a2, a3, a4,
+ super.select(av,0)); }
+ protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 2);
+ return target.invokeExact(a0, a1, a2, a3,
+ super.select(av,0), super.select(av,1)); }
+ protected Object invoke_S3(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 3);
+ return target.invokeExact(a0, a1, a2,
+ super.select(av,0), super.select(av,1), super.select(av,2)); }
+ protected Object invoke_S4(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 4);
+ return target.invokeExact(a0, a1,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+ protected Object invoke_S5(Object a0, Object av) throws Throwable { av = super.check(av, 5);
+ return target.invokeExact(a0,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4)); }
+ protected Object invoke_S6(Object av) throws Throwable { av = super.check(av, 6);
+ return target.invokeExact(
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5)); }
+ }
+ static class S7 extends Adapter {
+ protected S7(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S7(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S7 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S7(outer, t); }
+ protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 1);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5,
+ super.select(av,0)); }
+ protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 2);
+ return target.invokeExact(a0, a1, a2, a3, a4,
+ super.select(av,0), super.select(av,1)); }
+ protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 3);
+ return target.invokeExact(a0, a1, a2, a3,
+ super.select(av,0), super.select(av,1), super.select(av,2)); }
+ protected Object invoke_S4(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 4);
+ return target.invokeExact(a0, a1, a2,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+ protected Object invoke_S5(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 5);
+ return target.invokeExact(a0, a1,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4)); }
+ protected Object invoke_S6(Object a0, Object av) throws Throwable { av = super.check(av, 6);
+ return target.invokeExact(a0,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5)); }
+ protected Object invoke_S7(Object av) throws Throwable { av = super.check(av, 7);
+ return target.invokeExact(
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5), super.select(av,6)); }
+ }
+ static class S8 extends Adapter {
+ protected S8(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S8(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S8 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S8(outer, t); }
+ protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 1);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
+ super.select(av,0)); }
+ protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 2);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5,
+ super.select(av,0), super.select(av,1)); }
+ protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 3);
+ return target.invokeExact(a0, a1, a2, a3, a4,
+ super.select(av,0), super.select(av,1), super.select(av,2)); }
+ protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 4);
+ return target.invokeExact(a0, a1, a2, a3,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+ protected Object invoke_S5(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 5);
+ return target.invokeExact(a0, a1, a2,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4)); }
+ protected Object invoke_S6(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 6);
+ return target.invokeExact(a0, a1,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5)); }
+ protected Object invoke_S7(Object a0, Object av) throws Throwable { av = super.check(av, 7);
+ return target.invokeExact(a0,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5), super.select(av,6)); }
+ protected Object invoke_S8(Object av) throws Throwable { av = super.check(av, 8);
+ return target.invokeExact(
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
+ }
+ static class S9 extends Adapter {
+ protected S9(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S9(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S9 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S9(outer, t); }
+ protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 1);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7,
+ super.select(av,0)); }
+ protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 2);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
+ super.select(av,0), super.select(av,1)); }
+ protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 3);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5,
+ super.select(av,0), super.select(av,1), super.select(av,2)); }
+ protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 4);
+ return target.invokeExact(a0, a1, a2, a3, a4,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+ protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 5);
+ return target.invokeExact(a0, a1, a2, a3,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4)); }
+ protected Object invoke_S6(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 6);
+ return target.invokeExact(a0, a1, a2,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5)); }
+ protected Object invoke_S7(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 7);
+ return target.invokeExact(a0, a1,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5), super.select(av,6)); }
+ protected Object invoke_S8(Object a0, Object av) throws Throwable { av = super.check(av, 8);
+ return target.invokeExact(a0,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
+ protected Object invoke_S9(Object av) throws Throwable { av = super.check(av, 9);
+ return target.invokeExact(
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
+ super.select(av,8)); }
+ }
+ static class S10 extends Adapter {
+ protected S10(SpreadGeneric outer) { super(outer); } // to build prototype
+ protected S10(SpreadGeneric outer, MethodHandle t) { super(outer, t); }
+ protected S10 makeInstance(SpreadGeneric outer, MethodHandle t) { return new S10(outer, t); }
+ protected Object invoke_S0(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9, Object av) throws Throwable { av = super.check(av, 0);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_S1(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object av) throws Throwable { av = super.check(av, 1);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7, a8,
+ super.select(av,0)); }
+ protected Object invoke_S2(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object av) throws Throwable { av = super.check(av, 2);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7,
+ super.select(av,0), super.select(av,1)); }
+ protected Object invoke_S3(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object av) throws Throwable { av = super.check(av, 3);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5, a6,
+ super.select(av,0), super.select(av,1), super.select(av,2)); }
+ protected Object invoke_S4(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object av) throws Throwable { av = super.check(av, 4);
+ return target.invokeExact(a0, a1, a2, a3, a4, a5,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3)); }
+ protected Object invoke_S5(Object a0, Object a1, Object a2, Object a3, Object a4, Object av) throws Throwable { av = super.check(av, 5);
+ return target.invokeExact(a0, a1, a2, a3, a4,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4)); }
+ protected Object invoke_S6(Object a0, Object a1, Object a2, Object a3, Object av) throws Throwable { av = super.check(av, 6);
+ return target.invokeExact(a0, a1, a2, a3,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5)); }
+ protected Object invoke_S7(Object a0, Object a1, Object a2, Object av) throws Throwable { av = super.check(av, 7);
+ return target.invokeExact(a0, a1, a2,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5), super.select(av,6)); }
+ protected Object invoke_S8(Object a0, Object a1, Object av) throws Throwable { av = super.check(av, 8);
+ return target.invokeExact(a0, a1,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7)); }
+ protected Object invoke_S9(Object a0, Object av) throws Throwable { av = super.check(av, 9);
+ return target.invokeExact(a0,
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
+ super.select(av,8)); }
+ protected Object invoke_S10(Object av) throws Throwable { av = super.check(av, 10);
+ return target.invokeExact(
+ super.select(av,0), super.select(av,1), super.select(av,2), super.select(av,3),
+ super.select(av,4), super.select(av,5), super.select(av,6), super.select(av,7),
+ super.select(av,8), super.select(av,9)); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/SwitchPoint.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * <p>
+ * A {@code SwitchPoint} is an object which can publish state transitions to other threads.
+ * A switch point is initially in the <em>valid</em> state, but may at any time be
+ * changed to the <em>invalid</em> state. Invalidation cannot be reversed.
+ * A switch point can combine a <em>guarded pair</em> of method handles into a
+ * <em>guarded delegator</em>.
+ * The guarded delegator is a method handle which delegates to one of the old method handles.
+ * The state of the switch point determines which of the two gets the delegation.
+ * <p>
+ * A single switch point may be used to control any number of method handles.
+ * (Indirectly, therefore, it can control any number of call sites.)
+ * This is done by using the single switch point as a factory for combining
+ * any number of guarded method handle pairs into guarded delegators.
+ * <p>
+ * When a guarded delegator is created from a guarded pair, the pair
+ * is wrapped in a new method handle {@code M},
+ * which is permanently associated with the switch point that created it.
+ * Each pair consists of a target {@code T} and a fallback {@code F}.
+ * While the switch point is valid, invocations to {@code M} are delegated to {@code T}.
+ * After it is invalidated, invocations are delegated to {@code F}.
+ * <p>
+ * Invalidation is global and immediate, as if the switch point contained a
+ * volatile boolean variable consulted on every call to {@code M}.
+ * The invalidation is also permanent, which means the switch point
+ * can change state only once.
+ * The switch point will always delegate to {@code F} after being invalidated.
+ * At that point {@code guardWithTest} may ignore {@code T} and return {@code F}.
+ * <p>
+ * Here is an example of a switch point in action:
+ * <blockquote><pre>
+MethodType MT_str2 = MethodType.methodType(String.class, String.class);
+MethodHandle MH_strcat = MethodHandles.lookup()
+ .findVirtual(String.class, "concat", MT_str2);
+SwitchPoint spt = new SwitchPoint();
+// the following steps may be repeated to re-use the same switch point:
+MethodHandle worker1 = strcat;
+MethodHandle worker2 = MethodHandles.permuteArguments(strcat, MT_str2, 1, 0);
+MethodHandle worker = spt.guardWithTest(worker1, worker2);
+assertEquals("method", (String) worker.invokeExact("met", "hod"));
+SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
+assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
+ * </pre></blockquote>
+ * <p style="font-size:smaller;">
+ * <em>Discussion:</em>
+ * Switch points are useful without subclassing. They may also be subclassed.
+ * This may be useful in order to associate application-specific invalidation logic
+ * with the switch point.
+ * Notice that there is no permanent association between a switch point and
+ * the method handles it produces and consumes.
+ * The garbage collector may collect method handles produced or consumed
+ * by a switch point independently of the lifetime of the switch point itself.
+ * <p style="font-size:smaller;">
+ * <em>Implementation Note:</em>
+ * A switch point behaves as if implemented on top of {@link MutableCallSite},
+ * approximately as follows:
+ * <blockquote><pre>
+public class SwitchPoint {
+ private static final MethodHandle
+ K_true = MethodHandles.constant(boolean.class, true),
+ K_false = MethodHandles.constant(boolean.class, false);
+ private final MutableCallSite mcs;
+ private final MethodHandle mcsInvoker;
+ public SwitchPoint() {
+ this.mcs = new MutableCallSite(K_true);
+ this.mcsInvoker = mcs.dynamicInvoker();
+ }
+ public MethodHandle guardWithTest(
+ MethodHandle target, MethodHandle fallback) {
+ // Note: mcsInvoker is of type ()boolean.
+ // Target and fallback may take any arguments, but must have the same type.
+ return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
+ }
+ public static void invalidateAll(SwitchPoint[] spts) {
+ List<MutableCallSite> mcss = new ArrayList<>();
+ for (SwitchPoint spt : spts) mcss.add(spt.mcs);
+ for (MutableCallSite mcs : mcss) mcs.setTarget(K_false);
+ MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
+ }
+}
+ * </pre></blockquote>
+ * @author Remi Forax, JSR 292 EG
+ */
+public class SwitchPoint {
+ private static final MethodHandle
+ K_true = MethodHandles.constant(boolean.class, true),
+ K_false = MethodHandles.constant(boolean.class, false);
+
+ private final MutableCallSite mcs;
+ private final MethodHandle mcsInvoker;
+
+ /**
+ * Creates a new switch point.
+ */
+ public SwitchPoint() {
+ this.mcs = new MutableCallSite(K_true);
+ this.mcsInvoker = mcs.dynamicInvoker();
+ }
+
+ /**
+ * Returns a method handle which always delegates either to the target or the fallback.
+ * The method handle will delegate to the target exactly as long as the switch point is valid.
+ * After that, it will permanently delegate to the fallback.
+ * <p>
+ * The target and fallback must be of exactly the same method type,
+ * and the resulting combined method handle will also be of this type.
+ *
+ * @param target the method handle selected by the switch point as long as it is valid
+ * @param fallback the method handle selected by the switch point after it is invalidated
+ * @return a combined method handle which always calls either the target or fallback
+ * @throws NullPointerException if either argument is null
+ * @see MethodHandles#guardWithTest
+ */
+ public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback) {
+ if (mcs.getTarget() == K_false)
+ return fallback; // already invalid
+ return MethodHandles.guardWithTest(mcsInvoker, target, fallback);
+ }
+
+ /**
+ * Sets all of the given switch points into the invalid state.
+ * After this call executes, no thread will observe any of the
+ * switch points to be in a valid state.
+ * <p>
+ * This operation is likely to be expensive and should be used sparingly.
+ * If possible, it should be buffered for batch processing on sets of switch points.
+ * <p>
+ * If {@code switchPoints} contains a null element,
+ * a {@code NullPointerException} will be raised.
+ * In this case, some non-null elements in the array may be
+ * processed before the method returns abnormally.
+ * Which elements these are (if any) is implementation-dependent.
+ *
+ * <p style="font-size:smaller;">
+ * <em>Discussion:</em>
+ * For performance reasons, {@code invalidateAll} is not a virtual method
+ * on a single switch point, but rather applies to a set of switch points.
+ * Some implementations may incur a large fixed overhead cost
+ * for processing one or more invalidation operations,
+ * but a small incremental cost for each additional invalidation.
+ * In any case, this operation is likely to be costly, since
+ * other threads may have to be somehow interrupted
+ * in order to make them notice the updated switch point state.
+ * However, it may be observed that a single call to invalidate
+ * several switch points has the same formal effect as many calls,
+ * each on just one of the switch points.
+ *
+ * <p style="font-size:smaller;">
+ * <em>Implementation Note:</em>
+ * Simple implementations of {@code SwitchPoint} may use
+ * a private {@link MutableCallSite} to publish the state of a switch point.
+ * In such an implementation, the {@code invalidateAll} method can
+ * simply change the call site's target, and issue one call to
+ * {@linkplain MutableCallSite#syncAll synchronize} all the
+ * private call sites.
+ *
+ * @param switchPoints an array of call sites to be synchronized
+ * @throws NullPointerException if the {@code switchPoints} array reference is null
+ * or the array contains a null
+ */
+ public static void invalidateAll(SwitchPoint[] switchPoints) {
+ if (switchPoints.length == 0) return;
+ MutableCallSite[] sites = new MutableCallSite[switchPoints.length];
+ for (int i = 0; i < switchPoints.length; i++) {
+ SwitchPoint spt = switchPoints[i];
+ if (spt == null) break; // MSC.syncAll will trigger a NPE
+ sites[i] = spt.mcs;
+ spt.mcs.setTarget(K_false);
+ }
+ MutableCallSite.syncAll(sites);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/ToGeneric.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,1062 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.Wrapper;
+import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
+
+/**
+ * Adapters which mediate between incoming calls which are not generic
+ * and outgoing calls which are. Any call can be represented generically
+ * boxing up its arguments, and (on return) unboxing the return value.
+ * <p>
+ * A call is "generic" (in MethodHandle terms) if its MethodType features
+ * only Object arguments. A non-generic call therefore features
+ * primitives and/or reference types other than Object.
+ * An adapter has types for its incoming and outgoing calls.
+ * The incoming call type is simply determined by the adapter's type
+ * (the MethodType it presents to callers). The outgoing call type
+ * is determined by the adapter's target (a MethodHandle that the adapter
+ * either binds internally or else takes as a leading argument).
+ * (To stretch the term, adapter-like method handles may have multiple
+ * targets or be polymorphic across multiple call types.)
+ * @author jrose
+ */
+class ToGeneric {
+ // type for the incoming call (may be erased)
+ private final MethodType entryType;
+ // incoming type with primitives moved to the end and turned to int/long
+ private final MethodType rawEntryType;
+ // adapter for the erased type
+ private final Adapter adapter;
+ // entry point for adapter (Adapter mh, a...) => ...
+ private final MethodHandle entryPoint;
+ // permutation of arguments for primsAtEndType
+ private final int[] primsAtEndOrder;
+ // optional final argument list conversions (at least, invokes the target)
+ private final MethodHandle invoker;
+ // conversion which unboxes a primitive return value
+ private final MethodHandle returnConversion;
+
+ /** Compute and cache information common to all generifying (boxing) adapters
+ * that implement members of the erasure-family of the given erased type.
+ */
+ private ToGeneric(MethodType entryType) {
+ assert(entryType.erase() == entryType); // for now
+ // incoming call will first "forget" all reference types except Object
+ this.entryType = entryType;
+ MethodHandle invoker0 = entryType.generic().invokers().exactInvoker();
+ MethodType rawEntryTypeInit;
+ Adapter ad = findAdapter(rawEntryTypeInit = entryType);
+ if (ad != null) {
+ // Immediate hit to exactly the adapter we want,
+ // with no monkeying around with primitive types.
+ this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
+ this.rawEntryType = rawEntryTypeInit;
+ this.adapter = ad;
+ this.entryPoint = ad.prototypeEntryPoint();
+ this.primsAtEndOrder = null;
+ this.invoker = invoker0;
+ return;
+ }
+
+ // next, it will reorder primitives after references
+ MethodType primsAtEnd = entryType.form().primsAtEnd();
+ // at the same time, it will "forget" all primitive types except int/long
+ this.primsAtEndOrder = MethodTypeForm.primsAtEndOrder(entryType);
+ if (primsAtEndOrder != null) {
+ // reordering is required; build on top of a simpler ToGeneric
+ ToGeneric va2 = ToGeneric.of(primsAtEnd);
+ this.adapter = va2.adapter;
+ if (true) throw new UnsupportedOperationException("NYI: primitive parameters must follow references; entryType = "+entryType);
+ this.entryPoint = MethodHandleImpl.convertArguments(
+ va2.entryPoint, primsAtEnd, entryType, primsAtEndOrder);
+ // example: for entryType of (int,Object,Object), the reordered
+ // type is (Object,Object,int) and the order is {1,2,0},
+ // and putPAE is (mh,int0,obj1,obj2) => mh.invokeExact(obj1,obj2,int0)
+ return;
+ }
+
+ // after any needed argument reordering, it will reinterpret
+ // primitive arguments according to their "raw" types int/long
+ MethodType intsAtEnd = primsAtEnd.form().primsAsInts();
+ ad = findAdapter(rawEntryTypeInit = intsAtEnd);
+ MethodHandle rawEntryPoint;
+ if (ad != null) {
+ rawEntryPoint = ad.prototypeEntryPoint();
+ } else {
+ // Perhaps the adapter is available only for longs.
+ // If so, we can use it, but there will have to be a little
+ // more stack motion on each call.
+ MethodType longsAtEnd = primsAtEnd.form().primsAsLongs();
+ ad = findAdapter(rawEntryTypeInit = longsAtEnd);
+ if (ad != null) {
+ MethodType eptWithLongs = longsAtEnd.insertParameterTypes(0, ad.getClass());
+ MethodType eptWithInts = intsAtEnd.insertParameterTypes(0, ad.getClass());
+ rawEntryPoint = ad.prototypeEntryPoint();
+ MethodType midType = eptWithLongs; // will change longs to ints
+ for (int i = 0, nargs = midType.parameterCount(); i < nargs; i++) {
+ if (midType.parameterType(i) != eptWithInts.parameterType(i)) {
+ assert(midType.parameterType(i) == long.class);
+ assert(eptWithInts.parameterType(i) == int.class);
+ MethodType nextType = midType.changeParameterType(i, int.class);
+ rawEntryPoint = MethodHandleImpl.convertArguments(
+ rawEntryPoint, nextType, midType, null);
+ midType = nextType;
+ }
+ }
+ assert(midType == eptWithInts);
+ } else {
+ // If there is no statically compiled adapter,
+ // build one by means of dynamic bytecode generation.
+ ad = buildAdapterFromBytecodes(rawEntryTypeInit = intsAtEnd);
+ rawEntryPoint = ad.prototypeEntryPoint();
+ }
+ }
+ MethodType tepType = entryType.insertParameterTypes(0, ad.getClass());
+ this.entryPoint =
+ AdapterMethodHandle.makeRetypeRaw(tepType, rawEntryPoint);
+ if (this.entryPoint == null)
+ throw new UnsupportedOperationException("cannot retype to "+entryType
+ +" from "+rawEntryPoint.type().dropParameterTypes(0, 1));
+ this.returnConversion = computeReturnConversion(entryType, rawEntryTypeInit, false);
+ this.rawEntryType = rawEntryTypeInit;
+ this.adapter = ad;
+ this.invoker = makeRawArgumentFilter(invoker0, rawEntryTypeInit, entryType);
+ }
+
+ /** A generic argument list will be created by a call of type 'raw'.
+ * The values need to be reboxed for to match 'cooked'.
+ * Do this on the fly.
+ */
+ // TO DO: Use a generic argument converter in a different file
+ static MethodHandle makeRawArgumentFilter(MethodHandle invoker,
+ MethodType raw, MethodType cooked) {
+ MethodHandle filteredInvoker = null;
+ for (int i = 0, nargs = raw.parameterCount(); i < nargs; i++) {
+ Class<?> src = raw.parameterType(i);
+ Class<?> dst = cooked.parameterType(i);
+ if (src == dst) continue;
+ assert(src.isPrimitive() && dst.isPrimitive());
+ if (filteredInvoker == null) {
+ filteredInvoker =
+ AdapterMethodHandle.makeCheckCast(
+ invoker.type().generic(), invoker, 0, MethodHandle.class);
+ if (filteredInvoker == null) throw new UnsupportedOperationException("NYI");
+ }
+ MethodHandle reboxer = ValueConversions.rebox(dst, false);
+ filteredInvoker = FilterGeneric.makeArgumentFilter(1+i, reboxer, filteredInvoker);
+ if (filteredInvoker == null) throw new InternalError();
+ }
+ if (filteredInvoker == null) return invoker;
+ return AdapterMethodHandle.makeRetypeOnly(invoker.type(), filteredInvoker);
+ }
+
+ /**
+ * Caller will be expecting a result from a call to {@code type},
+ * while the internal adapter entry point is rawEntryType.
+ * Also, the internal target method will be returning a boxed value,
+ * as an untyped object.
+ * <p>
+ * Produce a value converter which will be typed to convert from
+ * {@code Object} to the return value of {@code rawEntryType}, and will
+ * in fact ensure that the value is compatible with the return type of
+ * {@code type}.
+ */
+ private static MethodHandle computeReturnConversion(
+ MethodType type, MethodType rawEntryType, boolean mustCast) {
+ Class<?> tret = type.returnType();
+ Class<?> rret = rawEntryType.returnType();
+ if (mustCast || !tret.isPrimitive()) {
+ assert(!tret.isPrimitive());
+ assert(!rret.isPrimitive());
+ if (rret == Object.class && !mustCast)
+ return null;
+ return ValueConversions.cast(tret, false);
+ } else if (tret == rret) {
+ return ValueConversions.unbox(tret, false);
+ } else {
+ assert(rret.isPrimitive());
+ assert(tret == double.class ? rret == long.class : rret == int.class);
+ return ValueConversions.unboxRaw(tret, false);
+ }
+ }
+
+ Adapter makeInstance(MethodType type, MethodHandle genericTarget) {
+ genericTarget.getClass(); // check for NPE
+ MethodHandle convert = returnConversion;
+ if (primsAtEndOrder != null)
+ // reorder arguments passed to genericTarget, if primsAtEndOrder
+ throw new UnsupportedOperationException("NYI");
+ if (type == entryType) {
+ if (convert == null) convert = ValueConversions.identity();
+ return adapter.makeInstance(entryPoint, invoker, convert, genericTarget);
+ }
+ // my erased-type is not exactly the same as the desired type
+ assert(type.erase() == entryType); // else we are busted
+ if (convert == null)
+ convert = computeReturnConversion(type, rawEntryType, true);
+ // retype erased reference arguments (the cast makes it safe to do this)
+ MethodType tepType = type.insertParameterTypes(0, adapter.getClass());
+ MethodHandle typedEntryPoint =
+ AdapterMethodHandle.makeRetypeRaw(tepType, entryPoint);
+ return adapter.makeInstance(typedEntryPoint, invoker, convert, genericTarget);
+ }
+
+ /** Build an adapter of the given type, which invokes genericTarget
+ * on the incoming arguments, after boxing as necessary.
+ * The return value is unboxed if necessary.
+ * @param type the required type of the
+ * @param genericTarget the target, which must accept and return only Object values
+ * @return an adapter method handle
+ */
+ public static MethodHandle make(MethodType type, MethodHandle genericTarget) {
+ MethodType gtype = genericTarget.type();
+ if (type.generic() != gtype)
+ throw newIllegalArgumentException("type must be generic");
+ if (type == gtype) return genericTarget;
+ return ToGeneric.of(type).makeInstance(type, genericTarget);
+ }
+
+ /** Return the adapter information for this type's erasure. */
+ static ToGeneric of(MethodType type) {
+ MethodTypeForm form = type.form();
+ ToGeneric toGen = form.toGeneric;
+ if (toGen == null)
+ form.toGeneric = toGen = new ToGeneric(form.erasedType());
+ return toGen;
+ }
+
+ public String toString() {
+ return "ToGeneric"+entryType
+ +(primsAtEndOrder!=null?"[reorder]":"");
+ }
+
+ /* Create an adapter for the given incoming call type. */
+ static Adapter findAdapter(MethodType entryPointType) {
+ MethodTypeForm form = entryPointType.form();
+ Class<?> rtype = entryPointType.returnType();
+ int argc = form.parameterCount();
+ int lac = form.longPrimitiveParameterCount();
+ int iac = form.primitiveParameterCount() - lac;
+ String intsAndLongs = (iac > 0 ? "I"+iac : "")+(lac > 0 ? "J"+lac : "");
+ String rawReturn = String.valueOf(Wrapper.forPrimitiveType(rtype).basicTypeChar());
+ String iname0 = "invoke_"+rawReturn;
+ String iname1 = "invoke";
+ String[] inames = { iname0, iname1 };
+ String cname0 = rawReturn + argc;
+ String cname1 = "A" + argc;
+ String[] cnames = { cname1, cname1+intsAndLongs, cname0, cname0+intsAndLongs };
+ // e.g., D5I2, D5, L5I2, L5
+ for (String cname : cnames) {
+ Class<? extends Adapter> acls = Adapter.findSubClass(cname);
+ if (acls == null) continue;
+ // see if it has the required invoke method
+ for (String iname : inames) {
+ MethodHandle entryPoint = null;
+ try {
+ entryPoint = IMPL_LOOKUP.
+ findSpecial(acls, iname, entryPointType, acls);
+ } catch (ReflectiveOperationException ex) {
+ }
+ if (entryPoint == null) continue;
+ Constructor<? extends Adapter> ctor = null;
+ try {
+ // Prototype builder:
+ ctor = acls.getDeclaredConstructor(MethodHandle.class);
+ } catch (NoSuchMethodException ex) {
+ } catch (SecurityException ex) {
+ }
+ if (ctor == null) continue;
+ try {
+ return ctor.newInstance(entryPoint);
+ } catch (IllegalArgumentException ex) {
+ } catch (InvocationTargetException wex) {
+ Throwable ex = wex.getTargetException();
+ if (ex instanceof Error) throw (Error)ex;
+ if (ex instanceof RuntimeException) throw (RuntimeException)ex;
+ } catch (InstantiationException ex) {
+ } catch (IllegalAccessException ex) {
+ }
+ }
+ }
+ return null;
+ }
+
+ static Adapter buildAdapterFromBytecodes(MethodType entryPointType) {
+ throw new UnsupportedOperationException("NYI");
+ }
+
+ /**
+ * The invoke method takes some particular but unconstrained spread
+ * of raw argument types, and returns a raw return type (in L/I/J/F/D).
+ * Internally, it converts the incoming arguments uniformly into objects.
+ * This series of objects is then passed to the {@code target} method,
+ * which returns a result object. This result is finally converted,
+ * via another method handle {@code convert}, which is responsible for
+ * converting the object result into the raw return value.
+ */
+ static abstract class Adapter extends BoundMethodHandle {
+ /*
+ * class X<<R,A...>> extends Adapter {
+ * Object...=>Object target;
+ * Object=>R convert;
+ * R invoke(A... a...) = convert(invoker(target, a...)))
+ * }
+ */
+ protected final MethodHandle invoker; // (MH, Object...) -> Object
+ protected final MethodHandle target; // Object... -> Object
+ protected final MethodHandle convert; // Object -> R
+
+ @Override
+ public String toString() {
+ return target == null ? "prototype:"+convert : addTypeString(target, this);
+ }
+
+ protected boolean isPrototype() { return target == null; }
+ /* Prototype constructor. */
+ protected Adapter(MethodHandle entryPoint) {
+ super(entryPoint);
+ this.invoker = null;
+ this.convert = entryPoint;
+ this.target = null;
+ assert(isPrototype());
+ }
+ protected MethodHandle prototypeEntryPoint() {
+ if (!isPrototype()) throw new InternalError();
+ return convert;
+ }
+
+ protected Adapter(MethodHandle entryPoint, MethodHandle invoker, MethodHandle convert, MethodHandle target) {
+ super(entryPoint);
+ this.invoker = invoker;
+ this.convert = convert;
+ this.target = target;
+ }
+
+ /** Make a copy of self, with new fields. */
+ protected abstract Adapter makeInstance(MethodHandle entryPoint,
+ MethodHandle invoker, MethodHandle convert, MethodHandle target);
+ // { return new ThisType(entryPoint, convert, target); }
+
+ // Code to run when the arguments (<= 4) have all been boxed.
+ protected Object target() throws Throwable { return invoker.invokeExact(target); }
+ protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); }
+ protected Object target(Object a0, Object a1)
+ throws Throwable { return invoker.invokeExact(target, a0, a1); }
+ protected Object target(Object a0, Object a1, Object a2)
+ throws Throwable { return invoker.invokeExact(target, a0, a1, a2); }
+ protected Object target(Object a0, Object a1, Object a2, Object a3)
+ throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); }
+ /*
+ protected Object target_0(Object... av) throws Throwable { return invoker.invokeExact(target, av); }
+ protected Object target_1(Object a0, Object... av)
+ throws Throwable { return invoker.invokeExact(target, a0, (Object)av); }
+ protected Object target_2(Object a0, Object a1, Object... av)
+ throws Throwable { return invoker.invokeExact(target, a0, a1, (Object)av); }
+ protected Object target_3(Object a0, Object a1, Object a2, Object... av)
+ throws Throwable { return invoker.invokeExact(target, a0, a1, a2, (Object)av); }
+ protected Object target_4(Object a0, Object a1, Object a2, Object a3, Object... av)
+ throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, (Object)av); }
+ // */
+ // (For more than 4 arguments, generate the code in the adapter itself.)
+
+ // Code to run when the generic target has finished and produced a value.
+ protected Object return_L(Object res) throws Throwable { return (Object)convert.invokeExact(res); }
+ protected int return_I(Object res) throws Throwable { return (int) convert.invokeExact(res); }
+ protected long return_J(Object res) throws Throwable { return (long) convert.invokeExact(res); }
+ protected float return_F(Object res) throws Throwable { return (float) convert.invokeExact(res); }
+ protected double return_D(Object res) throws Throwable { return (double)convert.invokeExact(res); }
+
+ static private final String CLASS_PREFIX; // "java.lang.invoke.ToGeneric$"
+ static {
+ String aname = Adapter.class.getName();
+ String sname = Adapter.class.getSimpleName();
+ if (!aname.endsWith(sname)) throw new InternalError();
+ CLASS_PREFIX = aname.substring(0, aname.length() - sname.length());
+ }
+ /** Find a sibing class of Adapter. */
+ static Class<? extends Adapter> findSubClass(String name) {
+ String cname = Adapter.CLASS_PREFIX + name;
+ try {
+ return Class.forName(cname).asSubclass(Adapter.class);
+ } catch (ClassNotFoundException ex) {
+ return null;
+ } catch (ClassCastException ex) {
+ return null;
+ }
+ }
+ }
+
+ /* generated classes follow this pattern:
+ static class A1 extends Adapter {
+ protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
+ protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); }
+ protected Object targetA1(Object a0) throws Throwable { return target(a0); }
+ protected Object targetA1(int a0) throws Throwable { return target(a0); }
+ protected Object targetA1(long a0) throws Throwable { return target(a0); }
+ protected Object invoke_L(Object a0) throws Throwable { return return_L(targetA1(a0)); }
+ protected int invoke_I(Object a0) throws Throwable { return return_I(targetA1(a0)); }
+ protected long invoke_J(Object a0) throws Throwable { return return_J(targetA1(a0)); }
+ protected float invoke_F(Object a0) throws Throwable { return return_F(targetA1(a0)); }
+ protected double invoke_D(Object a0) throws Throwable { return return_D(targetA1(a0)); }
+ protected Object invoke_L(int a0) throws Throwable { return return_L(targetA1(a0)); }
+ protected int invoke_I(int a0) throws Throwable { return return_I(targetA1(a0)); }
+ protected long invoke_J(int a0) throws Throwable { return return_J(targetA1(a0)); }
+ protected float invoke_F(int a0) throws Throwable { return return_F(targetA1(a0)); }
+ protected double invoke_D(int a0) throws Throwable { return return_D(targetA1(a0)); }
+ protected Object invoke_L(long a0) throws Throwable { return return_L(targetA1(a0)); }
+ protected int invoke_I(long a0) throws Throwable { return return_I(targetA1(a0)); }
+ protected long invoke_J(long a0) throws Throwable { return return_J(targetA1(a0)); }
+ protected float invoke_F(long a0) throws Throwable { return return_F(targetA1(a0)); }
+ protected double invoke_D(long a0) throws Throwable { return return_D(targetA1(a0)); }
+ }
+ // */
+
+/*
+: SHELL; n=ToGeneric; cp -p $n.java $n.java-; sed < $n.java- > $n.java+ -e '/{{*{{/,/}}*}}/w /tmp/genclasses.java' -e '/}}*}}/q'; (cd /tmp; javac -d . genclasses.java; java -cp . genclasses) >> $n.java+; echo '}' >> $n.java+; mv $n.java+ $n.java; mv $n.java- $n.java~
+//{{{
+import java.util.*;
+class genclasses {
+ static String[] TYPES = { "Object", "int ", "long ", "float ", "double" };
+ static String[] TCHARS = { "L", "I", "J", "F", "D", "A" };
+ static String[][] TEMPLATES = { {
+ "@for@ arity=0..3 rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
+ "@for@ arity=4..4 rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
+ "@for@ arity=5..5 rcat<=2 nrefs<=99 nints<=99 nlongs<=99",
+ "@for@ arity=6..10 rcat<=2 nrefs<=99 nints=0 nlongs<=99",
+ " //@each-cat@",
+ " static class @cat@ extends Adapter {",
+ " protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
+ " protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }",
+ " protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }",
+ " protected Object target(@Ovav@) throws Throwable { return invoker.invokeExact(target@comma@@av@); }",
+ " //@each-Tv@",
+ " protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }",
+ " //@end-Tv@",
+ " //@each-Tv@",
+ " //@each-R@",
+ " protected @R@ invoke_@Rc@(@Tvav@) throws Throwable { return return_@Rc@(target@cat@(@av@)); }",
+ " //@end-R@",
+ " //@end-Tv@",
+ " }",
+ } };
+ enum VAR {
+ cat, R, Rc, Tv, av, comma, Tvav, Ovav;
+ public final String pattern = "@"+toString().replace('_','.')+"@";
+ public String binding;
+ static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
+ int nargs = nrefs + nints + nlongs;
+ if (topLevel)
+ VAR.cat.binding = catstr(ALL_RETURN_TYPES ? TYPES.length : rcat, nrefs, nints, nlongs);
+ VAR.R.binding = TYPES[rcat];
+ VAR.Rc.binding = TCHARS[rcat];
+ String[] Tv = new String[nargs];
+ String[] av = new String[nargs];
+ String[] Tvav = new String[nargs];
+ String[] Ovav = new String[nargs];
+ for (int i = 0; i < nargs; i++) {
+ int tcat = (i < nrefs) ? 0 : (i < nrefs + nints) ? 1 : 2;
+ Tv[i] = TYPES[tcat];
+ av[i] = arg(i);
+ Tvav[i] = param(Tv[i], av[i]);
+ Ovav[i] = param("Object", av[i]);
+ }
+ VAR.Tv.binding = comma(Tv);
+ VAR.av.binding = comma(av);
+ VAR.comma.binding = (av.length == 0 ? "" : ", ");
+ VAR.Tvav.binding = comma(Tvav);
+ VAR.Ovav.binding = comma(Ovav);
+ }
+ static String arg(int i) { return "a"+i; }
+ static String param(String t, String a) { return t+" "+a; }
+ static String comma(String[] v) { return comma("", v); }
+ static String comma(String sep, String[] v) {
+ if (v.length == 0) return "";
+ String res = sep+v[0];
+ for (int i = 1; i < v.length; i++) res += ", "+v[i];
+ return res;
+ }
+ static String transform(String string) {
+ for (VAR var : values())
+ string = string.replaceAll(var.pattern, var.binding);
+ return string;
+ }
+ }
+ static String[] stringsIn(String[] strings, int beg, int end) {
+ return Arrays.copyOfRange(strings, beg, Math.min(end, strings.length));
+ }
+ static String[] stringsBefore(String[] strings, int pos) {
+ return stringsIn(strings, 0, pos);
+ }
+ static String[] stringsAfter(String[] strings, int pos) {
+ return stringsIn(strings, pos, strings.length);
+ }
+ static int indexAfter(String[] strings, int pos, String tag) {
+ return Math.min(indexBefore(strings, pos, tag) + 1, strings.length);
+ }
+ static int indexBefore(String[] strings, int pos, String tag) {
+ for (int i = pos, end = strings.length; ; i++) {
+ if (i == end || strings[i].endsWith(tag)) return i;
+ }
+ }
+ static int MIN_ARITY, MAX_ARITY, MAX_RCAT, MAX_REFS, MAX_INTS, MAX_LONGS;
+ static boolean ALL_ARG_TYPES, ALL_RETURN_TYPES;
+ static HashSet<String> done = new HashSet<String>();
+ public static void main(String... av) {
+ for (String[] template : TEMPLATES) {
+ int forLinesLimit = indexBefore(template, 0, "@each-cat@");
+ String[] forLines = stringsBefore(template, forLinesLimit);
+ template = stringsAfter(template, forLinesLimit);
+ for (String forLine : forLines)
+ expandTemplate(forLine, template);
+ }
+ }
+ static void expandTemplate(String forLine, String[] template) {
+ String[] params = forLine.split("[^0-9]+");
+ if (params[0].length() == 0) params = stringsAfter(params, 1);
+ System.out.println("//params="+Arrays.asList(params));
+ int pcur = 0;
+ MIN_ARITY = Integer.valueOf(params[pcur++]);
+ MAX_ARITY = Integer.valueOf(params[pcur++]);
+ MAX_RCAT = Integer.valueOf(params[pcur++]);
+ MAX_REFS = Integer.valueOf(params[pcur++]);
+ MAX_INTS = Integer.valueOf(params[pcur++]);
+ MAX_LONGS = Integer.valueOf(params[pcur++]);
+ if (pcur != params.length) throw new RuntimeException("bad extra param: "+forLine);
+ if (MAX_RCAT >= TYPES.length) MAX_RCAT = TYPES.length - 1;
+ ALL_ARG_TYPES = (indexBefore(template, 0, "@each-Tv@") < template.length);
+ ALL_RETURN_TYPES = (indexBefore(template, 0, "@each-R@") < template.length);
+ for (int nargs = MIN_ARITY; nargs <= MAX_ARITY; nargs++) {
+ for (int rcat = 0; rcat <= MAX_RCAT; rcat++) {
+ expandTemplate(template, true, rcat, nargs, 0, 0);
+ if (ALL_ARG_TYPES) break;
+ expandTemplateForPrims(template, true, rcat, nargs, 1, 1);
+ if (ALL_RETURN_TYPES) break;
+ }
+ }
+ }
+ static String catstr(int rcat, int nrefs, int nints, int nlongs) {
+ int nargs = nrefs + nints + nlongs;
+ String cat = TCHARS[rcat] + nargs;
+ if (!ALL_ARG_TYPES) cat += (nints==0?"":"I"+nints)+(nlongs==0?"":"J"+nlongs);
+ return cat;
+ }
+ static void expandTemplateForPrims(String[] template, boolean topLevel, int rcat, int nargs, int minints, int minlongs) {
+ for (int isLong = 0; isLong <= 1; isLong++) {
+ for (int nprims = 1; nprims <= nargs; nprims++) {
+ int nrefs = nargs - nprims;
+ int nints = ((1-isLong) * nprims);
+ int nlongs = (isLong * nprims);
+ expandTemplate(template, topLevel, rcat, nrefs, nints, nlongs);
+ }
+ }
+ }
+ static void expandTemplate(String[] template, boolean topLevel,
+ int rcat, int nrefs, int nints, int nlongs) {
+ int nargs = nrefs + nints + nlongs;
+ if (nrefs > MAX_REFS || nints > MAX_INTS || nlongs > MAX_LONGS) return;
+ VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+ if (topLevel && !done.add(VAR.cat.binding)) {
+ System.out.println(" //repeat "+VAR.cat.binding);
+ return;
+ }
+ for (int i = 0; i < template.length; i++) {
+ String line = template[i];
+ if (line.endsWith("@each-cat@")) {
+ // ignore
+ } else if (line.endsWith("@each-R@")) {
+ int blockEnd = indexAfter(template, i, "@end-R@");
+ String[] block = stringsIn(template, i+1, blockEnd-1);
+ for (int rcat1 = rcat; rcat1 <= MAX_RCAT; rcat1++)
+ expandTemplate(block, false, rcat1, nrefs, nints, nlongs);
+ VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+ i = blockEnd-1; continue;
+ } else if (line.endsWith("@each-Tv@")) {
+ int blockEnd = indexAfter(template, i, "@end-Tv@");
+ String[] block = stringsIn(template, i+1, blockEnd-1);
+ expandTemplate(block, false, rcat, nrefs, nints, nlongs);
+ expandTemplateForPrims(block, false, rcat, nargs, nints+1, nlongs+1);
+ VAR.makeBindings(topLevel, rcat, nrefs, nints, nlongs);
+ i = blockEnd-1; continue;
+ } else {
+ System.out.println(VAR.transform(line));
+ }
+ }
+ }
+}
+//}}} */
+//params=[0, 3, 4, 99, 99, 99]
+ static class A0 extends Adapter {
+ protected A0(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A0(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A0 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A0(e, i, c, t); }
+ protected Object target() throws Throwable { return invoker.invokeExact(target); }
+ protected Object targetA0() throws Throwable { return target(); }
+ protected Object invoke_L() throws Throwable { return return_L(targetA0()); }
+ protected int invoke_I() throws Throwable { return return_I(targetA0()); }
+ protected long invoke_J() throws Throwable { return return_J(targetA0()); }
+ protected float invoke_F() throws Throwable { return return_F(targetA0()); }
+ protected double invoke_D() throws Throwable { return return_D(targetA0()); }
+ }
+ static class A1 extends Adapter {
+ protected A1(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A1(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A1 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A1(e, i, c, t); }
+ protected Object target(Object a0) throws Throwable { return invoker.invokeExact(target, a0); }
+ protected Object targetA1(Object a0) throws Throwable { return target(a0); }
+ protected Object targetA1(int a0) throws Throwable { return target(a0); }
+ protected Object targetA1(long a0) throws Throwable { return target(a0); }
+ protected Object invoke_L(Object a0) throws Throwable { return return_L(targetA1(a0)); }
+ protected int invoke_I(Object a0) throws Throwable { return return_I(targetA1(a0)); }
+ protected long invoke_J(Object a0) throws Throwable { return return_J(targetA1(a0)); }
+ protected float invoke_F(Object a0) throws Throwable { return return_F(targetA1(a0)); }
+ protected double invoke_D(Object a0) throws Throwable { return return_D(targetA1(a0)); }
+ protected Object invoke_L(int a0) throws Throwable { return return_L(targetA1(a0)); }
+ protected int invoke_I(int a0) throws Throwable { return return_I(targetA1(a0)); }
+ protected long invoke_J(int a0) throws Throwable { return return_J(targetA1(a0)); }
+ protected float invoke_F(int a0) throws Throwable { return return_F(targetA1(a0)); }
+ protected double invoke_D(int a0) throws Throwable { return return_D(targetA1(a0)); }
+ protected Object invoke_L(long a0) throws Throwable { return return_L(targetA1(a0)); }
+ protected int invoke_I(long a0) throws Throwable { return return_I(targetA1(a0)); }
+ protected long invoke_J(long a0) throws Throwable { return return_J(targetA1(a0)); }
+ protected float invoke_F(long a0) throws Throwable { return return_F(targetA1(a0)); }
+ protected double invoke_D(long a0) throws Throwable { return return_D(targetA1(a0)); }
+ }
+ static class A2 extends Adapter {
+ protected A2(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A2(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A2 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A2(e, i, c, t); }
+ protected Object target(Object a0, Object a1) throws Throwable { return invoker.invokeExact(target, a0, a1); }
+ protected Object targetA2(Object a0, Object a1) throws Throwable { return target(a0, a1); }
+ protected Object targetA2(Object a0, int a1) throws Throwable { return target(a0, a1); }
+ protected Object targetA2(int a0, int a1) throws Throwable { return target(a0, a1); }
+ protected Object targetA2(Object a0, long a1) throws Throwable { return target(a0, a1); }
+ protected Object targetA2(long a0, long a1) throws Throwable { return target(a0, a1); }
+ protected Object invoke_L(Object a0, Object a1) throws Throwable { return return_L(targetA2(a0, a1)); }
+ protected int invoke_I(Object a0, Object a1) throws Throwable { return return_I(targetA2(a0, a1)); }
+ protected long invoke_J(Object a0, Object a1) throws Throwable { return return_J(targetA2(a0, a1)); }
+ protected float invoke_F(Object a0, Object a1) throws Throwable { return return_F(targetA2(a0, a1)); }
+ protected double invoke_D(Object a0, Object a1) throws Throwable { return return_D(targetA2(a0, a1)); }
+ protected Object invoke_L(Object a0, int a1) throws Throwable { return return_L(targetA2(a0, a1)); }
+ protected int invoke_I(Object a0, int a1) throws Throwable { return return_I(targetA2(a0, a1)); }
+ protected long invoke_J(Object a0, int a1) throws Throwable { return return_J(targetA2(a0, a1)); }
+ protected float invoke_F(Object a0, int a1) throws Throwable { return return_F(targetA2(a0, a1)); }
+ protected double invoke_D(Object a0, int a1) throws Throwable { return return_D(targetA2(a0, a1)); }
+ protected Object invoke_L(int a0, int a1) throws Throwable { return return_L(targetA2(a0, a1)); }
+ protected int invoke_I(int a0, int a1) throws Throwable { return return_I(targetA2(a0, a1)); }
+ protected long invoke_J(int a0, int a1) throws Throwable { return return_J(targetA2(a0, a1)); }
+ protected float invoke_F(int a0, int a1) throws Throwable { return return_F(targetA2(a0, a1)); }
+ protected double invoke_D(int a0, int a1) throws Throwable { return return_D(targetA2(a0, a1)); }
+ protected Object invoke_L(Object a0, long a1) throws Throwable { return return_L(targetA2(a0, a1)); }
+ protected int invoke_I(Object a0, long a1) throws Throwable { return return_I(targetA2(a0, a1)); }
+ protected long invoke_J(Object a0, long a1) throws Throwable { return return_J(targetA2(a0, a1)); }
+ protected float invoke_F(Object a0, long a1) throws Throwable { return return_F(targetA2(a0, a1)); }
+ protected double invoke_D(Object a0, long a1) throws Throwable { return return_D(targetA2(a0, a1)); }
+ protected Object invoke_L(long a0, long a1) throws Throwable { return return_L(targetA2(a0, a1)); }
+ protected int invoke_I(long a0, long a1) throws Throwable { return return_I(targetA2(a0, a1)); }
+ protected long invoke_J(long a0, long a1) throws Throwable { return return_J(targetA2(a0, a1)); }
+ protected float invoke_F(long a0, long a1) throws Throwable { return return_F(targetA2(a0, a1)); }
+ protected double invoke_D(long a0, long a1) throws Throwable { return return_D(targetA2(a0, a1)); }
+ }
+ static class A3 extends Adapter {
+ protected A3(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A3(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A3 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A3(e, i, c, t); }
+ protected Object target(Object a0, Object a1, Object a2) throws Throwable { return invoker.invokeExact(target, a0, a1, a2); }
+ protected Object targetA3(Object a0, Object a1, Object a2) throws Throwable { return target(a0, a1, a2); }
+ protected Object targetA3(Object a0, Object a1, int a2) throws Throwable { return target(a0, a1, a2); }
+ protected Object targetA3(Object a0, int a1, int a2) throws Throwable { return target(a0, a1, a2); }
+ protected Object targetA3(int a0, int a1, int a2) throws Throwable { return target(a0, a1, a2); }
+ protected Object targetA3(Object a0, Object a1, long a2) throws Throwable { return target(a0, a1, a2); }
+ protected Object targetA3(Object a0, long a1, long a2) throws Throwable { return target(a0, a1, a2); }
+ protected Object targetA3(long a0, long a1, long a2) throws Throwable { return target(a0, a1, a2); }
+ protected Object invoke_L(Object a0, Object a1, Object a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+ protected int invoke_I(Object a0, Object a1, Object a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+ protected long invoke_J(Object a0, Object a1, Object a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+ protected float invoke_F(Object a0, Object a1, Object a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+ protected double invoke_D(Object a0, Object a1, Object a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+ protected Object invoke_L(Object a0, Object a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+ protected int invoke_I(Object a0, Object a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+ protected long invoke_J(Object a0, Object a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+ protected float invoke_F(Object a0, Object a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+ protected double invoke_D(Object a0, Object a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+ protected Object invoke_L(Object a0, int a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+ protected int invoke_I(Object a0, int a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+ protected long invoke_J(Object a0, int a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+ protected float invoke_F(Object a0, int a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+ protected double invoke_D(Object a0, int a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+ protected Object invoke_L(int a0, int a1, int a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+ protected int invoke_I(int a0, int a1, int a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+ protected long invoke_J(int a0, int a1, int a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+ protected float invoke_F(int a0, int a1, int a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+ protected double invoke_D(int a0, int a1, int a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+ protected Object invoke_L(Object a0, Object a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+ protected int invoke_I(Object a0, Object a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+ protected long invoke_J(Object a0, Object a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+ protected float invoke_F(Object a0, Object a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+ protected double invoke_D(Object a0, Object a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+ protected Object invoke_L(Object a0, long a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+ protected int invoke_I(Object a0, long a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+ protected long invoke_J(Object a0, long a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+ protected float invoke_F(Object a0, long a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+ protected double invoke_D(Object a0, long a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+ protected Object invoke_L(long a0, long a1, long a2) throws Throwable { return return_L(targetA3(a0, a1, a2)); }
+ protected int invoke_I(long a0, long a1, long a2) throws Throwable { return return_I(targetA3(a0, a1, a2)); }
+ protected long invoke_J(long a0, long a1, long a2) throws Throwable { return return_J(targetA3(a0, a1, a2)); }
+ protected float invoke_F(long a0, long a1, long a2) throws Throwable { return return_F(targetA3(a0, a1, a2)); }
+ protected double invoke_D(long a0, long a1, long a2) throws Throwable { return return_D(targetA3(a0, a1, a2)); }
+ }
+//params=[4, 4, 4, 99, 99, 99]
+ static class A4 extends Adapter {
+ protected A4(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A4(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A4 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A4(e, i, c, t); }
+ protected Object target(Object a0, Object a1, Object a2, Object a3) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3); }
+ protected Object targetA4(Object a0, Object a1, Object a2, Object a3) throws Throwable { return target(a0, a1, a2, a3); }
+ protected Object targetA4(Object a0, Object a1, Object a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
+ protected Object targetA4(Object a0, Object a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
+ protected Object targetA4(Object a0, int a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
+ protected Object targetA4(int a0, int a1, int a2, int a3) throws Throwable { return target(a0, a1, a2, a3); }
+ protected Object targetA4(Object a0, Object a1, Object a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
+ protected Object targetA4(Object a0, Object a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
+ protected Object targetA4(Object a0, long a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
+ protected Object targetA4(long a0, long a1, long a2, long a3) throws Throwable { return target(a0, a1, a2, a3); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, Object a1, Object a2, Object a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, Object a1, Object a2, int a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
+ protected Object invoke_L(Object a0, Object a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+ protected int invoke_I(Object a0, Object a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+ protected long invoke_J(Object a0, Object a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, Object a1, int a2, int a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, Object a1, int a2, int a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
+ protected Object invoke_L(Object a0, int a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+ protected int invoke_I(Object a0, int a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+ protected long invoke_J(Object a0, int a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, int a1, int a2, int a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, int a1, int a2, int a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
+ protected Object invoke_L(int a0, int a1, int a2, int a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+ protected int invoke_I(int a0, int a1, int a2, int a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+ protected long invoke_J(int a0, int a1, int a2, int a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(int a0, int a1, int a2, int a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(int a0, int a1, int a2, int a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, Object a1, Object a2, long a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
+ protected Object invoke_L(Object a0, Object a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+ protected int invoke_I(Object a0, Object a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+ protected long invoke_J(Object a0, Object a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, Object a1, long a2, long a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, Object a1, long a2, long a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
+ protected Object invoke_L(Object a0, long a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+ protected int invoke_I(Object a0, long a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+ protected long invoke_J(Object a0, long a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(Object a0, long a1, long a2, long a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(Object a0, long a1, long a2, long a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
+ protected Object invoke_L(long a0, long a1, long a2, long a3) throws Throwable { return return_L(targetA4(a0, a1, a2, a3)); }
+ protected int invoke_I(long a0, long a1, long a2, long a3) throws Throwable { return return_I(targetA4(a0, a1, a2, a3)); }
+ protected long invoke_J(long a0, long a1, long a2, long a3) throws Throwable { return return_J(targetA4(a0, a1, a2, a3)); }
+ protected float invoke_F(long a0, long a1, long a2, long a3) throws Throwable { return return_F(targetA4(a0, a1, a2, a3)); }
+ protected double invoke_D(long a0, long a1, long a2, long a3) throws Throwable { return return_D(targetA4(a0, a1, a2, a3)); }
+ }
+//params=[5, 5, 2, 99, 99, 99]
+ static class A5 extends Adapter {
+ protected A5(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A5(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A5 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A5(e, i, c, t); }
+ protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4); }
+ protected Object targetA5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object targetA5(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object targetA5(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object targetA5(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object targetA5(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object targetA5(int a0, int a1, int a2, int a3, int a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object targetA5(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object targetA5(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object targetA5(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object targetA5(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object targetA5(long a0, long a1, long a2, long a3, long a4) throws Throwable { return target(a0, a1, a2, a3, a4); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ protected Object invoke_L(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(Object a0, Object a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ protected Object invoke_L(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(Object a0, int a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ protected Object invoke_L(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(int a0, int a1, int a2, int a3, int a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(Object a0, long a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ protected Object invoke_L(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_L(targetA5(a0, a1, a2, a3, a4)); }
+ protected int invoke_I(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_I(targetA5(a0, a1, a2, a3, a4)); }
+ protected long invoke_J(long a0, long a1, long a2, long a3, long a4) throws Throwable { return return_J(targetA5(a0, a1, a2, a3, a4)); }
+ }
+//params=[6, 10, 2, 99, 0, 99]
+ static class A6 extends Adapter {
+ protected A6(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A6(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A6 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A6(e, i, c, t); }
+ protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5); }
+ protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+ protected Object targetA6(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+ protected Object targetA6(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+ protected Object targetA6(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+ protected Object targetA6(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+ protected Object targetA6(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+ protected Object targetA6(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return target(a0, a1, a2, a3, a4, a5); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_L(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_I(targetA6(a0, a1, a2, a3, a4, a5)); }
+ protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { return return_J(targetA6(a0, a1, a2, a3, a4, a5)); }
+ }
+ static class A7 extends Adapter {
+ protected A7(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A7(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A7 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A7(e, i, c, t); }
+ protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6); }
+ protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+ protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+ protected Object targetA7(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+ protected Object targetA7(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+ protected Object targetA7(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+ protected Object targetA7(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+ protected Object targetA7(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+ protected Object targetA7(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_L(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_I(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { return return_J(targetA7(a0, a1, a2, a3, a4, a5, a6)); }
+ }
+ static class A8 extends Adapter {
+ protected A8(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A8(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A8 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A8(e, i, c, t); }
+ protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object targetA8(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object targetA8(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object targetA8(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object targetA8(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object targetA8(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object targetA8(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_L(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_I(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { return return_J(targetA8(a0, a1, a2, a3, a4, a5, a6, a7)); }
+ }
+ static class A9 extends Adapter {
+ protected A9(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A9(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A9 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A9(e, i, c, t); }
+ protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object targetA9(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object targetA9(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object targetA9(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object targetA9(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object targetA9(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object targetA9(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_L(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_I(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { return return_J(targetA9(a0, a1, a2, a3, a4, a5, a6, a7, a8)); }
+ }
+ static class A10 extends Adapter {
+ protected A10(MethodHandle entryPoint) { super(entryPoint); } // to build prototype
+ protected A10(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }
+ protected A10 makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new A10(e, i, c, t); }
+ protected Object target(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return invoker.invokeExact(target, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object targetA10(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return target(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, Object a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, Object a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_L(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(Object a0, Object a1, Object a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_L(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(Object a0, Object a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_L(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(Object a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected Object invoke_L(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_L(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected int invoke_I(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_I(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ protected long invoke_J(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { return return_J(targetA10(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)); }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/VolatileCallSite.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
+ * An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates
+ * to its call site target immediately, even if the update occurs in another thread.
+ * There may be a performance penalty for such tight coupling between threads.
+ * <p>
+ * Unlike {@code MutableCallSite}, there is no
+ * {@linkplain MutableCallSite#syncAll syncAll operation} on volatile
+ * call sites, since every write to a volatile variable is implicitly
+ * synchronized with reader threads.
+ * <p>
+ * In other respects, a {@code VolatileCallSite} is interchangeable
+ * with {@code MutableCallSite}.
+ * @see MutableCallSite
+ * @author John Rose, JSR 292 EG
+ */
+public class VolatileCallSite extends CallSite {
+ /**
+ * Creates a call site with a volatile binding to its target.
+ * The initial target is set to a method handle
+ * of the given type which will throw an {@code IllegalStateException} if called.
+ * @param type the method type that this call site will have
+ * @throws NullPointerException if the proposed type is null
+ */
+ public VolatileCallSite(MethodType type) {
+ super(type);
+ }
+
+ /**
+ * Creates a call site with a volatile binding to its target.
+ * The target is set to the given value.
+ * @param target the method handle that will be the initial target of the call site
+ * @throws NullPointerException if the proposed target is null
+ */
+ public VolatileCallSite(MethodHandle target) {
+ super(target);
+ }
+
+ /**
+ * Returns the target method of the call site, which behaves
+ * like a {@code volatile} field of the {@code VolatileCallSite}.
+ * <p>
+ * The interactions of {@code getTarget} with memory are the same
+ * as of a read from a {@code volatile} field.
+ * <p>
+ * In particular, the current thread is required to issue a fresh
+ * read of the target from memory, and must not fail to see
+ * a recent update to the target by another thread.
+ *
+ * @return the linkage state of this call site, a method handle which can change over time
+ * @see #setTarget
+ */
+ @Override public final MethodHandle getTarget() {
+ return getTargetVolatile();
+ }
+
+ /**
+ * Updates the target method of this call site, as a volatile variable.
+ * The type of the new target must agree with the type of the old target.
+ * <p>
+ * The interactions with memory are the same as of a write to a volatile field.
+ * In particular, any threads is guaranteed to see the updated target
+ * the next time it calls {@code getTarget}.
+ * @param newTarget the new target
+ * @throws NullPointerException if the proposed new target is null
+ * @throws WrongMethodTypeException if the proposed new target
+ * has a method type that differs from the previous target
+ * @see #getTarget
+ */
+ @Override public void setTarget(MethodHandle newTarget) {
+ checkTargetChange(getTargetVolatile(), newTarget);
+ setTargetVolatile(newTarget);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final MethodHandle dynamicInvoker() {
+ return makeDynamicInvoker();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/WrongMethodTypeException.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+/**
+ * Thrown to indicate that code has attempted to call a method handle
+ * via the wrong method type. As with the bytecode representation of
+ * normal Java method calls, method handle calls are strongly typed
+ * to a specific type descriptor associated with a call site.
+ * <p>
+ * This exception may also be thrown when two method handles are
+ * composed, and the system detects that their types cannot be
+ * matched up correctly. This amounts to an early evaluation
+ * of the type mismatch, at method handle construction time,
+ * instead of when the mismatched method handle is called.
+ *
+ * @author John Rose, JSR 292 EG
+ * @since 1.7
+ */
+public class WrongMethodTypeException extends RuntimeException {
+ private static final long serialVersionUID = 292L;
+
+ /**
+ * Constructs a {@code WrongMethodTypeException} with no detail message.
+ */
+ public WrongMethodTypeException() {
+ super();
+ }
+
+ /**
+ * Constructs a {@code WrongMethodTypeException} with the specified
+ * detail message.
+ *
+ * @param s the detail message.
+ */
+ public WrongMethodTypeException(String s) {
+ super(s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/lang/invoke/package-info.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,466 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * The {@code java.lang.invoke} package contains dynamic language support provided directly by
+ * the Java core class libraries and virtual machine.
+ *
+ * <p>
+ * Certain types in this package have special relations to dynamic
+ * language support in the virtual machine:
+ * <ul>
+ * <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
+ * <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
+ * which can be linked regardless of their type descriptor.
+ * Normally, method linkage requires exact matching of type descriptors.
+ * </li>
+ *
+ * <li>The JVM bytecode format supports immediate constants of
+ * the classes {@link java.lang.invoke.MethodHandle MethodHandle} and {@link java.lang.invoke.MethodType MethodType}.
+ * </li>
+ * </ul>
+ *
+ * <h2><a name="jvm_mods"></a>Corresponding JVM bytecode format changes</h2>
+ * <em>The following low-level information is presented here as a preview of
+ * changes being made to the Java Virtual Machine specification for JSR 292.
+ * This information will be incorporated in a future version of the JVM specification.</em>
+ *
+ * <h3><a name="indyinsn"></a>{@code invokedynamic} instruction format</h3>
+ * In bytecode, an {@code invokedynamic} instruction is formatted as five bytes.
+ * The first byte is the opcode 186 (hexadecimal {@code BA}).
+ * The next two bytes are a constant pool index (in the same format as for the other {@code invoke} instructions).
+ * The final two bytes are reserved for future use and required to be zero.
+ * The constant pool reference of an {@code invokedynamic} instruction is to a entry
+ * with tag {@code CONSTANT_InvokeDynamic} (decimal 18). See below for its format.
+ * The entry specifies the following information:
+ * <ul>
+ * <li>a bootstrap method (a {@link java.lang.invoke.MethodHandle MethodHandle} constant)</li>
+ * <li>the dynamic invocation name (a UTF8 string)</li>
+ * <li>the argument and return types of the call (encoded as a type descriptor in a UTF8 string)</li>
+ * <li>optionally, a sequence of additional <em>static arguments</em> to the bootstrap method ({@code ldc}-type constants)</li>
+ * </ul>
+ * <p>
+ * Each instance of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
+ * Multiple instances of an {@code invokedynamic} instruction can share a single
+ * {@code CONSTANT_InvokeDynamic} entry.
+ * In any case, distinct call sites always have distinct linkage state.
+ * <p>
+ * A dynamic call site is originally in an unlinked state. In this state, there is
+ * no target method for the call site to invoke.
+ * A dynamic call site is linked by means of a bootstrap method,
+ * as <a href="#bsm">described below</a>.
+ *
+ * <h3><a name="indycon"></a>constant pool entries for {@code invokedynamic} instructions</h3>
+ * If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18),
+ * it must contain exactly four more bytes after the tag.
+ * These bytes are interpreted as two 16-bit indexes, in the usual {@code u2} format.
+ * The first pair of bytes after the tag must be an index into a side table called the
+ * <em>bootstrap method table</em>, which is stored in the {@code BootstrapMethods}
+ * attribute as <a href="#bsmattr">described below</a>.
+ * The second pair of bytes must be an index to a {@code CONSTANT_NameAndType}.
+ * <p>
+ * The first index specifies a bootstrap method used by the associated dynamic call sites.
+ * The second index specifies the method name, argument types, and return type of the dynamic call site.
+ * The structure of such an entry is therefore analogous to a {@code CONSTANT_Methodref},
+ * except that the bootstrap method specifier reference replaces
+ * the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry.
+ *
+ * <h3><a name="mtcon"></a>constant pool entries for {@linkplain java.lang.invoke.MethodType method types}</h3>
+ * If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
+ * it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
+ * entry which represents a method type descriptor.
+ * <p>
+ * The JVM will ensure that on first
+ * execution of an {@code ldc} instruction for this entry, a {@link java.lang.invoke.MethodType MethodType}
+ * will be created which represents the type descriptor.
+ * Any classes mentioned in the {@code MethodType} will be loaded if necessary,
+ * but not initialized.
+ * Access checking and error reporting is performed exactly as it is for
+ * references by {@code ldc} instructions to {@code CONSTANT_Class} constants.
+ *
+ * <h3><a name="mhcon"></a>constant pool entries for {@linkplain java.lang.invoke.MethodHandle method handles}</h3>
+ * If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
+ * it must contain exactly three more bytes. The first byte after the tag is a subtag
+ * value which must be in the range 1 through 9, and the last two must be an index to a
+ * {@code CONSTANT_Fieldref}, {@code CONSTANT_Methodref}, or
+ * {@code CONSTANT_InterfaceMethodref} entry which represents a field or method
+ * for which a method handle is to be created.
+ * Furthermore, the subtag value and the type of the constant index value
+ * must agree according to the table below.
+ * <p>
+ * The JVM will ensure that on first execution of an {@code ldc} instruction
+ * for this entry, a {@link java.lang.invoke.MethodHandle MethodHandle} will be created which represents
+ * the field or method reference, according to the specific mode implied by the subtag.
+ * <p>
+ * As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
+ * the {@code Class} or {@code MethodType} object which reifies the field or method's
+ * type is created. Any classes mentioned in this reification will be loaded if necessary,
+ * but not initialized, and access checking and error reporting performed as usual.
+ * <p>
+ * Unlike the reflective {@code Lookup} API, there are no security manager calls made
+ * when these constants are resolved.
+ * <p>
+ * The method handle itself will have a type and behavior determined by the subtag as follows:
+ * <code>
+ * <table border=1 cellpadding=5 summary="CONSTANT_MethodHandle subtypes">
+ * <tr><th>N</th><th>subtag name</th><th>member</th><th>MH type</th><th>bytecode behavior</th><th>lookup expression</th></tr>
+ * <tr><td>1</td><td>REF_getField</td><td>C.f:T</td><td>(C)T</td><td>getfield C.f:T</td>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter findGetter(C.class,"f",T.class)}</td></tr>
+ * <tr><td>2</td><td>REF_getStatic</td><td>C.f:T</td><td>( )T</td><td>getstatic C.f:T</td>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter findStaticGetter(C.class,"f",T.class)}</td></tr>
+ * <tr><td>3</td><td>REF_putField</td><td>C.f:T</td><td>(C,T)void</td><td>putfield C.f:T</td>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter findSetter(C.class,"f",T.class)}</td></tr>
+ * <tr><td>4</td><td>REF_putStatic</td><td>C.f:T</td><td>(T)void</td><td>putstatic C.f:T</td>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter findStaticSetter(C.class,"f",T.class)}</td></tr>
+ * <tr><td>5</td><td>REF_invokeVirtual</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokevirtual C.m(A*)T</td>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
+ * <tr><td>6</td><td>REF_invokeStatic</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokestatic C.m(A*)T</td>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic findStatic(C.class,"m",MT)}</td></tr>
+ * <tr><td>7</td><td>REF_invokeSpecial</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokespecial C.m(A*)T</td>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial findSpecial(C.class,"m",MT,this.class)}</td></tr>
+ * <tr><td>8</td><td>REF_newInvokeSpecial</td><td>C.<init>(A*)void</td><td>(A*)C</td><td>new C; dup; invokespecial C.<init>(A*)void</td>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor findConstructor(C.class,MT)}</td></tr>
+ * <tr><td>9</td><td>REF_invokeInterface</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokeinterface C.m(A*)T</td>
+ * <td>{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
+ * </table>
+ * </code>
+ * Here, the type {@code C} is taken from the {@code CONSTANT_Class} reference associated
+ * with the {@code CONSTANT_NameAndType} descriptor.
+ * The field name {@code f} or method name {@code m} is taken from the {@code CONSTANT_NameAndType}
+ * as is the result type {@code T} and (in the case of a method or constructor) the argument type sequence
+ * {@code A*}.
+ * <p>
+ * Each method handle constant has an equivalent instruction sequence called its <em>bytecode behavior</em>.
+ * In general, creating a method handle constant can be done in exactly the same circumstances that
+ * the JVM would successfully resolve the symbolic references in the bytecode behavior.
+ * Also, the type of a method handle constant is such that a valid {@code invokeExact} call
+ * on the method handle has exactly the same JVM stack effects as the <em>bytecode behavior</em>.
+ * Finally, calling a method handle constant on a valid set of arguments has exactly the same effect
+ * and returns the same result (if any) as the corresponding <em>bytecode behavior</em>.
+ * <p>
+ * Each method handle constant also has an equivalent reflective <em>lookup expression</em>,
+ * which is a query to a method in {@link java.lang.invoke.MethodHandles.Lookup}.
+ * In the example lookup method expression given in the table above, the name {@code MT}
+ * stands for a {@code MethodType} built from {@code T} and the sequence of argument types {@code A*}.
+ * (Note that the type {@code C} is not prepended to the query type {@code MT} even if the member is non-static.)
+ * In the case of {@code findSpecial}, the name {@code this.class} refers to the class containing
+ * the bytecodes.
+ * <p>
+ * The special name {@code <clinit>} is not allowed.
+ * The special name {@code <init>} is not allowed except for subtag 8 as shown.
+ * <p>
+ * The JVM verifier and linker apply the same access checks and restrictions for these references as for the hypothetical
+ * bytecode instructions specified in the last column of the table.
+ * A method handle constant will successfully resolve to a method handle if the symbolic references
+ * of the corresponding bytecode instruction(s) would also resolve successfully.
+ * Otherwise, an attempt to resolve the constant will throw equivalent linkage errors.
+ * In particular, method handles to
+ * private and protected members can be created in exactly those classes for which the corresponding
+ * normal accesses are legal.
+ * <p>
+ * A constant may refer to a method or constructor with the {@code varargs}
+ * bit (hexadecimal {@code 0x0080}) set in its modifier bitmask.
+ * The method handle constant produced for such a method behaves as if
+ * it were created by {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector}.
+ * In other words, the constant method handle will exhibit variable arity,
+ * when invoked via {@code invokeGeneric}.
+ * On the other hand, its behavior with respect to {@code invokeExact} will be the same
+ * as if the {@code varargs} bit were not set.
+ * <p>
+ * Although the {@code CONSTANT_MethodHandle} and {@code CONSTANT_MethodType} constant types
+ * resolve class names, they do not force class initialization.
+ * Method handle constants for subtags {@code REF_getStatic}, {@code REF_putStatic}, and {@code REF_invokeStatic}
+ * may force class initialization on their first invocation, just like the corresponding bytecodes.
+ * <p>
+ * The rules of section 5.4.3 of the
+ * <a href="http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#73492">JVM Specification</a>
+ * apply to the resolution of {@code CONSTANT_MethodType}, {@code CONSTANT_MethodHandle},
+ * and {@code CONSTANT_InvokeDynamic} constants,
+ * by the execution of {@code invokedynamic} and {@code ldc} instructions.
+ * (Roughly speaking, this means that every use of a constant pool entry
+ * must lead to the same outcome.
+ * If the resolution succeeds, the same object reference is produced
+ * by every subsequent execution of the same instruction.
+ * If the resolution of the constant causes an error to occur,
+ * the same error will be re-thrown on every subsequent attempt
+ * to use this particular constant.)
+ * <p>
+ * Constants created by the resolution of these constant pool types are not necessarily
+ * interned. Except for {@code CONSTANT_Class} and {@code CONSTANT_String} entries,
+ * two distinct constant pool entries might not resolve to the same reference
+ * even if they contain the same symbolic reference.
+ *
+ * <h2><a name="bsm"></a>Bootstrap Methods</h2>
+ * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
+ * the call site must first be <em>linked</em>.
+ * Linking is accomplished by calling a <em>bootstrap method</em>
+ * which is given the static information content of the call site,
+ * and which must produce a {@link java.lang.invoke.MethodHandle method handle}
+ * that gives the behavior of the call site.
+ * <p>
+ * Each {@code invokedynamic} instruction statically specifies its own
+ * bootstrap method as a constant pool reference.
+ * The constant pool reference also specifies the call site's name and type descriptor,
+ * just like {@code invokevirtual} and the other invoke instructions.
+ * <p>
+ * Linking starts with resolving the constant pool entry for the
+ * bootstrap method, and resolving a {@link java.lang.invoke.MethodType MethodType} object for
+ * the type descriptor of the dynamic call site.
+ * This resolution process may trigger class loading.
+ * It may therefore throw an error if a class fails to load.
+ * This error becomes the abnormal termination of the dynamic
+ * call site execution.
+ * Linkage does not trigger class initialization.
+ * <p>
+ * Next, the bootstrap method call is started, with at least four values being stacked:
+ * <ul>
+ * <li>a {@code MethodHandle}, the resolved bootstrap method itself </li>
+ * <li>a {@code MethodHandles.Lookup}, a lookup object on the <em>caller class</em> in which dynamic call site occurs </li>
+ * <li>a {@code String}, the method name mentioned in the call site </li>
+ * <li>a {@code MethodType}, the resolved type descriptor of the call </li>
+ * <li>optionally, one or more <a href="#args">additional static arguments</a> </li>
+ * </ul>
+ * The method handle is then applied to the other values as if by
+ * {@link java.lang.invoke.MethodHandle#invokeGeneric invokeGeneric}.
+ * The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass).
+ * The type of the call site's target must be exactly equal to the type
+ * derived from the dynamic call site's type descriptor and passed to
+ * the bootstrap method.
+ * The call site then becomes permanently linked to the dynamic call site.
+ * <p>
+ * As long as each bootstrap method can be correctly invoked
+ * by <code>invokeGeneric</code>, its detailed type is arbitrary.
+ * For example, the first argument could be {@code Object}
+ * instead of {@code MethodHandles.Lookup}, and the return type
+ * could also be {@code Object} instead of {@code CallSite}.
+ * (Note that the types and number of the stacked arguments limit
+ * the legal kinds of bootstrap methods to appropriately typed
+ * static methods and constructors of {@code CallSite} subclasses.)
+ * <p>
+ * After resolution, the linkage process may fail in a variety of ways.
+ * All failures are reported by a {@link java.lang.BootstrapMethodError BootstrapMethodError},
+ * which is thrown as the abnormal termination of the dynamic call
+ * site execution.
+ * The following circumstances will cause this:
+ * <ul>
+ * <li>the index to the bootstrap method specifier is out of range </li>
+ * <li>the bootstrap method cannot be resolved </li>
+ * <li>the {@code MethodType} to pass to the bootstrap method cannot be resolved </li>
+ * <li>a static argument to the bootstrap method cannot be resolved
+ * (i.e., a {@code CONSTANT_Class}, {@code CONSTANT_MethodType},
+ * or {@code CONSTANT_MethodHandle} argument cannot be linked) </li>
+ * <li>the bootstrap method has the wrong arity,
+ * causing {@code invokeGeneric} to throw {@code WrongMethodTypeException} </li>
+ * <li>the bootstrap method has a wrong argument or return type </li>
+ * <li>the bootstrap method invocation completes abnormally </li>
+ * <li>the result from the bootstrap invocation is not a reference to
+ * an object of type {@link java.lang.invoke.CallSite CallSite} </li>
+ * <li>the target of the {@code CallSite} does not have a target of
+ * the expected {@code MethodType} </li>
+ * </ul>
+ *
+ * <h3><a name="linktime"></a>timing of linkage</h3>
+ * A dynamic call site is linked just before its first execution.
+ * The bootstrap method call implementing the linkage occurs within
+ * a thread that is attempting a first execution.
+ * <p>
+ * If there are several such threads, the bootstrap method may be
+ * invoked in several threads concurrently.
+ * Therefore, bootstrap methods which access global application
+ * data must take the usual precautions against race conditions.
+ * In any case, every {@code invokedynamic} instruction is either
+ * unlinked or linked to a unique {@code CallSite} object.
+ * <p>
+ * In an application which requires dynamic call sites with individually
+ * mutable behaviors, their bootstrap methods should produce distinct
+ * {@link java.lang.invoke.CallSite CallSite} objects, one for each linkage request.
+ * Alternatively, an application can link a single {@code CallSite} object
+ * to several {@code invokedynamic} instructions, in which case
+ * a change to the target method will become visible at each of
+ * the instructions.
+ * <p>
+ * If several threads simultaneously execute a bootstrap method for a single dynamic
+ * call site, the JVM must choose one {@code CallSite} object and install it visibly to
+ * all threads. Any other bootstrap method calls are allowed to complete, but their
+ * results are ignored, and their dynamic call site invocations proceed with the originally
+ * chosen target object.
+ *
+ * <p style="font-size:smaller;">
+ * <em>Discussion:</em>
+ * These rules do not enable the JVM to duplicate dynamic call sites,
+ * or to issue “causeless” bootstrap method calls.
+ * Every dynamic call site transitions at most once from unlinked to linked,
+ * just before its first invocation.
+ * There is no way to undo the effect of a completed bootstrap method call.
+ *
+ * <h3><a name="bsmattr">the {@code BootstrapMethods} attribute </h3>
+ * Each {@code CONSTANT_InvokeDynamic} entry contains an index which references
+ * a bootstrap method specifier; all such specifiers are contained in a separate array.
+ * This array is defined by a class attribute named {@code BootstrapMethods}.
+ * The body of this attribute consists of a sequence of byte pairs, all interpreted as
+ * as 16-bit counts or constant pool indexes, in the {@code u2} format.
+ * The attribute body starts with a count of bootstrap method specifiers,
+ * which is immediately followed by the sequence of specifiers.
+ * <p>
+ * Each bootstrap method specifier contains an index to a
+ * {@code CONSTANT_MethodHandle} constant, which is the bootstrap
+ * method itself.
+ * This is followed by a count, and then a sequence (perhaps empty) of
+ * indexes to <a href="#args">additional static arguments</a>
+ * for the bootstrap method.
+ * <p>
+ * During class loading, the verifier must check the structure of the
+ * {@code BootstrapMethods} attribute. In particular, each constant
+ * pool index must be of the correct type. A bootstrap method index
+ * must refer to a {@code CONSTANT_MethodHandle} (tag 15).
+ * Every other index must refer to a valid operand of an
+ * {@code ldc_w} or {@code ldc2_w} instruction (tag 3..8 or 15..16).
+ *
+ * <h3><a name="args">static arguments to the bootstrap method</h3>
+ * An {@code invokedynamic} instruction specifies at least three arguments
+ * to pass to its bootstrap method:
+ * The caller class (expressed as a {@link java.lang.invoke.MethodHandles.Lookup Lookup object},
+ * the name (extracted from the {@code CONSTANT_NameAndType} entry),
+ * and the type (also extracted from the {@code CONSTANT_NameAndType} entry).
+ * The {@code invokedynamic} instruction may specify additional metadata values
+ * to pass to its bootstrap method.
+ * Collectively, these values are called <em>static arguments</em> to the
+ * {@code invokedynamic} instruction, because they are used once at link
+ * time to determine the instruction's behavior on subsequent sets of
+ * <em>dynamic arguments</em>.
+ * <p>
+ * Static arguments are used to communicate application-specific meta-data
+ * to the bootstrap method.
+ * Drawn from the constant pool, they may include references to classes, method handles,
+ * strings, or numeric data that may be relevant to the task of linking that particular call site.
+ * <p>
+ * Static arguments are specified constant pool indexes stored in the {@code BootstrapMethods} attribute.
+ * Before the bootstrap method is invoked, each index is used to compute an {@code Object}
+ * reference to the indexed value in the constant pool.
+ * The valid constant pool entries are listed in this table:
+ * <code>
+ * <table border=1 cellpadding=5 summary="Static argument types">
+ * <tr><th>entry type</th><th>argument type</th><th>argument value</th></tr>
+ * <tr><td>CONSTANT_String</td><td><code>java.lang.String</code></td><td>the indexed string literal</td></tr>
+ * <tr><td>CONSTANT_Class</td><td><code>java.lang.Class</code></td><td>the indexed class, resolved</td></tr>
+ * <tr><td>CONSTANT_Integer</td><td><code>java.lang.Integer</code></td><td>the indexed int value</td></tr>
+ * <tr><td>CONSTANT_Long</td><td><code>java.lang.Long</code></td><td>the indexed long value</td></tr>
+ * <tr><td>CONSTANT_Float</td><td><code>java.lang.Float</code></td><td>the indexed float value</td></tr>
+ * <tr><td>CONSTANT_Double</td><td><code>java.lang.Double</code></td><td>the indexed double value</td></tr>
+ * <tr><td>CONSTANT_MethodHandle</td><td><code>java.lang.invoke.MethodHandle</code></td><td>the indexed method handle constant</td></tr>
+ * <tr><td>CONSTANT_MethodType</td><td><code>java.lang.invoke.MethodType</code></td><td>the indexed method type constant</td></tr>
+ * </table>
+ * </code>
+ * <p>
+ * If a given {@code invokedynamic} instruction specifies no static arguments,
+ * the instruction's bootstrap method will be invoked on three arguments,
+ * conveying the instruction's caller class, name, and method type.
+ * If the {@code invokedynamic} instruction specifies one or more static arguments,
+ * those values will be passed as additional arguments to the method handle.
+ * (Note that because there is a limit of 255 arguments to any method,
+ * at most 252 extra arguments can be supplied.)
+ * The bootstrap method will be invoked as if by either {@code invokeGeneric}
+ * or {@code invokeWithArguments}. (There is no way to tell the difference.)
+ * <p>
+ * The normal argument conversion rules for {@code invokeGeneric} apply to all stacked arguments.
+ * For example, if a pushed value is a primitive type, it may be converted to a reference by boxing conversion.
+ * If the bootstrap method is a variable arity method (its modifier bit {@code 0x0080} is set),
+ * then some or all of the arguments specified here may be collected into a trailing array parameter.
+ * (This is not a special rule, but rather a useful consequence of the interaction
+ * between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods,
+ * and the {@code java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
+ * <p>
+ * Given these rules, here are examples of legal bootstrap method declarations,
+ * given various numbers {@code N} of extra arguments.
+ * The first rows (marked {@code *}) will work for any number of extra arguments.
+ * <code>
+ * <table border=1 cellpadding=5 summary="Static argument types">
+ * <tr><th>N</th><th>sample bootstrap method</th></tr>
+ * <tr><td>*</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
+ * <tr><td>*</td><td><code>CallSite bootstrap(Object... args)</code></td></tr>
+ * <tr><td>*</td><td><code>CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs)</code></td></tr>
+ * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type)</code></td></tr>
+ * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, Object... nameAndType)</code></td></tr>
+ * <tr><td>1</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg)</code></td></tr>
+ * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
+ * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String... args)</code></td></tr>
+ * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)</code></td></tr>
+ * </table>
+ * </code>
+ * The last example assumes that the extra arguments are of type
+ * {@code CONSTANT_String} and {@code CONSTANT_Integer}, respectively.
+ * The second-to-last example assumes that all extra arguments are of type
+ * {@code CONSTANT_String}.
+ * The other examples work with all types of extra arguments.
+ * <p>
+ * As noted above, the actual method type of the bootstrap method can vary.
+ * For example, the fourth argument could be {@code MethodHandle},
+ * if that is the type of the corresponding constant in
+ * the {@code CONSTANT_InvokeDynamic} entry.
+ * In that case, the {@code invokeGeneric} call will pass the extra method handle
+ * constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric}
+ * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
+ * (If a string constant were passed instead, by badly generated code, that cast would then fail,
+ * resulting in a {@code BootstrapMethodError}.)
+ * <p>
+ * Extra bootstrap method arguments are intended to allow language implementors
+ * to safely and compactly encode metadata.
+ * In principle, the name and extra arguments are redundant,
+ * since each call site could be given its own unique bootstrap method.
+ * Such a practice is likely to produce large class files and constant pools.
+ *
+ * <h2><a name="structs"></a>Structure Summary</h2>
+ * <blockquote><pre>// summary of constant and attribute structures
+struct CONSTANT_MethodHandle_info {
+ u1 tag = 15;
+ u1 reference_kind; // 1..8 (one of REF_invokeVirtual, etc.)
+ u2 reference_index; // index to CONSTANT_Fieldref or *Methodref
+}
+struct CONSTANT_MethodType_info {
+ u1 tag = 16;
+ u2 descriptor_index; // index to CONSTANT_Utf8, as in NameAndType
+}
+struct CONSTANT_InvokeDynamic_info {
+ u1 tag = 18;
+ u2 bootstrap_method_attr_index; // index into BootstrapMethods_attr
+ u2 name_and_type_index; // index to CONSTANT_NameAndType, as in Methodref
+}
+struct BootstrapMethods_attr {
+ u2 name; // CONSTANT_Utf8 = "BootstrapMethods"
+ u4 size;
+ u2 bootstrap_method_count;
+ struct bootstrap_method_specifier {
+ u2 bootstrap_method_ref; // index to CONSTANT_MethodHandle
+ u2 bootstrap_argument_count;
+ u2 bootstrap_arguments[bootstrap_argument_count]; // constant pool indexes
+ } bootstrap_methods[bootstrap_method_count];
+}
+ * </pre></blockquote>
+ *
+ * @author John Rose, JSR 292 EG
+ * @since 1.7
+ */
+
+package java.lang.invoke;
--- a/jdk/src/share/classes/sun/dyn/WrapperInstance.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn;
-
-import java.dyn.MethodHandle;
-
-/**
- * Private API used inside of java.dyn.MethodHandles.
- * Interface implemented by every object which is produced by
- * {@link java.dyn.MethodHandles#asInstance MethodHandles.asInstance}.
- * The methods of this interface allow a caller to recover the parameters
- * to {@code asInstance}.
- * This allows applications to repeatedly convert between method handles
- * and SAM objects, without the risk of creating unbounded delegation chains.
- */
-public interface WrapperInstance {
- /** Produce or recover a target method handle which is behaviorally
- * equivalent to the SAM method of this object.
- */
- public MethodHandle getWrapperInstanceTarget();
- /** Recover the SAM type for which this object was created.
- */
- public Class<?> getWrapperInstanceType();
-}
-
--- a/jdk/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.anon;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import sun.misc.IOUtils;
-
-/**
- * Anonymous class loader. Will load any valid classfile, producing
- * a {@link Class} metaobject, without installing that class in the
- * system dictionary. Therefore, {@link Class#forName(String)} will never
- * produce a reference to an anonymous class.
- * <p>
- * The access permissions of the anonymous class are borrowed from
- * a <em>host class</em>. The new class behaves as if it were an
- * inner class of the host class. It can access the host's private
- * members, if the creator of the class loader has permission to
- * do so (or to create accessible reflective objects).
- * <p>
- * When the anonymous class is loaded, elements of its constant pool
- * can be patched to new values. This provides a hook to pre-resolve
- * named classes in the constant pool to other classes, including
- * anonymous ones. Also, string constants can be pre-resolved to
- * any reference. (The verifier treats non-string, non-class reference
- * constants as plain objects.)
- * <p>
- * Why include the patching function? It makes some use cases much easier.
- * Second, the constant pool needed some internal patching anyway,
- * to anonymize the loaded class itself. Finally, if you are going
- * to use this seriously, you'll want to build anonymous classes
- * on top of pre-existing anonymous classes, and that requires patching.
- *
- * <p>%%% TO-DO:
- * <ul>
- * <li>needs better documentation</li>
- * <li>needs more security work (for safe delegation)</li>
- * <li>needs a clearer story about error processing</li>
- * <li>patch member references also (use ';' as delimiter char)</li>
- * <li>patch method references to (conforming) method handles</li>
- * </ul>
- *
- * @author jrose
- * @author Remi Forax
- * @see <a href="http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm">
- * http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm</a>
- */
-
-public class AnonymousClassLoader {
- final Class<?> hostClass;
-
- // Note: Do not refactor the calls to checkHostClass unless you
- // also adjust this constant:
- private static int CHC_CALLERS = 3;
-
- public AnonymousClassLoader() {
- this.hostClass = checkHostClass(null);
- }
- public AnonymousClassLoader(Class<?> hostClass) {
- this.hostClass = checkHostClass(hostClass);
- }
-
- private static Class<?> getTopLevelClass(Class<?> clazz) {
- for(Class<?> outer = clazz.getDeclaringClass(); outer != null;
- outer = outer.getDeclaringClass()) {
- clazz = outer;
- }
- return clazz;
- }
-
- private static Class<?> checkHostClass(Class<?> hostClass) {
- // called only from the constructor
- // does a context-sensitive check on caller class
- // CC[0..3] = {Reflection, this.checkHostClass, this.<init>, caller}
- Class<?> caller = sun.reflect.Reflection.getCallerClass(CHC_CALLERS);
-
- if (caller == null) {
- // called from the JVM directly
- if (hostClass == null)
- return AnonymousClassLoader.class; // anything central will do
- return hostClass;
- }
-
- if (hostClass == null)
- hostClass = caller; // default value is caller itself
-
- // anonymous class will access hostClass on behalf of caller
- Class<?> callee = hostClass;
-
- if (caller == callee)
- // caller can always nominate itself to grant caller's own access rights
- return hostClass;
-
- // normalize caller and callee to their top-level classes:
- caller = getTopLevelClass(caller);
- callee = getTopLevelClass(callee);
- if (caller == callee)
- return caller;
-
- ClassLoader callerCL = caller.getClassLoader();
- if (callerCL == null) {
- // caller is trusted code, so accept the proposed hostClass
- return hostClass;
- }
-
- // %%% should do something with doPrivileged, because trusted
- // code should have a way to execute on behalf of
- // partially-trusted clients
-
- // Does the caller have the right to access the private
- // members of the callee? If not, raise an error.
- final int ACC_PRIVATE = 2;
- try {
- sun.reflect.Reflection.ensureMemberAccess(caller, callee, null, ACC_PRIVATE);
- } catch (IllegalAccessException ee) {
- throw new IllegalArgumentException(ee);
- }
-
- return hostClass;
- }
-
- public Class<?> loadClass(byte[] classFile) {
- if (defineAnonymousClass == null) {
- // no JVM support; try to fake an approximation
- try {
- return fakeLoadClass(new ConstantPoolParser(classFile).createPatch());
- } catch (InvalidConstantPoolFormatException ee) {
- throw new IllegalArgumentException(ee);
- }
- }
- return loadClass(classFile, null);
- }
-
- public Class<?> loadClass(ConstantPoolPatch classPatch) {
- if (defineAnonymousClass == null) {
- // no JVM support; try to fake an approximation
- return fakeLoadClass(classPatch);
- }
- Object[] patches = classPatch.patchArray;
- // Convert class names (this late in the game)
- // to use slash '/' instead of dot '.'.
- // Java likes dots, but the JVM likes slashes.
- for (int i = 0; i < patches.length; i++) {
- Object value = patches[i];
- if (value != null) {
- byte tag = classPatch.getTag(i);
- switch (tag) {
- case ConstantPoolVisitor.CONSTANT_Class:
- if (value instanceof String) {
- if (patches == classPatch.patchArray)
- patches = patches.clone();
- patches[i] = ((String)value).replace('.', '/');
- }
- break;
- case ConstantPoolVisitor.CONSTANT_Fieldref:
- case ConstantPoolVisitor.CONSTANT_Methodref:
- case ConstantPoolVisitor.CONSTANT_InterfaceMethodref:
- case ConstantPoolVisitor.CONSTANT_NameAndType:
- // When/if the JVM supports these patches,
- // we'll probably need to reformat them also.
- // Meanwhile, let the class loader create the error.
- break;
- }
- }
- }
- return loadClass(classPatch.outer.classFile, classPatch.patchArray);
- }
-
- private Class<?> loadClass(byte[] classFile, Object[] patchArray) {
- try {
- return (Class<?>)
- defineAnonymousClass.invoke(unsafe,
- hostClass, classFile, patchArray);
- } catch (Exception ex) {
- throwReflectedException(ex);
- throw new RuntimeException("error loading into "+hostClass, ex);
- }
- }
-
- private static void throwReflectedException(Exception ex) {
- if (ex instanceof InvocationTargetException) {
- Throwable tex = ((InvocationTargetException)ex).getTargetException();
- if (tex instanceof Error)
- throw (Error) tex;
- ex = (Exception) tex;
- }
- if (ex instanceof RuntimeException) {
- throw (RuntimeException) ex;
- }
- }
-
- private Class<?> fakeLoadClass(ConstantPoolPatch classPatch) {
- // Implementation:
- // 1. Make up a new name nobody has used yet.
- // 2. Inspect the tail-header of the class to find the this_class index.
- // 3. Patch the CONSTANT_Class for this_class to the new name.
- // 4. Add other CP entries required by (e.g.) string patches.
- // 5. Flatten Class constants down to their names, making sure that
- // the host class loader can pick them up again accurately.
- // 6. Generate the edited class file bytes.
- //
- // Potential limitations:
- // * The class won't be truly anonymous, and may interfere with others.
- // * Flattened class constants might not work, because of loader issues.
- // * Pseudo-string constants will not flatten down to real strings.
- // * Method handles will (of course) fail to flatten to linkage strings.
- if (true) throw new UnsupportedOperationException("NYI");
- Object[] cpArray;
- try {
- cpArray = classPatch.getOriginalCP();
- } catch (InvalidConstantPoolFormatException ex) {
- throw new RuntimeException(ex);
- }
- int thisClassIndex = classPatch.getParser().getThisClassIndex();
- String thisClassName = (String) cpArray[thisClassIndex];
- synchronized (AnonymousClassLoader.class) {
- thisClassName = thisClassName+"\\|"+(++fakeNameCounter);
- }
- classPatch.putUTF8(thisClassIndex, thisClassName);
- byte[] classFile = null;
- return unsafe.defineClass(null, classFile, 0, classFile.length,
- hostClass.getClassLoader(),
- hostClass.getProtectionDomain());
- }
- private static int fakeNameCounter = 99999;
-
- // ignore two warnings on this line:
- static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
- // preceding line requires that this class be on the boot class path
-
- static private final Method defineAnonymousClass;
- static {
- Method dac = null;
- Class<? extends sun.misc.Unsafe> unsafeClass = unsafe.getClass();
- try {
- dac = unsafeClass.getMethod("defineAnonymousClass",
- Class.class,
- byte[].class,
- Object[].class);
- } catch (Exception ee) {
- dac = null;
- }
- defineAnonymousClass = dac;
- }
-
- private static void noJVMSupport() {
- throw new UnsupportedOperationException("no JVM support for anonymous classes");
- }
-
-
- private static native Class<?> loadClassInternal(Class<?> hostClass,
- byte[] classFile,
- Object[] patchArray);
-
- public static byte[] readClassFile(Class<?> templateClass) throws IOException {
- String templateName = templateClass.getName();
- int lastDot = templateName.lastIndexOf('.');
- java.net.URL url = templateClass.getResource(templateName.substring(lastDot+1)+".class");
- java.net.URLConnection connection = url.openConnection();
- int contentLength = connection.getContentLength();
- if (contentLength < 0)
- throw new IOException("invalid content length "+contentLength);
-
- return IOUtils.readFully(connection.getInputStream(), contentLength, true);
- }
-}
--- a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolParser.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,368 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.anon;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
-
-import static sun.dyn.anon.ConstantPoolVisitor.*;
-
-/** A constant pool parser.
- */
-public class ConstantPoolParser {
- final byte[] classFile;
- final byte[] tags;
- final char[] firstHeader; // maghi, maglo, minor, major, cplen
-
- // these are filled in on first parse:
- int endOffset;
- char[] secondHeader; // flags, this_class, super_class, intlen
-
- // used to decode UTF8 array
- private char[] charArray = new char[80];
-
- /** Creates a constant pool parser.
- * @param classFile an array of bytes containing a class.
- * @throws InvalidConstantPoolFormatException if the header of the class has errors.
- */
- public ConstantPoolParser(byte[] classFile) throws InvalidConstantPoolFormatException {
- this.classFile = classFile;
- this.firstHeader = parseHeader(classFile);
- this.tags = new byte[firstHeader[4]];
- }
-
- /** Create a constant pool parser by loading the bytecodes of the
- * class taken as argument.
- *
- * @param templateClass the class to parse.
- *
- * @throws IOException raised if an I/O occurs when loading
- * the bytecode of the template class.
- * @throws InvalidConstantPoolFormatException if the header of the class has errors.
- *
- * @see #ConstantPoolParser(byte[])
- * @see AnonymousClassLoader#readClassFile(Class)
- */
- public ConstantPoolParser(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
- this(AnonymousClassLoader.readClassFile(templateClass));
- }
-
- /** Creates an empty patch to patch the class file
- * used by the current parser.
- * @return a new class patch.
- */
- public ConstantPoolPatch createPatch() {
- return new ConstantPoolPatch(this);
- }
-
- /** Report the tag of the indicated CP entry.
- * @param index
- * @return one of {@link ConstantPoolVisitor#CONSTANT_Utf8}, etc.
- */
- public byte getTag(int index) {
- getEndOffset(); // trigger an exception if we haven't parsed yet
- return tags[index];
- }
-
- /** Report the length of the constant pool. */
- public int getLength() {
- return firstHeader[4];
- }
-
- /** Report the offset, within the class file, of the start of the constant pool. */
- public int getStartOffset() {
- return firstHeader.length * 2;
- }
-
- /** Report the offset, within the class file, of the end of the constant pool. */
- public int getEndOffset() {
- if (endOffset == 0)
- throw new IllegalStateException("class file has not yet been parsed");
- return endOffset;
- }
-
- /** Report the CP index of this class's own name. */
- public int getThisClassIndex() {
- getEndOffset(); // provoke exception if not yet parsed
- return secondHeader[1];
- }
-
- /** Report the total size of the class file. */
- public int getTailLength() {
- return classFile.length - getEndOffset();
- }
-
- /** Write the head (header plus constant pool)
- * of the class file to the indicated stream.
- */
- public void writeHead(OutputStream out) throws IOException {
- out.write(classFile, 0, getEndOffset());
- }
-
- /** Write the head (header plus constant pool)
- * of the class file to the indicated stream,
- * incorporating the non-null entries of the given array
- * as patches.
- */
- void writePatchedHead(OutputStream out, Object[] patchArray) {
- // this will be useful to partially emulate the class loader on old JVMs
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- /** Write the tail (everything after the constant pool)
- * of the class file to the indicated stream.
- */
- public void writeTail(OutputStream out) throws IOException {
- out.write(classFile, getEndOffset(), getTailLength());
- }
-
- private static char[] parseHeader(byte[] classFile) throws InvalidConstantPoolFormatException {
- char[] result = new char[5];
- ByteBuffer buffer = ByteBuffer.wrap(classFile);
- for (int i = 0; i < result.length; i++)
- result[i] = (char) getUnsignedShort(buffer);
- int magic = result[0] << 16 | result[1] << 0;
- if (magic != 0xCAFEBABE)
- throw new InvalidConstantPoolFormatException("invalid magic number "+magic);
- // skip major, minor version
- int len = result[4];
- if (len < 1)
- throw new InvalidConstantPoolFormatException("constant pool length < 1");
- return result;
- }
-
- /** Parse the constant pool of the class
- * calling a method visit* each time a constant pool entry is parsed.
- *
- * The order of the calls to visit* is not guaranteed to be the same
- * than the order of the constant pool entry in the bytecode array.
- *
- * @param visitor
- * @throws InvalidConstantPoolFormatException
- */
- public void parse(ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
- ByteBuffer buffer = ByteBuffer.wrap(classFile);
- buffer.position(getStartOffset()); //skip header
-
- Object[] values = new Object[getLength()];
- try {
- parseConstantPool(buffer, values, visitor);
- } catch(BufferUnderflowException e) {
- throw new InvalidConstantPoolFormatException(e);
- }
- if (endOffset == 0) {
- endOffset = buffer.position();
- secondHeader = new char[4];
- for (int i = 0; i < secondHeader.length; i++) {
- secondHeader[i] = (char) getUnsignedShort(buffer);
- }
- }
- resolveConstantPool(values, visitor);
- }
-
- private char[] getCharArray(int utfLength) {
- if (utfLength <= charArray.length)
- return charArray;
- return charArray = new char[utfLength];
- }
-
- private void parseConstantPool(ByteBuffer buffer, Object[] values, ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
- for (int i = 1; i < tags.length; ) {
- byte tag = (byte) getUnsignedByte(buffer);
- assert(tags[i] == 0 || tags[i] == tag);
- tags[i] = tag;
- switch (tag) {
- case CONSTANT_Utf8:
- int utfLen = getUnsignedShort(buffer);
- String value = getUTF8(buffer, utfLen, getCharArray(utfLen));
- visitor.visitUTF8(i, CONSTANT_Utf8, value);
- tags[i] = tag;
- values[i++] = value;
- break;
- case CONSTANT_Integer:
- visitor.visitConstantValue(i, tag, buffer.getInt());
- i++;
- break;
- case CONSTANT_Float:
- visitor.visitConstantValue(i, tag, buffer.getFloat());
- i++;
- break;
- case CONSTANT_Long:
- visitor.visitConstantValue(i, tag, buffer.getLong());
- i+=2;
- break;
- case CONSTANT_Double:
- visitor.visitConstantValue(i, tag, buffer.getDouble());
- i+=2;
- break;
-
- case CONSTANT_Class: // fall through:
- case CONSTANT_String:
- tags[i] = tag;
- values[i++] = new int[] { getUnsignedShort(buffer) };
- break;
-
- case CONSTANT_Fieldref: // fall through:
- case CONSTANT_Methodref: // fall through:
- case CONSTANT_InterfaceMethodref: // fall through:
- case CONSTANT_NameAndType:
- tags[i] = tag;
- values[i++] = new int[] { getUnsignedShort(buffer), getUnsignedShort(buffer) };
- break;
- default:
- throw new AssertionError("invalid constant "+tag);
- }
- }
- }
-
- private void resolveConstantPool(Object[] values, ConstantPoolVisitor visitor) {
- // clean out the int[] values, which are temporary
- for (int beg = 1, end = values.length-1, beg2, end2;
- beg <= end;
- beg = beg2, end = end2) {
- beg2 = end; end2 = beg-1;
- //System.out.println("CP resolve pass: "+beg+".."+end);
- for (int i = beg; i <= end; i++) {
- Object value = values[i];
- if (!(value instanceof int[]))
- continue;
- int[] array = (int[]) value;
- byte tag = tags[i];
- switch (tag) {
- case CONSTANT_String:
- String stringBody = (String) values[array[0]];
- visitor.visitConstantString(i, tag, stringBody, array[0]);
- values[i] = null;
- break;
- case CONSTANT_Class: {
- String className = (String) values[array[0]];
- // use the external form favored by Class.forName:
- className = className.replace('/', '.');
- visitor.visitConstantString(i, tag, className, array[0]);
- values[i] = className;
- break;
- }
- case CONSTANT_NameAndType: {
- String memberName = (String) values[array[0]];
- String signature = (String) values[array[1]];
- visitor.visitDescriptor(i, tag, memberName, signature,
- array[0], array[1]);
- values[i] = new String[] {memberName, signature};
- break;
- }
- case CONSTANT_Fieldref: // fall through:
- case CONSTANT_Methodref: // fall through:
- case CONSTANT_InterfaceMethodref: {
- Object className = values[array[0]];
- Object nameAndType = values[array[1]];
- if (!(className instanceof String) ||
- !(nameAndType instanceof String[])) {
- // one more pass is needed
- if (beg2 > i) beg2 = i;
- if (end2 < i) end2 = i;
- continue;
- }
- String[] nameAndTypeArray = (String[]) nameAndType;
- visitor.visitMemberRef(i, tag,
- (String)className,
- nameAndTypeArray[0],
- nameAndTypeArray[1],
- array[0], array[1]);
- values[i] = null;
- }
- break;
- default:
- continue;
- }
- }
- }
- }
-
- private static int getUnsignedByte(ByteBuffer buffer) {
- return buffer.get() & 0xFF;
- }
-
- private static int getUnsignedShort(ByteBuffer buffer) {
- int b1 = getUnsignedByte(buffer);
- int b2 = getUnsignedByte(buffer);
- return (b1 << 8) + (b2 << 0);
- }
-
- private static String getUTF8(ByteBuffer buffer, int utfLen, char[] charArray) throws InvalidConstantPoolFormatException {
- int utfLimit = buffer.position() + utfLen;
- int index = 0;
- while (buffer.position() < utfLimit) {
- int c = buffer.get() & 0xff;
- if (c > 127) {
- buffer.position(buffer.position() - 1);
- return getUTF8Extended(buffer, utfLimit, charArray, index);
- }
- charArray[index++] = (char)c;
- }
- return new String(charArray, 0, index);
- }
-
- private static String getUTF8Extended(ByteBuffer buffer, int utfLimit, char[] charArray, int index) throws InvalidConstantPoolFormatException {
- int c, c2, c3;
- while (buffer.position() < utfLimit) {
- c = buffer.get() & 0xff;
- switch (c >> 4) {
- case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
- /* 0xxxxxxx*/
- charArray[index++] = (char)c;
- break;
- case 12: case 13:
- /* 110x xxxx 10xx xxxx*/
- c2 = buffer.get();
- if ((c2 & 0xC0) != 0x80)
- throw new InvalidConstantPoolFormatException(
- "malformed input around byte " + buffer.position());
- charArray[index++] = (char)(((c & 0x1F) << 6) |
- (c2 & 0x3F));
- break;
- case 14:
- /* 1110 xxxx 10xx xxxx 10xx xxxx */
- c2 = buffer.get();
- c3 = buffer.get();
- if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80))
- throw new InvalidConstantPoolFormatException(
- "malformed input around byte " + (buffer.position()));
- charArray[index++] = (char)(((c & 0x0F) << 12) |
- ((c2 & 0x3F) << 6) |
- ((c3 & 0x3F) << 0));
- break;
- default:
- /* 10xx xxxx, 1111 xxxx */
- throw new InvalidConstantPoolFormatException(
- "malformed input around byte " + buffer.position());
- }
- }
- // The number of chars produced may be less than utflen
- return new String(charArray, 0, index);
- }
-}
--- a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolPatch.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,503 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.anon;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Map;
-
-import static sun.dyn.anon.ConstantPoolVisitor.*;
-
-/** A class and its patched constant pool.
- *
- * This class allow to modify (patch) a constant pool
- * by changing the value of its entry.
- * Entry are referenced using index that can be get
- * by parsing the constant pool using
- * {@link ConstantPoolParser#parse(ConstantPoolVisitor)}.
- *
- * @see ConstantPoolVisitor
- * @see ConstantPoolParser#createPatch()
- */
-public class ConstantPoolPatch {
- final ConstantPoolParser outer;
- final Object[] patchArray;
-
- ConstantPoolPatch(ConstantPoolParser outer) {
- this.outer = outer;
- this.patchArray = new Object[outer.getLength()];
- }
-
- /** Create a {@link ConstantPoolParser} and
- * a {@link ConstantPoolPatch} in one step.
- * Equivalent to {@code new ConstantPoolParser(classFile).createPatch()}.
- *
- * @param classFile an array of bytes containing a class.
- * @see #ConstantPoolParser(Class)
- */
- public ConstantPoolPatch(byte[] classFile) throws InvalidConstantPoolFormatException {
- this(new ConstantPoolParser(classFile));
- }
-
- /** Create a {@link ConstantPoolParser} and
- * a {@link ConstantPoolPatch} in one step.
- * Equivalent to {@code new ConstantPoolParser(templateClass).createPatch()}.
- *
- * @param templateClass the class to parse.
- * @see #ConstantPoolParser(Class)
- */
- public ConstantPoolPatch(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
- this(new ConstantPoolParser(templateClass));
- }
-
-
- /** Creates a patch from an existing patch.
- * All changes are copied from that patch.
- * @param patch a patch
- *
- * @see ConstantPoolParser#createPatch()
- */
- public ConstantPoolPatch(ConstantPoolPatch patch) {
- outer = patch.outer;
- patchArray = patch.patchArray.clone();
- }
-
- /** Which parser built this patch? */
- public ConstantPoolParser getParser() {
- return outer;
- }
-
- /** Report the tag at the given index in the constant pool. */
- public byte getTag(int index) {
- return outer.getTag(index);
- }
-
- /** Report the current patch at the given index of the constant pool.
- * Null means no patch will be made.
- * To observe the unpatched entry at the given index, use
- * {@link #getParser()}{@code .}@link ConstantPoolParser#parse(ConstantPoolVisitor)}
- */
- public Object getPatch(int index) {
- Object value = patchArray[index];
- if (value == null) return null;
- switch (getTag(index)) {
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- if (value instanceof String)
- value = stripSemis(2, (String) value);
- break;
- case CONSTANT_NameAndType:
- if (value instanceof String)
- value = stripSemis(1, (String) value);
- break;
- }
- return value;
- }
-
- /** Clear all patches. */
- public void clear() {
- Arrays.fill(patchArray, null);
- }
-
- /** Clear one patch. */
- public void clear(int index) {
- patchArray[index] = null;
- }
-
- /** Produce the patches as an array. */
- public Object[] getPatches() {
- return patchArray.clone();
- }
-
- /** Produce the original constant pool as an array. */
- public Object[] getOriginalCP() throws InvalidConstantPoolFormatException {
- return getOriginalCP(0, patchArray.length, -1);
- }
-
- /** Walk the constant pool, applying patches using the given map.
- *
- * @param utf8Map Utf8 strings to modify, if encountered
- * @param classMap Classes (or their names) to modify, if encountered
- * @param valueMap Constant values to modify, if encountered
- * @param deleteUsedEntries if true, delete map entries that are used
- */
- public void putPatches(final Map<String,String> utf8Map,
- final Map<String,Object> classMap,
- final Map<Object,Object> valueMap,
- boolean deleteUsedEntries) throws InvalidConstantPoolFormatException {
- final HashSet<String> usedUtf8Keys;
- final HashSet<String> usedClassKeys;
- final HashSet<Object> usedValueKeys;
- if (deleteUsedEntries) {
- usedUtf8Keys = (utf8Map == null) ? null : new HashSet<String>();
- usedClassKeys = (classMap == null) ? null : new HashSet<String>();
- usedValueKeys = (valueMap == null) ? null : new HashSet<Object>();
- } else {
- usedUtf8Keys = null;
- usedClassKeys = null;
- usedValueKeys = null;
- }
-
- outer.parse(new ConstantPoolVisitor() {
-
- @Override
- public void visitUTF8(int index, byte tag, String utf8) {
- putUTF8(index, utf8Map.get(utf8));
- if (usedUtf8Keys != null) usedUtf8Keys.add(utf8);
- }
-
- @Override
- public void visitConstantValue(int index, byte tag, Object value) {
- putConstantValue(index, tag, valueMap.get(value));
- if (usedValueKeys != null) usedValueKeys.add(value);
- }
-
- @Override
- public void visitConstantString(int index, byte tag, String name, int nameIndex) {
- if (tag == CONSTANT_Class) {
- putConstantValue(index, tag, classMap.get(name));
- if (usedClassKeys != null) usedClassKeys.add(name);
- } else {
- assert(tag == CONSTANT_String);
- visitConstantValue(index, tag, name);
- }
- }
- });
- if (usedUtf8Keys != null) utf8Map.keySet().removeAll(usedUtf8Keys);
- if (usedClassKeys != null) classMap.keySet().removeAll(usedClassKeys);
- if (usedValueKeys != null) valueMap.keySet().removeAll(usedValueKeys);
- }
-
- Object[] getOriginalCP(final int startIndex,
- final int endIndex,
- final int tagMask) throws InvalidConstantPoolFormatException {
- final Object[] cpArray = new Object[endIndex - startIndex];
- outer.parse(new ConstantPoolVisitor() {
-
- void show(int index, byte tag, Object value) {
- if (index < startIndex || index >= endIndex) return;
- if (((1 << tag) & tagMask) == 0) return;
- cpArray[index - startIndex] = value;
- }
-
- @Override
- public void visitUTF8(int index, byte tag, String utf8) {
- show(index, tag, utf8);
- }
-
- @Override
- public void visitConstantValue(int index, byte tag, Object value) {
- assert(tag != CONSTANT_String);
- show(index, tag, value);
- }
-
- @Override
- public void visitConstantString(int index, byte tag,
- String value, int j) {
- show(index, tag, value);
- }
-
- @Override
- public void visitMemberRef(int index, byte tag,
- String className, String memberName,
- String signature,
- int j, int k) {
- show(index, tag, new String[]{ className, memberName, signature });
- }
-
- @Override
- public void visitDescriptor(int index, byte tag,
- String memberName, String signature,
- int j, int k) {
- show(index, tag, new String[]{ memberName, signature });
- }
- });
- return cpArray;
- }
-
- /** Write the head (header plus constant pool)
- * of the patched class file to the indicated stream.
- */
- void writeHead(OutputStream out) throws IOException {
- outer.writePatchedHead(out, patchArray);
- }
-
- /** Write the tail (everything after the constant pool)
- * of the patched class file to the indicated stream.
- */
- void writeTail(OutputStream out) throws IOException {
- outer.writeTail(out);
- }
-
- private void checkConstantTag(byte tag, Object value) {
- if (value == null)
- throw new IllegalArgumentException(
- "invalid null constant value");
- if (classForTag(tag) != value.getClass())
- throw new IllegalArgumentException(
- "invalid constant value"
- + (tag == CONSTANT_None ? ""
- : " for tag "+tagName(tag))
- + " of class "+value.getClass());
- }
-
- private void checkTag(int index, byte putTag) {
- byte tag = outer.tags[index];
- if (tag != putTag)
- throw new IllegalArgumentException(
- "invalid put operation"
- + " for " + tagName(putTag)
- + " at index " + index + " found " + tagName(tag));
- }
-
- private void checkTagMask(int index, int tagBitMask) {
- byte tag = outer.tags[index];
- int tagBit = ((tag & 0x1F) == tag) ? (1 << tag) : 0;
- if ((tagBit & tagBitMask) == 0)
- throw new IllegalArgumentException(
- "invalid put operation"
- + " at index " + index + " found " + tagName(tag));
- }
-
- private static void checkMemberName(String memberName) {
- if (memberName.indexOf(';') >= 0)
- throw new IllegalArgumentException("memberName " + memberName + " contains a ';'");
- }
-
- /** Set the entry of the constant pool indexed by index to
- * a new string.
- *
- * @param index an index to a constant pool entry containing a
- * {@link ConstantPoolVisitor#CONSTANT_Utf8} value.
- * @param utf8 a string
- *
- * @see ConstantPoolVisitor#visitUTF8(int, byte, String)
- */
- public void putUTF8(int index, String utf8) {
- if (utf8 == null) { clear(index); return; }
- checkTag(index, CONSTANT_Utf8);
- patchArray[index] = utf8;
- }
-
- /** Set the entry of the constant pool indexed by index to
- * a new value, depending on its dynamic type.
- *
- * @param index an index to a constant pool entry containing a
- * one of the following structures:
- * {@link ConstantPoolVisitor#CONSTANT_Integer},
- * {@link ConstantPoolVisitor#CONSTANT_Float},
- * {@link ConstantPoolVisitor#CONSTANT_Long},
- * {@link ConstantPoolVisitor#CONSTANT_Double},
- * {@link ConstantPoolVisitor#CONSTANT_String}, or
- * {@link ConstantPoolVisitor#CONSTANT_Class}
- * @param value a boxed int, float, long or double; or a string or class object
- * @throws IllegalArgumentException if the type of the constant does not
- * match the constant pool entry type,
- * as reported by {@link #getTag(int)}
- *
- * @see #putConstantValue(int, byte, Object)
- * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
- * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
- */
- public void putConstantValue(int index, Object value) {
- if (value == null) { clear(index); return; }
- byte tag = tagForConstant(value.getClass());
- checkConstantTag(tag, value);
- checkTag(index, tag);
- patchArray[index] = value;
- }
-
- /** Set the entry of the constant pool indexed by index to
- * a new value.
- *
- * @param index an index to a constant pool entry matching the given tag
- * @param tag one of the following values:
- * {@link ConstantPoolVisitor#CONSTANT_Integer},
- * {@link ConstantPoolVisitor#CONSTANT_Float},
- * {@link ConstantPoolVisitor#CONSTANT_Long},
- * {@link ConstantPoolVisitor#CONSTANT_Double},
- * {@link ConstantPoolVisitor#CONSTANT_String}, or
- * {@link ConstantPoolVisitor#CONSTANT_Class}
- * @param value a boxed number, string, or class object
- * @throws IllegalArgumentException if the type of the constant does not
- * match the constant pool entry type, or if a class name contains
- * '/' or ';'
- *
- * @see #putConstantValue(int, Object)
- * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
- * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
- */
- public void putConstantValue(int index, byte tag, Object value) {
- if (value == null) { clear(index); return; }
- checkTag(index, tag);
- if (tag == CONSTANT_Class && value instanceof String) {
- checkClassName((String) value);
- } else if (tag == CONSTANT_String) {
- // the JVM accepts any object as a patch for a string
- } else {
- // make sure the incoming value is the right type
- checkConstantTag(tag, value);
- }
- checkTag(index, tag);
- patchArray[index] = value;
- }
-
- /** Set the entry of the constant pool indexed by index to
- * a new {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
- *
- * @param index an index to a constant pool entry containing a
- * {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
- * @param memberName a memberName
- * @param signature a signature
- * @throws IllegalArgumentException if memberName contains the character ';'
- *
- * @see ConstantPoolVisitor#visitDescriptor(int, byte, String, String, int, int)
- */
- public void putDescriptor(int index, String memberName, String signature) {
- checkTag(index, CONSTANT_NameAndType);
- checkMemberName(memberName);
- patchArray[index] = addSemis(memberName, signature);
- }
-
- /** Set the entry of the constant pool indexed by index to
- * a new {@link ConstantPoolVisitor#CONSTANT_Fieldref},
- * {@link ConstantPoolVisitor#CONSTANT_Methodref}, or
- * {@link ConstantPoolVisitor#CONSTANT_InterfaceMethodref} value.
- *
- * @param index an index to a constant pool entry containing a member reference
- * @param className a class name
- * @param memberName a field or method name
- * @param signature a field or method signature
- * @throws IllegalArgumentException if memberName contains the character ';'
- * or signature is not a correct signature
- *
- * @see ConstantPoolVisitor#visitMemberRef(int, byte, String, String, String, int, int)
- */
- public void putMemberRef(int index, byte tag,
- String className, String memberName, String signature) {
- checkTagMask(tag, CONSTANT_MemberRef_MASK);
- checkTag(index, tag);
- checkClassName(className);
- checkMemberName(memberName);
- if (signature.startsWith("(") == (tag == CONSTANT_Fieldref))
- throw new IllegalArgumentException("bad signature: "+signature);
- patchArray[index] = addSemis(className, memberName, signature);
- }
-
- static private final int CONSTANT_MemberRef_MASK =
- CONSTANT_Fieldref
- | CONSTANT_Methodref
- | CONSTANT_InterfaceMethodref;
-
- private static final Map<Class<?>, Byte> CONSTANT_VALUE_CLASS_TAG
- = new IdentityHashMap<Class<?>, Byte>();
- private static final Class[] CONSTANT_VALUE_CLASS = new Class[16];
- static {
- Object[][] values = {
- {Integer.class, CONSTANT_Integer},
- {Long.class, CONSTANT_Long},
- {Float.class, CONSTANT_Float},
- {Double.class, CONSTANT_Double},
- {String.class, CONSTANT_String},
- {Class.class, CONSTANT_Class}
- };
- for (Object[] value : values) {
- Class<?> cls = (Class<?>)value[0];
- Byte tag = (Byte) value[1];
- CONSTANT_VALUE_CLASS_TAG.put(cls, tag);
- CONSTANT_VALUE_CLASS[(byte)tag] = cls;
- }
- }
-
- static Class<?> classForTag(byte tag) {
- if ((tag & 0xFF) >= CONSTANT_VALUE_CLASS.length)
- return null;
- return CONSTANT_VALUE_CLASS[tag];
- }
-
- static byte tagForConstant(Class<?> cls) {
- Byte tag = CONSTANT_VALUE_CLASS_TAG.get(cls);
- return (tag == null) ? CONSTANT_None : (byte)tag;
- }
-
- private static void checkClassName(String className) {
- if (className.indexOf('/') >= 0 || className.indexOf(';') >= 0)
- throw new IllegalArgumentException("invalid class name " + className);
- }
-
- static String addSemis(String name, String... names) {
- StringBuilder buf = new StringBuilder(name.length() * 5);
- buf.append(name);
- for (String name2 : names) {
- buf.append(';').append(name2);
- }
- String res = buf.toString();
- assert(stripSemis(names.length, res)[0].equals(name));
- assert(stripSemis(names.length, res)[1].equals(names[0]));
- assert(names.length == 1 ||
- stripSemis(names.length, res)[2].equals(names[1]));
- return res;
- }
-
- static String[] stripSemis(int count, String string) {
- String[] res = new String[count+1];
- int pos = 0;
- for (int i = 0; i < count; i++) {
- int pos2 = string.indexOf(';', pos);
- if (pos2 < 0) pos2 = string.length(); // yuck
- res[i] = string.substring(pos, pos2);
- pos = pos2;
- }
- res[count] = string.substring(pos);
- return res;
- }
-
- public String toString() {
- StringBuilder buf = new StringBuilder(this.getClass().getName());
- buf.append("{");
- Object[] origCP = null;
- for (int i = 0; i < patchArray.length; i++) {
- if (patchArray[i] == null) continue;
- if (origCP != null) {
- buf.append(", ");
- } else {
- try {
- origCP = getOriginalCP();
- } catch (InvalidConstantPoolFormatException ee) {
- origCP = new Object[0];
- }
- }
- Object orig = (i < origCP.length) ? origCP[i] : "?";
- buf.append(orig).append("=").append(patchArray[i]);
- }
- buf.append("}");
- return buf.toString();
- }
-}
--- a/jdk/src/share/classes/sun/dyn/anon/ConstantPoolVisitor.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.anon;
-
-/**
- * A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
- * when a constant pool entry is parsed.
- * <p>
- * A visit* method is called when a constant pool entry is parsed.
- * The first argument is always the constant pool index.
- * The second argument is always the constant pool tag,
- * even for methods like {@link #visitUTF8(int, byte, String)} which only apply to one tag.
- * String arguments refer to Utf8 or NameAndType entries declared elsewhere,
- * and are always accompanied by the indexes of those entries.
- * <p>
- * The order of the calls to the visit* methods is not necessarily related
- * to the order of the entries in the constant pool.
- * If one entry has a reference to another entry, the latter (lower-level)
- * entry will be visited first.
- * <p>
- * The following table shows the relation between constant pool entry
- * types and the corresponding visit* methods:
- *
- * <table border=1 cellpadding=5 summary="constant pool visitor methods">
- * <tr><th>Tag(s)</th><th>Method</th></tr>
- * <tr>
- * <td>{@link #CONSTANT_Utf8}</td>
- * <td>{@link #visitUTF8(int, byte, String)}</td>
- * </tr><tr>
- * <td>{@link #CONSTANT_Integer}, {@link #CONSTANT_Float},
- * {@link #CONSTANT_Long}, {@link #CONSTANT_Double}</td>
- * <td>{@link #visitConstantValue(int, byte, Object)}</td>
- * </tr><tr>
- * <td>{@link #CONSTANT_String}, {@link #CONSTANT_Class}</td>
- * <td>{@link #visitConstantString(int, byte, String, int)}</td>
- * </tr><tr>
- * <td>{@link #CONSTANT_NameAndType}</td>
- * <td>{@link #visitDescriptor(int, byte, String, String, int, int)}</td>
- * </tr><tr>
- * <td>{@link #CONSTANT_Fieldref},
- * {@link #CONSTANT_Methodref},
- * {@link #CONSTANT_InterfaceMethodref}</td>
- * <td>{@link #visitMemberRef(int, byte, String, String, String, int, int)}</td>
- * </tr>
- * </table>
- *
- * @see ConstantPoolPatch
- * @author Remi Forax
- * @author jrose
- */
-public class ConstantPoolVisitor {
- /** Called each time an UTF8 constant pool entry is found.
- * @param index the constant pool index
- * @param tag always {@link #CONSTANT_Utf8}
- * @param utf8 string encoded in modified UTF-8 format passed as a {@code String}
- *
- * @see ConstantPoolPatch#putUTF8(int, String)
- */
- public void visitUTF8(int index, byte tag, String utf8) {
- // do nothing
- }
-
- /** Called for each constant pool entry that encodes an integer,
- * a float, a long, or a double.
- * Constant strings and classes are not managed by this method but
- * by {@link #visitConstantString(int, byte, String, int)}.
- *
- * @param index the constant pool index
- * @param tag one of {@link #CONSTANT_Integer},
- * {@link #CONSTANT_Float},
- * {@link #CONSTANT_Long},
- * or {@link #CONSTANT_Double}
- * @param value encoded value
- *
- * @see ConstantPoolPatch#putConstantValue(int, Object)
- */
- public void visitConstantValue(int index, byte tag, Object value) {
- // do nothing
- }
-
- /** Called for each constant pool entry that encodes a string or a class.
- * @param index the constant pool index
- * @param tag one of {@link #CONSTANT_String},
- * {@link #CONSTANT_Class},
- * @param name string body or class name (using dot separator)
- * @param nameIndex the index of the Utf8 string for the name
- *
- * @see ConstantPoolPatch#putConstantValue(int, byte, Object)
- */
- public void visitConstantString(int index, byte tag,
- String name, int nameIndex) {
- // do nothing
- }
-
- /** Called for each constant pool entry that encodes a name and type.
- * @param index the constant pool index
- * @param tag always {@link #CONSTANT_NameAndType}
- * @param memberName a field or method name
- * @param signature the member signature
- * @param memberNameIndex index of the Utf8 string for the member name
- * @param signatureIndex index of the Utf8 string for the signature
- *
- * @see ConstantPoolPatch#putDescriptor(int, String, String)
- */
- public void visitDescriptor(int index, byte tag,
- String memberName, String signature,
- int memberNameIndex, int signatureIndex) {
- // do nothing
- }
-
- /** Called for each constant pool entry that encodes a field or method.
- * @param index the constant pool index
- * @param tag one of {@link #CONSTANT_Fieldref},
- * or {@link #CONSTANT_Methodref},
- * or {@link #CONSTANT_InterfaceMethodref}
- * @param className the class name (using dot separator)
- * @param memberName name of the field or method
- * @param signature the field or method signature
- * @param classNameIndex index of the Utf8 string for the class name
- * @param descriptorIndex index of the NameAndType descriptor constant
- *
- * @see ConstantPoolPatch#putMemberRef(int, byte, String, String, String)
- */
- public void visitMemberRef(int index, byte tag,
- String className, String memberName, String signature,
- int classNameIndex, int descriptorIndex) {
- // do nothing
- }
-
- public static final byte
- CONSTANT_None = 0,
- CONSTANT_Utf8 = 1,
- //CONSTANT_Unicode = 2, /* unused */
- CONSTANT_Integer = 3,
- CONSTANT_Float = 4,
- CONSTANT_Long = 5,
- CONSTANT_Double = 6,
- CONSTANT_Class = 7,
- CONSTANT_String = 8,
- CONSTANT_Fieldref = 9,
- CONSTANT_Methodref = 10,
- CONSTANT_InterfaceMethodref = 11,
- CONSTANT_NameAndType = 12;
-
- private static String[] TAG_NAMES = {
- "Empty",
- "Utf8",
- null, //"Unicode",
- "Integer",
- "Float",
- "Long",
- "Double",
- "Class",
- "String",
- "Fieldref",
- "Methodref",
- "InterfaceMethodref",
- "NameAndType"
- };
-
- public static String tagName(byte tag) {
- String name = null;
- if ((tag & 0xFF) < TAG_NAMES.length)
- name = TAG_NAMES[tag];
- if (name == null)
- name = "Unknown#"+(tag&0xFF);
- return name;
- }
-}
--- a/jdk/src/share/classes/sun/dyn/anon/InvalidConstantPoolFormatException.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.anon;
-
-/** Exception used when there is an error in the constant pool
- * format.
- */
-public class InvalidConstantPoolFormatException extends Exception {
- private static final long serialVersionUID=-6103888330523770949L;
-
- public InvalidConstantPoolFormatException(String message,Throwable cause) {
- super(message,cause);
- }
-
- public InvalidConstantPoolFormatException(String message) {
- super(message);
- }
-
- public InvalidConstantPoolFormatException(Throwable cause) {
- super(cause);
- }
-}
--- a/jdk/src/share/classes/sun/dyn/empty/Empty.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.empty;
-
-/**
- * An empty class in an empty package.
- * Used as a proxy for unprivileged code, since making access checks
- * against it will only succeed against public methods in public types.
- * <p>
- * This class also stands (internally to sun.dyn) for the type of a
- * value that cannot be produced, because the expression of this type
- * always returns abnormally. (Cf. Nothing in the closures proposal.)
- * @author jrose
- */
-public class Empty {
- private Empty() { throw new InternalError(); }
-}
--- a/jdk/src/share/classes/sun/dyn/package-info.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * Implementation details for JSR 292 RI, package java.dyn.
- * @author jrose
- */
-
-package sun.dyn;
--- a/jdk/src/share/classes/sun/dyn/util/BytecodeDescriptor.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-import java.dyn.MethodType;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Utility routines for dealing with bytecode-level signatures.
- * @author jrose
- */
-public class BytecodeDescriptor {
-
- private BytecodeDescriptor() { } // cannot instantiate
-
- public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
- return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
- }
-
- static List<Class<?>> parseMethod(String bytecodeSignature,
- int start, int end, ClassLoader loader) {
- if (loader == null)
- loader = ClassLoader.getSystemClassLoader();
- String str = bytecodeSignature;
- int[] i = {start};
- ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>();
- if (i[0] < end && str.charAt(i[0]) == '(') {
- ++i[0]; // skip '('
- while (i[0] < end && str.charAt(i[0]) != ')') {
- Class<?> pt = parseSig(str, i, end, loader);
- if (pt == null || pt == void.class)
- parseError(str, "bad argument type");
- ptypes.add(pt);
- }
- ++i[0]; // skip ')'
- } else {
- parseError(str, "not a method type");
- }
- Class<?> rtype = parseSig(str, i, end, loader);
- if (rtype == null || i[0] != end)
- parseError(str, "bad return type");
- ptypes.add(rtype);
- return ptypes;
- }
-
- static private void parseError(String str, String msg) {
- throw new IllegalArgumentException("bad signature: "+str+": "+msg);
- }
-
- static private Class<?> parseSig(String str, int[] i, int end, ClassLoader loader) {
- if (i[0] == end) return null;
- char c = str.charAt(i[0]++);
- if (c == 'L') {
- int begc = i[0], endc = str.indexOf(';', begc);
- if (endc < 0) return null;
- i[0] = endc+1;
- String name = str.substring(begc, endc).replace('/', '.');
- try {
- return loader.loadClass(name);
- } catch (ClassNotFoundException ex) {
- throw new TypeNotPresentException(name, ex);
- }
- } else if (c == '[') {
- Class<?> t = parseSig(str, i, end, loader);
- if (t != null)
- t = java.lang.reflect.Array.newInstance(t, 0).getClass();
- return t;
- } else {
- return Wrapper.forBasicType(c).primitiveType();
- }
- }
-
- public static String unparse(Class<?> type) {
- StringBuilder sb = new StringBuilder();
- unparseSig(type, sb);
- return sb.toString();
- }
-
- public static String unparse(MethodType type) {
- return unparseMethod(type.returnType(), type.parameterList());
- }
-
- public static String unparse(Object type) {
- if (type instanceof Class<?>)
- return unparse((Class<?>) type);
- if (type instanceof MethodType)
- return unparse((MethodType) type);
- return (String) type;
- }
-
- public static String unparseMethod(Class<?> rtype, List<Class<?>> ptypes) {
- StringBuilder sb = new StringBuilder();
- sb.append('(');
- for (Class<?> pt : ptypes)
- unparseSig(pt, sb);
- sb.append(')');
- unparseSig(rtype, sb);
- return sb.toString();
- }
-
- static private void unparseSig(Class<?> t, StringBuilder sb) {
- char c = Wrapper.forBasicType(t).basicTypeChar();
- if (c != 'L') {
- sb.append(c);
- } else {
- boolean lsemi = (!t.isArray());
- if (lsemi) sb.append('L');
- sb.append(t.getName().replace('.', '/'));
- if (lsemi) sb.append(';');
- }
- }
-
-}
--- a/jdk/src/share/classes/sun/dyn/util/BytecodeName.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,627 +0,0 @@
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-/**
- * Utility routines for dealing with bytecode-level names.
- * Includes universal mangling rules for the JVM.
- *
- * <h3>Avoiding Dangerous Characters </h3>
- *
- * <p>
- * The JVM defines a very small set of characters which are illegal
- * in name spellings. We will slightly extend and regularize this set
- * into a group of <cite>dangerous characters</cite>.
- * These characters will then be replaced, in mangled names, by escape sequences.
- * In addition, accidental escape sequences must be further escaped.
- * Finally, a special prefix will be applied if and only if
- * the mangling would otherwise fail to begin with the escape character.
- * This happens to cover the corner case of the null string,
- * and also clearly marks symbols which need demangling.
- * </p>
- * <p>
- * Dangerous characters are the union of all characters forbidden
- * or otherwise restricted by the JVM specification,
- * plus their mates, if they are brackets
- * (<code><big><b>[</b></big></code> and <code><big><b>]</b></big></code>,
- * <code><big><b><</b></big></code> and <code><big><b>></b></big></code>),
- * plus, arbitrarily, the colon character <code><big><b>:</b></big></code>.
- * There is no distinction between type, method, and field names.
- * This makes it easier to convert between mangled names of different
- * types, since they do not need to be decoded (demangled).
- * </p>
- * <p>
- * The escape character is backslash <code><big><b>\</b></big></code>
- * (also known as reverse solidus).
- * This character is, until now, unheard of in bytecode names,
- * but traditional in the proposed role.
- *
- * </p>
- * <h3> Replacement Characters </h3>
- *
- *
- * <p>
- * Every escape sequence is two characters
- * (in fact, two UTF8 bytes) beginning with
- * the escape character and followed by a
- * <cite>replacement character</cite>.
- * (Since the replacement character is never a backslash,
- * iterated manglings do not double in size.)
- * </p>
- * <p>
- * Each dangerous character has some rough visual similarity
- * to its corresponding replacement character.
- * This makes mangled symbols easier to recognize by sight.
- * </p>
- * <p>
- * The dangerous characters are
- * <code><big><b>/</b></big></code> (forward slash, used to delimit package components),
- * <code><big><b>.</b></big></code> (dot, also a package delimiter),
- * <code><big><b>;</b></big></code> (semicolon, used in signatures),
- * <code><big><b>$</b></big></code> (dollar, used in inner classes and synthetic members),
- * <code><big><b><</b></big></code> (left angle),
- * <code><big><b>></b></big></code> (right angle),
- * <code><big><b>[</b></big></code> (left square bracket, used in array types),
- * <code><big><b>]</b></big></code> (right square bracket, reserved in this scheme for language use),
- * and <code><big><b>:</b></big></code> (colon, reserved in this scheme for language use).
- * Their replacements are, respectively,
- * <code><big><b>|</b></big></code> (vertical bar),
- * <code><big><b>,</b></big></code> (comma),
- * <code><big><b>?</b></big></code> (question mark),
- * <code><big><b>%</b></big></code> (percent),
- * <code><big><b>^</b></big></code> (caret),
- * <code><big><b>_</b></big></code> (underscore), and
- * <code><big><b>{</b></big></code> (left curly bracket),
- * <code><big><b>}</b></big></code> (right curly bracket),
- * <code><big><b>!</b></big></code> (exclamation mark).
- * In addition, the replacement character for the escape character itself is
- * <code><big><b>-</b></big></code> (hyphen),
- * and the replacement character for the null prefix is
- * <code><big><b>=</b></big></code> (equal sign).
- * </p>
- * <p>
- * An escape character <code><big><b>\</b></big></code>
- * followed by any of these replacement characters
- * is an escape sequence, and there are no other escape sequences.
- * An equal sign is only part of an escape sequence
- * if it is the second character in the whole string, following a backslash.
- * Two consecutive backslashes do <em>not</em> form an escape sequence.
- * </p>
- * <p>
- * Each escape sequence replaces a so-called <cite>original character</cite>
- * which is either one of the dangerous characters or the escape character.
- * A null prefix replaces an initial null string, not a character.
- * </p>
- * <p>
- * All this implies that escape sequences cannot overlap and may be
- * determined all at once for a whole string. Note that a spelling
- * string can contain <cite>accidental escapes</cite>, apparent escape
- * sequences which must not be interpreted as manglings.
- * These are disabled by replacing their leading backslash with an
- * escape sequence (<code><big><b>\-</b></big></code>). To mangle a string, three logical steps
- * are required, though they may be carried out in one pass:
- * </p>
- * <ol>
- * <li>In each accidental escape, replace the backslash with an escape sequence
- * (<code><big><b>\-</b></big></code>).</li>
- * <li>Replace each dangerous character with an escape sequence
- * (<code><big><b>\|</b></big></code> for <code><big><b>/</b></big></code>, etc.).</li>
- * <li>If the first two steps introduced any change, <em>and</em>
- * if the string does not already begin with a backslash, prepend a null prefix (<code><big><b>\=</b></big></code>).</li>
- * </ol>
- *
- * To demangle a mangled string that begins with an escape,
- * remove any null prefix, and then replace (in parallel)
- * each escape sequence by its original character.
- * <p>Spelling strings which contain accidental
- * escapes <em>must</em> have them replaced, even if those
- * strings do not contain dangerous characters.
- * This restriction means that mangling a string always
- * requires a scan of the string for escapes.
- * But then, a scan would be required anyway,
- * to check for dangerous characters.
- *
- * </p>
- * <h3> Nice Properties </h3>
- *
- * <p>
- * If a bytecode name does not contain any escape sequence,
- * demangling is a no-op: The string demangles to itself.
- * Such a string is called <cite>self-mangling</cite>.
- * Almost all strings are self-mangling.
- * In practice, to demangle almost any name “found in nature”,
- * simply verify that it does not begin with a backslash.
- * </p>
- * <p>
- * Mangling is a one-to-one function, while demangling
- * is a many-to-one function.
- * A mangled string is defined as <cite>validly mangled</cite> if
- * it is in fact the unique mangling of its spelling string.
- * Three examples of invalidly mangled strings are <code><big><b>\=foo</b></big></code>,
- * <code><big><b>\-bar</b></big></code>, and <code><big><b>baz\!</b></big></code>, which demangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and
- * <code><big><b>baz\!</b></big></code>, but then remangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and <code><big><b>\=baz\-!</b></big></code>.
- * If a language back-end or runtime is using mangled names,
- * it should never present an invalidly mangled bytecode
- * name to the JVM. If the runtime encounters one,
- * it should also report an error, since such an occurrence
- * probably indicates a bug in name encoding which
- * will lead to errors in linkage.
- * However, this note does not propose that the JVM verifier
- * detect invalidly mangled names.
- * </p>
- * <p>
- * As a result of these rules, it is a simple matter to
- * compute validly mangled substrings and concatenations
- * of validly mangled strings, and (with a little care)
- * these correspond to corresponding operations on their
- * spelling strings.
- * </p>
- * <ul>
- * <li>Any prefix of a validly mangled string is also validly mangled,
- * although a null prefix may need to be removed.</li>
- * <li>Any suffix of a validly mangled string is also validly mangled,
- * although a null prefix may need to be added.</li>
- * <li>Two validly mangled strings, when concatenated,
- * are also validly mangled, although any null prefix
- * must be removed from the second string,
- * and a trailing backslash on the first string may need escaping,
- * if it would participate in an accidental escape when followed
- * by the first character of the second string.</li>
- * </ul>
- * <p>If languages that include non-Java symbol spellings use this
- * mangling convention, they will enjoy the following advantages:
- * </p>
- * <ul>
- * <li>They can interoperate via symbols they share in common.</li>
- * <li>Low-level tools, such as backtrace printers, will have readable displays.</li>
- * <li>Future JVM and language extensions can safely use the dangerous characters
- * for structuring symbols, but will never interfere with valid spellings.</li>
- * <li>Runtimes and compilers can use standard libraries for mangling and demangling.</li>
- * <li>Occasional transliterations and name composition will be simple and regular,
- * for classes, methods, and fields.</li>
- * <li>Bytecode names will continue to be compact.
- * When mangled, spellings will at most double in length, either in
- * UTF8 or UTF16 format, and most will not change at all.</li>
- * </ul>
- *
- *
- * <h3> Suggestions for Human Readable Presentations </h3>
- *
- *
- * <p>
- * For human readable displays of symbols,
- * it will be better to present a string-like quoted
- * representation of the spelling, because JVM users
- * are generally familiar with such tokens.
- * We suggest using single or double quotes before and after
- * mangled symbols which are not valid Java identifiers,
- * with quotes, backslashes, and non-printing characters
- * escaped as if for literals in the Java language.
- * </p>
- * <p>
- * For example, an HTML-like spelling
- * <code><big><b><pre></b></big></code> mangles to
- * <code><big><b>\^pre\_</b></big></code> and could
- * display more cleanly as
- * <code><big><b>'<pre>'</b></big></code>,
- * with the quotes included.
- * Such string-like conventions are <em>not</em> suitable
- * for mangled bytecode names, in part because
- * dangerous characters must be eliminated, rather
- * than just quoted. Otherwise internally structured
- * strings like package prefixes and method signatures
- * could not be reliably parsed.
- * </p>
- * <p>
- * In such human-readable displays, invalidly mangled
- * names should <em>not</em> be demangled and quoted,
- * for this would be misleading. Likewise, JVM symbols
- * which contain dangerous characters (like dots in field
- * names or brackets in method names) should not be
- * simply quoted. The bytecode names
- * <code><big><b>\=phase\,1</b></big></code> and
- * <code><big><b>phase.1</b></big></code> are distinct,
- * and in demangled displays they should be presented as
- * <code><big><b>'phase.1'</b></big></code> and something like
- * <code><big><b>'phase'.1</b></big></code>, respectively.
- * </p>
- *
- * @author John Rose
- * @version 1.2, 02/06/2008
- * @see http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm
- */
-public class BytecodeName {
- private BytecodeName() { } // static only class
-
- /** Given a source name, produce the corresponding bytecode name.
- * The source name should not be qualified, because any syntactic
- * markers (dots, slashes, dollar signs, colons, etc.) will be mangled.
- * @param s the source name
- * @return a valid bytecode name which represents the source name
- */
- public static String toBytecodeName(String s) {
- String bn = mangle(s);
- assert((Object)bn == s || looksMangled(bn)) : bn;
- assert(s.equals(toSourceName(bn))) : s;
- return bn;
- }
-
- /** Given an unqualified bytecode name, produce the corresponding source name.
- * The bytecode name must not contain dangerous characters.
- * In particular, it must not be qualified or segmented by colon {@code ':'}.
- * @param s the bytecode name
- * @return the source name, which may possibly have unsafe characters
- * @throws IllegalArgumentException if the bytecode name is not {@link #isSafeBytecodeName safe}
- * @see #isSafeBytecodeName(java.lang.String)
- */
- public static String toSourceName(String s) {
- checkSafeBytecodeName(s);
- String sn = s;
- if (looksMangled(s)) {
- sn = demangle(s);
- assert(s.equals(mangle(sn))) : s+" => "+sn+" => "+mangle(sn);
- }
- return sn;
- }
-
- /**
- * Given a bytecode name from a classfile, separate it into
- * components delimited by dangerous characters.
- * Each resulting array element will be either a dangerous character,
- * or else a safe bytecode name.
- * (The safe name might possibly be mangled to hide further dangerous characters.)
- * For example, the qualified class name {@code java/lang/String}
- * will be parsed into the array {@code {"java", '/', "lang", '/', "String"}}.
- * The name {@code <init>} will be parsed into { '<', "init", '>'}}
- * The name {@code foo/bar$:baz} will be parsed into
- * {@code {"foo", '/', "bar", '$', ':', "baz"}}.
- * The name {@code ::\=:foo:\=bar\!baz} will be parsed into
- * {@code {':', ':', "", ':', "foo", ':', "bar:baz"}}.
- */
- public static Object[] parseBytecodeName(String s) {
- int slen = s.length();
- Object[] res = null;
- for (int pass = 0; pass <= 1; pass++) {
- int fillp = 0;
- int lasti = 0;
- for (int i = 0; i <= slen; i++) {
- int whichDC = -1;
- if (i < slen) {
- whichDC = DANGEROUS_CHARS.indexOf(s.charAt(i));
- if (whichDC < DANGEROUS_CHAR_FIRST_INDEX) continue;
- }
- // got to end of string or next dangerous char
- if (lasti < i) {
- // normal component
- if (pass != 0)
- res[fillp] = toSourceName(s.substring(lasti, i));
- fillp++;
- lasti = i+1;
- }
- if (whichDC >= DANGEROUS_CHAR_FIRST_INDEX) {
- if (pass != 0)
- res[fillp] = DANGEROUS_CHARS_CA[whichDC];
- fillp++;
- lasti = i+1;
- }
- }
- if (pass != 0) break;
- // between passes, build the result array
- res = new Object[fillp];
- if (fillp <= 1 && lasti == 0) {
- if (fillp != 0) res[0] = toSourceName(s);
- break;
- }
- }
- return res;
- }
-
- /**
- * Given a series of components, create a bytecode name for a classfile.
- * This is the inverse of {@link #parseBytecodeName(java.lang.String)}.
- * Each component must either be an interned one-character string of
- * a dangerous character, or else a safe bytecode name.
- * @param components a series of name components
- * @return the concatenation of all components
- * @throws IllegalArgumentException if any component contains an unsafe
- * character, and is not an interned one-character string
- * @throws NullPointerException if any component is null
- */
- public static String unparseBytecodeName(Object[] components) {
- Object[] components0 = components;
- for (int i = 0; i < components.length; i++) {
- Object c = components[i];
- if (c instanceof String) {
- String mc = toBytecodeName((String) c);
- if (i == 0 && components.length == 1)
- return mc; // usual case
- if ((Object)mc != c) {
- if (components == components0)
- components = components.clone();
- components[i] = c = mc;
- }
- }
- }
- return appendAll(components);
- }
- private static String appendAll(Object[] components) {
- if (components.length <= 1) {
- if (components.length == 1) {
- return String.valueOf(components[0]);
- }
- return "";
- }
- int slen = 0;
- for (Object c : components) {
- if (c instanceof String)
- slen += String.valueOf(c).length();
- else
- slen += 1;
- }
- StringBuilder sb = new StringBuilder(slen);
- for (Object c : components) {
- sb.append(c);
- }
- return sb.toString();
- }
-
- /**
- * Given a bytecode name, produce the corresponding display name.
- * This is the source name, plus quotes if needed.
- * If the bytecode name contains dangerous characters,
- * assume that they are being used as punctuation,
- * and pass them through unchanged.
- * Non-empty runs of non-dangerous characters are demangled
- * if necessary, and the resulting names are quoted if
- * they are not already valid Java identifiers, or if
- * they contain a dangerous character (i.e., dollar sign "$").
- * Single quotes are used when quoting.
- * Within quoted names, embedded single quotes and backslashes
- * are further escaped by prepended backslashes.
- *
- * @param s the original bytecode name (which may be qualified)
- * @return a human-readable presentation
- */
- public static String toDisplayName(String s) {
- Object[] components = parseBytecodeName(s);
- for (int i = 0; i < components.length; i++) {
- if (!(components[i] instanceof String))
- continue;
- String sn = (String) components[i];
- // note that the name is already demangled!
- //sn = toSourceName(sn);
- if (!isJavaIdent(sn) || sn.indexOf('$') >=0 ) {
- components[i] = quoteDisplay(sn);
- }
- }
- return appendAll(components);
- }
- private static boolean isJavaIdent(String s) {
- int slen = s.length();
- if (slen == 0) return false;
- if (!Character.isJavaIdentifierStart(s.charAt(0)))
- return false;
- for (int i = 1; i < slen; i++) {
- if (!Character.isJavaIdentifierPart(s.charAt(i)))
- return false;
- }
- return true;
- }
- private static String quoteDisplay(String s) {
- // TO DO: Replace wierd characters in s by C-style escapes.
- return "'"+s.replaceAll("['\\\\]", "\\\\$0")+"'";
- }
-
- private static void checkSafeBytecodeName(String s)
- throws IllegalArgumentException {
- if (!isSafeBytecodeName(s)) {
- throw new IllegalArgumentException(s);
- }
- }
-
- /**
- * Report whether a simple name is safe as a bytecode name.
- * Such names are acceptable in class files as class, method, and field names.
- * Additionally, they are free of "dangerous" characters, even if those
- * characters are legal in some (or all) names in class files.
- * @param s the proposed bytecode name
- * @return true if the name is non-empty and all of its characters are safe
- */
- public static boolean isSafeBytecodeName(String s) {
- if (s.length() == 0) return false;
- // check occurrences of each DANGEROUS char
- for (char xc : DANGEROUS_CHARS_A) {
- if (xc == ESCAPE_C) continue; // not really that dangerous
- if (s.indexOf(xc) >= 0) return false;
- }
- return true;
- }
-
- /**
- * Report whether a character is safe in a bytecode name.
- * This is true of any unicode character except the following
- * <em>dangerous characters</em>: {@code ".;:$[]<>/"}.
- * @param s the proposed character
- * @return true if the character is safe to use in classfiles
- */
- public static boolean isSafeBytecodeChar(char c) {
- return DANGEROUS_CHARS.indexOf(c) < DANGEROUS_CHAR_FIRST_INDEX;
- }
-
- private static boolean looksMangled(String s) {
- return s.charAt(0) == ESCAPE_C;
- }
-
- private static String mangle(String s) {
- if (s.length() == 0)
- return NULL_ESCAPE;
-
- // build this lazily, when we first need an escape:
- StringBuilder sb = null;
-
- for (int i = 0, slen = s.length(); i < slen; i++) {
- char c = s.charAt(i);
-
- boolean needEscape = false;
- if (c == ESCAPE_C) {
- if (i+1 < slen) {
- char c1 = s.charAt(i+1);
- if ((i == 0 && c1 == NULL_ESCAPE_C)
- || c1 != originalOfReplacement(c1)) {
- // an accidental escape
- needEscape = true;
- }
- }
- } else {
- needEscape = isDangerous(c);
- }
-
- if (!needEscape) {
- if (sb != null) sb.append(c);
- continue;
- }
-
- // build sb if this is the first escape
- if (sb == null) {
- sb = new StringBuilder(s.length()+10);
- // mangled names must begin with a backslash:
- if (s.charAt(0) != ESCAPE_C && i > 0)
- sb.append(NULL_ESCAPE);
- // append the string so far, which is unremarkable:
- sb.append(s.substring(0, i));
- }
-
- // rewrite \ to \-, / to \|, etc.
- sb.append(ESCAPE_C);
- sb.append(replacementOf(c));
- }
-
- if (sb != null) return sb.toString();
-
- return s;
- }
-
- private static String demangle(String s) {
- // build this lazily, when we first meet an escape:
- StringBuilder sb = null;
-
- int stringStart = 0;
- if (s.startsWith(NULL_ESCAPE))
- stringStart = 2;
-
- for (int i = stringStart, slen = s.length(); i < slen; i++) {
- char c = s.charAt(i);
-
- if (c == ESCAPE_C && i+1 < slen) {
- // might be an escape sequence
- char rc = s.charAt(i+1);
- char oc = originalOfReplacement(rc);
- if (oc != rc) {
- // build sb if this is the first escape
- if (sb == null) {
- sb = new StringBuilder(s.length());
- // append the string so far, which is unremarkable:
- sb.append(s.substring(stringStart, i));
- }
- ++i; // skip both characters
- c = oc;
- }
- }
-
- if (sb != null)
- sb.append(c);
- }
-
- if (sb != null) return sb.toString();
-
- return s.substring(stringStart);
- }
-
- static char ESCAPE_C = '\\';
- // empty escape sequence to avoid a null name or illegal prefix
- static char NULL_ESCAPE_C = '=';
- static String NULL_ESCAPE = ESCAPE_C+""+NULL_ESCAPE_C;
-
- static final String DANGEROUS_CHARS = "\\/.;:$[]<>"; // \\ must be first
- static final String REPLACEMENT_CHARS = "-|,?!%{}^_";
- static final int DANGEROUS_CHAR_FIRST_INDEX = 1; // index after \\
- static char[] DANGEROUS_CHARS_A = DANGEROUS_CHARS.toCharArray();
- static char[] REPLACEMENT_CHARS_A = REPLACEMENT_CHARS.toCharArray();
- static final Character[] DANGEROUS_CHARS_CA;
- static {
- Character[] dcca = new Character[DANGEROUS_CHARS.length()];
- for (int i = 0; i < dcca.length; i++)
- dcca[i] = Character.valueOf(DANGEROUS_CHARS.charAt(i));
- DANGEROUS_CHARS_CA = dcca;
- }
-
- static final long[] SPECIAL_BITMAP = new long[2]; // 128 bits
- static {
- String SPECIAL = DANGEROUS_CHARS + REPLACEMENT_CHARS;
- //System.out.println("SPECIAL = "+SPECIAL);
- for (char c : SPECIAL.toCharArray()) {
- SPECIAL_BITMAP[c >>> 6] |= 1L << c;
- }
- }
- static boolean isSpecial(char c) {
- if ((c >>> 6) < SPECIAL_BITMAP.length)
- return ((SPECIAL_BITMAP[c >>> 6] >> c) & 1) != 0;
- else
- return false;
- }
- static char replacementOf(char c) {
- if (!isSpecial(c)) return c;
- int i = DANGEROUS_CHARS.indexOf(c);
- if (i < 0) return c;
- return REPLACEMENT_CHARS.charAt(i);
- }
- static char originalOfReplacement(char c) {
- if (!isSpecial(c)) return c;
- int i = REPLACEMENT_CHARS.indexOf(c);
- if (i < 0) return c;
- return DANGEROUS_CHARS.charAt(i);
- }
- static boolean isDangerous(char c) {
- if (!isSpecial(c)) return false;
- return (DANGEROUS_CHARS.indexOf(c) >= DANGEROUS_CHAR_FIRST_INDEX);
- }
- static int indexOfDangerousChar(String s, int from) {
- for (int i = from, slen = s.length(); i < slen; i++) {
- if (isDangerous(s.charAt(i)))
- return i;
- }
- return -1;
- }
- static int lastIndexOfDangerousChar(String s, int from) {
- for (int i = Math.min(from, s.length()-1); i >= 0; i--) {
- if (isDangerous(s.charAt(i)))
- return i;
- }
- return -1;
- }
-
-
-}
--- a/jdk/src/share/classes/sun/dyn/util/ValueConversions.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,817 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-import java.dyn.MethodHandle;
-import java.dyn.MethodHandles;
-import java.dyn.MethodHandles.Lookup;
-import java.dyn.MethodType;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.EnumMap;
-import java.util.List;
-
-public class ValueConversions {
- private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
-
- private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
- @SuppressWarnings("unchecked")
- EnumMap<Wrapper, MethodHandle>[] caches
- = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap[n]; // unchecked warning expected here
- for (int i = 0; i < n; i++)
- caches[i] = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
- return caches;
- }
-
- /// Converting references to values.
-
- static int unboxInteger(Object x) {
- if (x == null) return 0; // never NPE
- return ((Integer) x).intValue();
- }
-
- static byte unboxByte(Object x) {
- if (x == null) return 0; // never NPE
- return ((Byte) x).byteValue();
- }
-
- static short unboxShort(Object x) {
- if (x == null) return 0; // never NPE
- return ((Short) x).shortValue();
- }
-
- static boolean unboxBoolean(Object x) {
- if (x == null) return false; // never NPE
- return ((Boolean) x).booleanValue();
- }
-
- static char unboxCharacter(Object x) {
- if (x == null) return 0; // never NPE
- return ((Character) x).charValue();
- }
-
- static long unboxLong(Object x) {
- if (x == null) return 0; // never NPE
- return ((Long) x).longValue();
- }
-
- static float unboxFloat(Object x) {
- if (x == null) return 0; // never NPE
- return ((Float) x).floatValue();
- }
-
- static double unboxDouble(Object x) {
- if (x == null) return 0; // never NPE
- return ((Double) x).doubleValue();
- }
-
- /// Converting references to "raw" values.
- /// A raw primitive value is always an int or long.
-
- static int unboxByteRaw(Object x) {
- return unboxByte(x);
- }
-
- static int unboxShortRaw(Object x) {
- return unboxShort(x);
- }
-
- static int unboxBooleanRaw(Object x) {
- return unboxBoolean(x) ? 1 : 0;
- }
-
- static int unboxCharacterRaw(Object x) {
- return unboxCharacter(x);
- }
-
- static int unboxFloatRaw(Object x) {
- return Float.floatToIntBits(unboxFloat(x));
- }
-
- static long unboxDoubleRaw(Object x) {
- return Double.doubleToRawLongBits(unboxDouble(x));
- }
-
- private static MethodType unboxType(Wrapper wrap, boolean raw) {
- return MethodType.methodType(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType());
- }
-
- private static final EnumMap<Wrapper, MethodHandle>[]
- UNBOX_CONVERSIONS = newWrapperCaches(4);
-
- private static MethodHandle unbox(Wrapper wrap, boolean exact, boolean raw) {
- EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
- MethodHandle mh = cache.get(wrap);
- if (mh != null) {
- return mh;
- }
- // slow path
- switch (wrap) {
- case OBJECT:
- mh = IDENTITY; break;
- case VOID:
- mh = raw ? ALWAYS_ZERO : IGNORE; break;
- case INT: case LONG:
- // these guys don't need separate raw channels
- if (raw) mh = unbox(wrap, exact, false);
- break;
- }
- if (mh != null) {
- cache.put(wrap, mh);
- return mh;
- }
- // look up the method
- String name = "unbox" + wrap.simpleName() + (raw ? "Raw" : "");
- MethodType type = unboxType(wrap, raw);
- if (!exact) {
- try {
- // actually, type is wrong; the Java method takes Object
- mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase());
- } catch (ReflectiveOperationException ex) {
- mh = null;
- }
- } else {
- mh = unbox(wrap, !exact, raw).asType(type);
- }
- if (mh != null) {
- cache.put(wrap, mh);
- return mh;
- }
- throw new IllegalArgumentException("cannot find unbox adapter for " + wrap + (raw ? " (raw)" : ""));
- }
-
- public static MethodHandle unbox(Wrapper type, boolean exact) {
- return unbox(type, exact, false);
- }
-
- public static MethodHandle unboxRaw(Wrapper type, boolean exact) {
- return unbox(type, exact, true);
- }
-
- public static MethodHandle unbox(Class<?> type, boolean exact) {
- return unbox(Wrapper.forPrimitiveType(type), exact, false);
- }
-
- public static MethodHandle unboxRaw(Class<?> type, boolean exact) {
- return unbox(Wrapper.forPrimitiveType(type), exact, true);
- }
-
- /// Converting primitives to references
-
- static Integer boxInteger(int x) {
- return x;
- }
-
- static Byte boxByte(byte x) {
- return x;
- }
-
- static Short boxShort(short x) {
- return x;
- }
-
- static Boolean boxBoolean(boolean x) {
- return x;
- }
-
- static Character boxCharacter(char x) {
- return x;
- }
-
- static Long boxLong(long x) {
- return x;
- }
-
- static Float boxFloat(float x) {
- return x;
- }
-
- static Double boxDouble(double x) {
- return x;
- }
-
- /// Converting raw primitives to references
-
- static Byte boxByteRaw(int x) {
- return boxByte((byte)x);
- }
-
- static Short boxShortRaw(int x) {
- return boxShort((short)x);
- }
-
- static Boolean boxBooleanRaw(int x) {
- return boxBoolean(x != 0);
- }
-
- static Character boxCharacterRaw(int x) {
- return boxCharacter((char)x);
- }
-
- static Float boxFloatRaw(int x) {
- return boxFloat(Float.intBitsToFloat(x));
- }
-
- static Double boxDoubleRaw(long x) {
- return boxDouble(Double.longBitsToDouble(x));
- }
-
- // a raw void value is (arbitrarily) a garbage int
- static Void boxVoidRaw(int x) {
- return null;
- }
-
- private static MethodType boxType(Wrapper wrap, boolean raw) {
- // be exact, since return casts are hard to compose
- Class<?> boxType = wrap.wrapperType();
- return MethodType.methodType(boxType, rawWrapper(wrap, raw).primitiveType());
- }
-
- private static Wrapper rawWrapper(Wrapper wrap, boolean raw) {
- if (raw) return wrap.isDoubleWord() ? Wrapper.LONG : Wrapper.INT;
- return wrap;
- }
-
- private static final EnumMap<Wrapper, MethodHandle>[]
- BOX_CONVERSIONS = newWrapperCaches(4);
-
- private static MethodHandle box(Wrapper wrap, boolean exact, boolean raw) {
- EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
- MethodHandle mh = cache.get(wrap);
- if (mh != null) {
- return mh;
- }
- // slow path
- switch (wrap) {
- case OBJECT:
- mh = IDENTITY; break;
- case VOID:
- if (!raw) mh = ZERO_OBJECT;
- break;
- case INT: case LONG:
- // these guys don't need separate raw channels
- if (raw) mh = box(wrap, exact, false);
- break;
- }
- if (mh != null) {
- cache.put(wrap, mh);
- return mh;
- }
- // look up the method
- String name = "box" + wrap.simpleName() + (raw ? "Raw" : "");
- MethodType type = boxType(wrap, raw);
- if (exact) {
- try {
- mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
- } catch (ReflectiveOperationException ex) {
- mh = null;
- }
- } else {
- mh = box(wrap, !exact, raw).asType(type.erase());
- }
- if (mh != null) {
- cache.put(wrap, mh);
- return mh;
- }
- throw new IllegalArgumentException("cannot find box adapter for " + wrap + (raw ? " (raw)" : ""));
- }
-
- public static MethodHandle box(Class<?> type, boolean exact) {
- return box(Wrapper.forPrimitiveType(type), exact, false);
- }
-
- public static MethodHandle boxRaw(Class<?> type, boolean exact) {
- return box(Wrapper.forPrimitiveType(type), exact, true);
- }
-
- public static MethodHandle box(Wrapper type, boolean exact) {
- return box(type, exact, false);
- }
-
- public static MethodHandle boxRaw(Wrapper type, boolean exact) {
- return box(type, exact, true);
- }
-
- /// Kludges for when raw values get accidentally boxed.
-
- static int unboxRawInteger(Object x) {
- if (x instanceof Integer)
- return unboxInteger(x);
- else
- return (int) unboxLong(x);
- }
-
- static Integer reboxRawInteger(Object x) {
- if (x instanceof Integer)
- return (Integer) x;
- else
- return (int) unboxLong(x);
- }
-
- static Byte reboxRawByte(Object x) {
- if (x instanceof Byte) return (Byte) x;
- return boxByteRaw(unboxRawInteger(x));
- }
-
- static Short reboxRawShort(Object x) {
- if (x instanceof Short) return (Short) x;
- return boxShortRaw(unboxRawInteger(x));
- }
-
- static Boolean reboxRawBoolean(Object x) {
- if (x instanceof Boolean) return (Boolean) x;
- return boxBooleanRaw(unboxRawInteger(x));
- }
-
- static Character reboxRawCharacter(Object x) {
- if (x instanceof Character) return (Character) x;
- return boxCharacterRaw(unboxRawInteger(x));
- }
-
- static Float reboxRawFloat(Object x) {
- if (x instanceof Float) return (Float) x;
- return boxFloatRaw(unboxRawInteger(x));
- }
-
- static Long reboxRawLong(Object x) {
- return (Long) x; //never a rebox
- }
-
- static Double reboxRawDouble(Object x) {
- if (x instanceof Double) return (Double) x;
- return boxDoubleRaw(unboxLong(x));
- }
-
- private static MethodType reboxType(Wrapper wrap) {
- Class<?> boxType = wrap.wrapperType();
- return MethodType.methodType(boxType, Object.class);
- }
-
- private static final EnumMap<Wrapper, MethodHandle>[]
- REBOX_CONVERSIONS = newWrapperCaches(2);
-
- /**
- * Because we normalize primitive types to reduce the number of signatures,
- * primitives are sometimes manipulated under an "erased" type,
- * either int (for types other than long/double) or long (for all types).
- * When the erased primitive value is then boxed into an Integer or Long,
- * the final boxed primitive is sometimes required. This transformation
- * is called a "rebox". It takes an Integer or Long and produces some
- * other boxed value.
- */
- public static MethodHandle rebox(Wrapper wrap, boolean exact) {
- EnumMap<Wrapper, MethodHandle> cache = REBOX_CONVERSIONS[exact?1:0];
- MethodHandle mh = cache.get(wrap);
- if (mh != null) {
- return mh;
- }
- // slow path
- switch (wrap) {
- case OBJECT:
- mh = IDENTITY; break;
- case VOID:
- throw new IllegalArgumentException("cannot rebox a void");
- }
- if (mh != null) {
- cache.put(wrap, mh);
- return mh;
- }
- // look up the method
- String name = "reboxRaw" + wrap.simpleName();
- MethodType type = reboxType(wrap);
- if (exact) {
- try {
- mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
- } catch (ReflectiveOperationException ex) {
- mh = null;
- }
- } else {
- mh = rebox(wrap, !exact).asType(IDENTITY.type());
- }
- if (mh != null) {
- cache.put(wrap, mh);
- return mh;
- }
- throw new IllegalArgumentException("cannot find rebox adapter for " + wrap);
- }
-
- public static MethodHandle rebox(Class<?> type, boolean exact) {
- return rebox(Wrapper.forPrimitiveType(type), exact);
- }
-
- /// Width-changing conversions between int and long.
-
- static long widenInt(int x) {
- return (long) x;
- }
-
- static Long widenBoxedInt(Integer x) {
- return (long)(int)x;
- }
-
- static int narrowLong(long x) {
- return (int) x;
- }
-
- static Integer narrowBoxedLong(Long x) {
- return (int)(long) x;
- }
-
- /// Constant functions
-
- static void ignore(Object x) {
- // no value to return; this is an unbox of null
- return;
- }
-
- static void empty() {
- return;
- }
-
- static Object zeroObject() {
- return null;
- }
-
- static int zeroInteger() {
- return 0;
- }
-
- static long zeroLong() {
- return 0;
- }
-
- static float zeroFloat() {
- return 0;
- }
-
- static double zeroDouble() {
- return 0;
- }
-
- private static final EnumMap<Wrapper, MethodHandle>[]
- CONSTANT_FUNCTIONS = newWrapperCaches(2);
-
- public static MethodHandle zeroConstantFunction(Wrapper wrap) {
- EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
- MethodHandle mh = cache.get(wrap);
- if (mh != null) {
- return mh;
- }
- // slow path
- MethodType type = MethodType.methodType(wrap.primitiveType());
- switch (wrap) {
- case VOID:
- mh = EMPTY;
- break;
- case INT: case LONG: case FLOAT: case DOUBLE:
- try {
- mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "zero"+wrap.simpleName(), type);
- } catch (ReflectiveOperationException ex) {
- mh = null;
- }
- break;
- }
- if (mh != null) {
- cache.put(wrap, mh);
- return mh;
- }
-
- // use the raw method
- Wrapper rawWrap = wrap.rawPrimitive();
- if (mh == null && rawWrap != wrap) {
- mh = MethodHandles.explicitCastArguments(zeroConstantFunction(rawWrap), type);
- }
- if (mh != null) {
- cache.put(wrap, mh);
- return mh;
- }
- throw new IllegalArgumentException("cannot find zero constant for " + wrap);
- }
-
- /// Converting references to references.
-
- /**
- * Value-killing function.
- * @param x an arbitrary reference value
- * @return a null
- */
- static Object alwaysNull(Object x) {
- return null;
- }
-
- /**
- * Value-killing function.
- * @param x an arbitrary reference value
- * @return a zero
- */
- static int alwaysZero(Object x) {
- return 0;
- }
-
- /**
- * Identity function.
- * @param x an arbitrary reference value
- * @return the same value x
- */
- static <T> T identity(T x) {
- return x;
- }
-
- /**
- * Identity function on ints.
- * @param x an arbitrary int value
- * @return the same value x
- */
- static int identity(int x) {
- return x;
- }
-
- static byte identity(byte x) {
- return x;
- }
-
- static short identity(short x) {
- return x;
- }
-
- static boolean identity(boolean x) {
- return x;
- }
-
- static char identity(char x) {
- return x;
- }
-
- /**
- * Identity function on longs.
- * @param x an arbitrary long value
- * @return the same value x
- */
- static long identity(long x) {
- return x;
- }
-
- static float identity(float x) {
- return x;
- }
-
- static double identity(double x) {
- return x;
- }
-
- /**
- * Identity function, with reference cast.
- * @param t an arbitrary reference type
- * @param x an arbitrary reference value
- * @return the same value x
- */
- static <T,U> T castReference(Class<? extends T> t, U x) {
- return t.cast(x);
- }
-
- private static final MethodHandle IDENTITY, IDENTITY_I, IDENTITY_J, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY;
- static {
- try {
- MethodType idType = MethodType.genericMethodType(1);
- MethodType castType = idType.insertParameterTypes(0, Class.class);
- MethodType alwaysZeroType = idType.changeReturnType(int.class);
- MethodType ignoreType = idType.changeReturnType(void.class);
- MethodType zeroObjectType = MethodType.genericMethodType(0);
- IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType);
- IDENTITY_I = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(int.class, int.class));
- IDENTITY_J = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(long.class, long.class));
- //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
- CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType);
- ALWAYS_NULL = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysNull", idType);
- ALWAYS_ZERO = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysZero", alwaysZeroType);
- ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType);
- IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType);
- EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterTypes(0, 1));
- } catch (Exception ex) {
- Error err = new InternalError("uncaught exception");
- err.initCause(ex);
- throw err;
- }
- }
-
- private static final EnumMap<Wrapper, MethodHandle> WRAPPER_CASTS
- = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
-
- private static final EnumMap<Wrapper, MethodHandle> EXACT_WRAPPER_CASTS
- = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
-
- /** Return a method that casts its sole argument (an Object) to the given type
- * and returns it as the given type (if exact is true), or as plain Object (if erase is true).
- */
- public static MethodHandle cast(Class<?> type, boolean exact) {
- if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type);
- MethodHandle mh = null;
- Wrapper wrap = null;
- EnumMap<Wrapper, MethodHandle> cache = null;
- if (Wrapper.isWrapperType(type)) {
- wrap = Wrapper.forWrapperType(type);
- cache = (exact ? EXACT_WRAPPER_CASTS : WRAPPER_CASTS);
- mh = cache.get(wrap);
- if (mh != null) return mh;
- }
- if (VerifyType.isNullReferenceConversion(Object.class, type))
- mh = IDENTITY;
- else if (VerifyType.isNullType(type))
- mh = ALWAYS_NULL;
- else
- mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
- if (exact) {
- MethodType xmt = MethodType.methodType(type, Object.class);
- mh = MethodHandles.explicitCastArguments(mh, xmt);
- //mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh);
- }
- if (cache != null)
- cache.put(wrap, mh);
- return mh;
- }
-
- public static MethodHandle identity() {
- return IDENTITY;
- }
-
- public static MethodHandle identity(Class<?> type) {
- // This stuff has been moved into MethodHandles:
- return MethodHandles.identity(type);
- }
-
- public static MethodHandle identity(Wrapper wrap) {
- EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
- MethodHandle mh = cache.get(wrap);
- if (mh != null) {
- return mh;
- }
- // slow path
- MethodType type = MethodType.methodType(wrap.primitiveType());
- if (wrap != Wrapper.VOID)
- type = type.appendParameterTypes(wrap.primitiveType());
- try {
- mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", type);
- } catch (ReflectiveOperationException ex) {
- mh = null;
- }
- if (mh == null && wrap == Wrapper.VOID) {
- mh = EMPTY; // #(){} : #()void
- }
- if (mh != null) {
- cache.put(wrap, mh);
- return mh;
- }
-
- if (mh != null) {
- cache.put(wrap, mh);
- return mh;
- }
- throw new IllegalArgumentException("cannot find identity for " + wrap);
- }
-
- private static final Object[] NO_ARGS_ARRAY = {};
- private static Object[] makeArray(Object... args) { return args; }
- private static Object[] array() { return NO_ARGS_ARRAY; }
- private static Object[] array(Object a0)
- { return makeArray(a0); }
- private static Object[] array(Object a0, Object a1)
- { return makeArray(a0, a1); }
- private static Object[] array(Object a0, Object a1, Object a2)
- { return makeArray(a0, a1, a2); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3)
- { return makeArray(a0, a1, a2, a3); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4)
- { return makeArray(a0, a1, a2, a3, a4); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5)
- { return makeArray(a0, a1, a2, a3, a4, a5); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- static MethodHandle[] makeArrays() {
- ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
- MethodHandles.Lookup lookup = IMPL_LOOKUP;
- for (;;) {
- int nargs = arrays.size();
- MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class);
- String name = "array";
- MethodHandle array = null;
- try {
- array = lookup.findStatic(ValueConversions.class, name, type);
- } catch (ReflectiveOperationException ex) {
- }
- if (array == null) break;
- arrays.add(array);
- }
- assert(arrays.size() == 11); // current number of methods
- return arrays.toArray(new MethodHandle[0]);
- }
- static final MethodHandle[] ARRAYS = makeArrays();
-
- /** Return a method handle that takes the indicated number of Object
- * arguments and returns an Object array of them, as if for varargs.
- */
- public static MethodHandle varargsArray(int nargs) {
- if (nargs < ARRAYS.length)
- return ARRAYS[nargs];
- // else need to spin bytecode or do something else fancy
- throw new UnsupportedOperationException("NYI: cannot form a varargs array of length "+nargs);
- }
-
- private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
- private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
- private static List<Object> list() { return NO_ARGS_LIST; }
- private static List<Object> list(Object a0)
- { return makeList(a0); }
- private static List<Object> list(Object a0, Object a1)
- { return makeList(a0, a1); }
- private static List<Object> list(Object a0, Object a1, Object a2)
- { return makeList(a0, a1, a2); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
- { return makeList(a0, a1, a2, a3); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4)
- { return makeList(a0, a1, a2, a3, a4); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5)
- { return makeList(a0, a1, a2, a3, a4, a5); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6)
- { return makeList(a0, a1, a2, a3, a4, a5, a6); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7)
- { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8)
- { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9)
- { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- static MethodHandle[] makeLists() {
- ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
- MethodHandles.Lookup lookup = IMPL_LOOKUP;
- for (;;) {
- int nargs = arrays.size();
- MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
- String name = "list";
- MethodHandle array = null;
- try {
- array = lookup.findStatic(ValueConversions.class, name, type);
- } catch (ReflectiveOperationException ex) {
- }
- if (array == null) break;
- arrays.add(array);
- }
- assert(arrays.size() == 11); // current number of methods
- return arrays.toArray(new MethodHandle[0]);
- }
- static final MethodHandle[] LISTS = makeLists();
-
- /** Return a method handle that takes the indicated number of Object
- * arguments and returns List.
- */
- public static MethodHandle varargsList(int nargs) {
- if (nargs < LISTS.length)
- return LISTS[nargs];
- // else need to spin bytecode or do something else fancy
- throw new UnsupportedOperationException("NYI");
- }
-}
-
--- a/jdk/src/share/classes/sun/dyn/util/VerifyAccess.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-import java.lang.reflect.Modifier;
-import static java.lang.reflect.Modifier.*;
-
-/**
- * This class centralizes information about the JVM's linkage access control.
- * @author jrose
- */
-public class VerifyAccess {
-
- private VerifyAccess() { } // cannot instantiate
-
- private static final int PACKAGE_ONLY = 0;
- private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
- private static final boolean ALLOW_NESTMATE_ACCESS = false;
-
- /**
- * Evaluate the JVM linkage rules for access to the given method
- * on behalf of a caller class which proposes to perform the access.
- * Return true if the caller class has privileges to invoke a method
- * or access a field with the given properties.
- * This requires an accessibility check of the referencing class,
- * plus an accessibility check of the member within the class,
- * which depends on the member's modifier flags.
- * <p>
- * The relevant properties include the defining class ({@code defc})
- * of the member, and its modifier flags ({@code mods}).
- * Also relevant is the class used to make the initial symbolic reference
- * to the member ({@code refc}). If this latter class is not distinguished,
- * the defining class should be passed for both arguments ({@code defc == refc}).
- * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
- * A field or method R is accessible to a class or interface D if
- * and only if any of the following conditions is true:<ul>
- * <li>R is public.
- * <li>R is protected and is declared in a class C, and D is either
- * a subclass of C or C itself. Furthermore, if R is not
- * static, then the symbolic reference to R must contain a
- * symbolic reference to a class T, such that T is either a
- * subclass of D, a superclass of D or D itself.
- * <li>R is either protected or has default access (that is,
- * neither public nor protected nor private), and is declared
- * by a class in the same runtime package as D.
- * <li>R is private and is declared in D.
- * </ul>
- * This discussion of access control omits a related restriction
- * on the target of a protected field access or method invocation
- * (the target must be of class D or a subtype of D). That
- * requirement is checked as part of the verification process
- * (5.4.1); it is not part of link-time access control.
- * @param refc the class used in the symbolic reference to the proposed member
- * @param defc the class in which the proposed member is actually defined
- * @param mods modifier flags for the proposed member
- * @param lookupClass the class for which the access check is being made
- * @return true iff the the accessing class can access such a member
- */
- public static boolean isMemberAccessible(Class<?> refc, // symbolic ref class
- Class<?> defc, // actual def class
- int mods, // actual member mods
- Class<?> lookupClass) {
- // Usually refc and defc are the same, but if they differ, verify them both.
- if (refc != defc) {
- if (!isClassAccessible(refc, lookupClass)) {
- // Note that defc is verified in the switch below.
- return false;
- }
- if ((mods & (ALL_ACCESS_MODES|STATIC)) == (PROTECTED|STATIC)) {
- // Apply the special rules for refc here.
- if (!isRelatedClass(refc, lookupClass))
- return isSamePackage(defc, lookupClass);
- // If refc == defc, the call to isPublicSuperClass will do
- // the whole job, since in that case refc (as defc) will be
- // a superclass of the lookup class.
- }
- }
- if (defc == lookupClass)
- return true; // easy check; all self-access is OK
- switch (mods & ALL_ACCESS_MODES) {
- case PUBLIC:
- if (refc != defc) return true; // already checked above
- return isClassAccessible(refc, lookupClass);
- case PROTECTED:
- return isSamePackage(defc, lookupClass) || isPublicSuperClass(defc, lookupClass);
- case PACKAGE_ONLY:
- return isSamePackage(defc, lookupClass);
- case PRIVATE:
- // Loosened rules for privates follows access rules for inner classes.
- return (ALLOW_NESTMATE_ACCESS &&
- isSamePackageMember(defc, lookupClass));
- default:
- throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
- }
- }
-
- static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
- return (refc == lookupClass ||
- refc.isAssignableFrom(lookupClass) ||
- lookupClass.isAssignableFrom(refc));
- }
-
- static boolean isPublicSuperClass(Class<?> defc, Class<?> lookupClass) {
- return isPublic(defc.getModifiers()) && defc.isAssignableFrom(lookupClass);
- }
-
- /**
- * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
- * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
- * A class or interface C is accessible to a class or interface D
- * if and only if either of the following conditions are true:<ul>
- * <li>C is public.
- * <li>C and D are members of the same runtime package.
- * </ul>
- * @param refc the symbolic reference class to which access is being checked (C)
- * @param lookupClass the class performing the lookup (D)
- */
- public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass) {
- int mods = refc.getModifiers();
- if (isPublic(mods))
- return true;
- if (isSamePackage(lookupClass, refc))
- return true;
- return false;
- }
-
- /**
- * Test if two classes have the same class loader and package qualifier.
- * @param class1
- * @param class2
- * @return whether they are in the same package
- */
- public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
- if (class1 == class2)
- return true;
- if (!loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
- return false;
- String name1 = class1.getName(), name2 = class2.getName();
- int dot = name1.lastIndexOf('.');
- if (dot != name2.lastIndexOf('.'))
- return false;
- for (int i = 0; i < dot; i++) {
- if (name1.charAt(i) != name2.charAt(i))
- return false;
- }
- return true;
- }
-
- /**
- * Test if two classes are defined as part of the same package member (top-level class).
- * If this is true, they can share private access with each other.
- * @param class1
- * @param class2
- * @return whether they are identical or nested together
- */
- public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
- if (class1 == class2)
- return true;
- if (!isSamePackage(class1, class2))
- return false;
- if (getOutermostEnclosingClass(class1) != getOutermostEnclosingClass(class2))
- return false;
- return true;
- }
-
- private static Class<?> getOutermostEnclosingClass(Class<?> c) {
- Class<?> pkgmem = c;
- for (Class<?> enc = c; (enc = enc.getEnclosingClass()) != null; )
- pkgmem = enc;
- return pkgmem;
- }
-
- private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2) {
- if (loader1 == loader2 || loader1 == null || loader2 == null) {
- return true;
- }
- for (ClassLoader scan1 = loader1;
- scan1 != null; scan1 = scan1.getParent()) {
- if (scan1 == loader2) return true;
- }
- for (ClassLoader scan2 = loader2;
- scan2 != null; scan2 = scan2.getParent()) {
- if (scan2 == loader1) return true;
- }
- return false;
- }
-}
--- a/jdk/src/share/classes/sun/dyn/util/VerifyType.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-import java.dyn.MethodType;
-import sun.dyn.empty.Empty;
-
-/**
- * This class centralizes information about the JVM verifier
- * and its requirements about type correctness.
- * @author jrose
- */
-public class VerifyType {
-
- private VerifyType() { } // cannot instantiate
-
- /**
- * True if a value can be stacked as the source type and unstacked as the
- * destination type, without violating the JVM's type consistency.
- *
- * @param call the type of a stacked value
- * @param recv the type by which we'd like to treat it
- * @return whether the retyping can be done without motion or reformatting
- */
- public static boolean isNullConversion(Class<?> src, Class<?> dst) {
- if (src == dst) return true;
- // Verifier allows any interface to be treated as Object:
- if (dst.isInterface()) dst = Object.class;
- if (src.isInterface()) src = Object.class;
- if (src == dst) return true; // check again
- if (dst == void.class) return true; // drop any return value
- if (isNullType(src)) return !dst.isPrimitive();
- if (!src.isPrimitive()) return dst.isAssignableFrom(src);
- // Verifier allows an int to carry byte, short, char, or even boolean:
- if (dst == int.class) return Wrapper.forPrimitiveType(src).isSubwordOrInt();
- return false;
- }
-
- /**
- * Specialization of isNullConversion to reference types.
-
- * @param call the type of a stacked value
- * @param recv the reference type by which we'd like to treat it
- * @return whether the retyping can be done without a cast
- */
- public static boolean isNullReferenceConversion(Class<?> src, Class<?> dst) {
- assert(!dst.isPrimitive());
- if (dst.isInterface()) return true; // verifier allows this
- if (isNullType(src)) return true;
- return dst.isAssignableFrom(src);
- }
-
- /**
- * Is the given type java.lang.Null or an equivalent null-only type?
- */
- public static boolean isNullType(Class<?> type) {
- if (type == null) return false;
- return type == NULL_CLASS
- // This one may also be used as a null type.
- // TO DO: Decide if we really want to legitimize it here.
- // Probably we do, unless java.lang.Null really makes it into Java 7
- //|| type == Void.class
- // Locally known null-only class:
- || type == Empty.class
- ;
- }
- private static final Class<?> NULL_CLASS;
- static {
- Class<?> nullClass = null;
- try {
- nullClass = Class.forName("java.lang.Null");
- } catch (ClassNotFoundException ex) {
- // OK, we'll cope
- }
- NULL_CLASS = nullClass;
- }
-
- /**
- * True if a method handle can receive a call under a slightly different
- * method type, without moving or reformatting any stack elements.
- *
- * @param call the type of call being made
- * @param recv the type of the method handle receiving the call
- * @return whether the retyping can be done without motion or reformatting
- */
- public static boolean isNullConversion(MethodType call, MethodType recv) {
- if (call == recv) return true;
- int len = call.parameterCount();
- if (len != recv.parameterCount()) return false;
- for (int i = 0; i < len; i++)
- if (!isNullConversion(call.parameterType(i), recv.parameterType(i)))
- return false;
- return isNullConversion(recv.returnType(), call.returnType());
- }
-
- //TO DO: isRawConversion
-
- /**
- * Determine if the JVM verifier allows a value of type call to be
- * passed to a formal parameter (or return variable) of type recv.
- * Returns 1 if the verifier allows the types to match without conversion.
- * Returns -1 if the types can be made to match by a JVM-supported adapter.
- * Cases supported are:
- * <ul><li>checkcast
- * </li><li>conversion between any two integral types (but not floats)
- * </li><li>unboxing from a wrapper to its corresponding primitive type
- * </li><li>conversion in either direction between float and double
- * </li></ul>
- * (Autoboxing is not supported here; it must be done via Java code.)
- * Returns 0 otherwise.
- */
- public static int canPassUnchecked(Class<?> src, Class<?> dst) {
- if (src == dst)
- return 1;
-
- if (dst.isPrimitive()) {
- if (dst == void.class)
- // Return anything to a caller expecting void.
- // This is a property of the implementation, which links
- // return values via a register rather than via a stack push.
- // This makes it possible to ignore cleanly.
- return 1;
- if (src == void.class)
- return 0; // void-to-something?
- if (!src.isPrimitive())
- // Cannot pass a reference to any primitive type (exc. void).
- return 0;
- Wrapper sw = Wrapper.forPrimitiveType(src);
- Wrapper dw = Wrapper.forPrimitiveType(dst);
- if (sw.isSubwordOrInt() && dw.isSubwordOrInt()) {
- if (sw.bitWidth() >= dw.bitWidth())
- return -1; // truncation may be required
- if (!dw.isSigned() && sw.isSigned())
- return -1; // sign elimination may be required
- }
- if (src == float.class || dst == float.class) {
- if (src == double.class || dst == double.class)
- return -1; // floating conversion may be required
- else
- return 0; // other primitive conversions NYI
- } else {
- // all fixed-point conversions are supported
- return 0;
- }
- } else if (src.isPrimitive()) {
- // Cannot pass a primitive to any reference type.
- // (Maybe allow null.class?)
- return 0;
- }
-
- // Handle reference types in the rest of the block:
-
- // The verifier treats interfaces exactly like Object.
- if (isNullReferenceConversion(src, dst))
- // pass any reference to object or an arb. interface
- return 1;
- // else it's a definite "maybe" (cast is required)
- return -1;
- }
-
- public static int canPassRaw(Class<?> src, Class<?> dst) {
- if (dst.isPrimitive()) {
- if (dst == void.class)
- // As above, return anything to a caller expecting void.
- return 1;
- if (src == void.class)
- // Special permission for raw conversions: allow a void
- // to be captured as a garbage int.
- // Caller promises that the actual value will be disregarded.
- return dst == int.class ? 1 : 0;
- if (isNullType(src))
- // Special permission for raw conversions: allow a null
- // to be reinterpreted as anything. For objects, it is safe,
- // and for primitives you get a garbage value (probably zero).
- return 1;
- if (!src.isPrimitive())
- return 0;
- Wrapper sw = Wrapper.forPrimitiveType(src);
- Wrapper dw = Wrapper.forPrimitiveType(dst);
- if (sw.stackSlots() == dw.stackSlots())
- return 1; // can do a reinterpret-cast on a stacked primitive
- if (sw.isSubwordOrInt() && dw == Wrapper.VOID)
- return 1; // can drop an outgoing int value
- return 0;
- } else if (src.isPrimitive()) {
- return 0;
- }
-
- // Both references.
- if (isNullReferenceConversion(src, dst))
- return 1;
- return -1;
- }
-
- public static boolean isSpreadArgType(Class<?> spreadArg) {
- return spreadArg.isArray();
- }
- public static Class<?> spreadArgElementType(Class<?> spreadArg, int i) {
- return spreadArg.getComponentType();
- }
-}
--- a/jdk/src/share/classes/sun/dyn/util/Wrapper.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,562 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.dyn.util;
-
-public enum Wrapper {
- BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)),
- // These must be in the order defined for widening primitive conversions in JLS 5.1.2
- BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, Format.signed(8)),
- SHORT(Short.class, short.class, 'S', (Short)(short)0, Format.signed(16)),
- CHAR(Character.class, char.class, 'C', (Character)(char)0, Format.unsigned(16)),
- INT(Integer.class, int.class, 'I', (Integer)(int)0, Format.signed(32)),
- LONG(Long.class, long.class, 'J', (Long)(long)0, Format.signed(64)),
- FLOAT(Float.class, float.class, 'F', (Float)(float)0, Format.floating(32)),
- DOUBLE(Double.class, double.class, 'D', (Double)(double)0, Format.floating(64)),
- //NULL(Null.class, null.class, 'N', null, Format.other(1)),
- OBJECT(Object.class, Object.class, 'L', null, Format.other(1)),
- // VOID must be the last type, since it is "assignable" from any other type:
- VOID(Void.class, void.class, 'V', null, Format.other(0)),
- ;
-
- private final Class<?> wrapperType;
- private final Class<?> primitiveType;
- private final char basicTypeChar;
- private final Object zero;
- private final int format;
- private final String simpleName;
-
- private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, int format) {
- this.wrapperType = wtype;
- this.primitiveType = ptype;
- this.basicTypeChar = tchar;
- this.zero = zero;
- this.format = format;
- this.simpleName = wtype.getSimpleName();
- }
-
- private static abstract class Format {
- static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
- static final int
- SIGNED = (-1) << KIND_SHIFT,
- UNSIGNED = 0 << KIND_SHIFT,
- FLOATING = 1 << KIND_SHIFT;
- static final int
- SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
- SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
- static int format(int kind, int size, int slots) {
- assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
- assert((size & (size-1)) == 0); // power of two
- assert((kind == SIGNED) ? (size > 0) :
- (kind == UNSIGNED) ? (size > 0) :
- (kind == FLOATING) ? (size == 32 || size == 64) :
- false);
- assert((slots == 2) ? (size == 64) :
- (slots == 1) ? (size <= 32) :
- false);
- return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT);
- }
- static final int
- INT = SIGNED | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
- SHORT = SIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
- BOOLEAN = UNSIGNED | (1 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
- CHAR = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
- FLOAT = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
- VOID = UNSIGNED | (0 << SIZE_SHIFT) | (0 << SLOT_SHIFT),
- NUM_MASK = (-1) << SIZE_SHIFT;
- static int signed(int size) { return format(SIGNED, size, (size > 32 ? 2 : 1)); }
- static int unsigned(int size) { return format(UNSIGNED, size, (size > 32 ? 2 : 1)); }
- static int floating(int size) { return format(FLOATING, size, (size > 32 ? 2 : 1)); }
- static int other(int slots) { return slots << SLOT_SHIFT; }
- }
-
- /// format queries:
-
- /** How many bits are in the wrapped value? Returns 0 for OBJECT or VOID. */
- public int bitWidth() { return (format >> Format.SIZE_SHIFT) & Format.SIZE_MASK; }
- /** How many JVM stack slots occupied by the wrapped value? Returns 0 for VOID. */
- public int stackSlots() { return (format >> Format.SLOT_SHIFT) & Format.SLOT_MASK; }
- /** Does the wrapped value occupy a single JVM stack slot? */
- public boolean isSingleWord() { return (format & (1 << Format.SLOT_SHIFT)) != 0; }
- /** Does the wrapped value occupy two JVM stack slots? */
- public boolean isDoubleWord() { return (format & (2 << Format.SLOT_SHIFT)) != 0; }
- /** Is the wrapped type numeric (not void or object)? */
- public boolean isNumeric() { return (format & Format.NUM_MASK) != 0; }
- /** Is the wrapped type a primitive other than float, double, or void? */
- public boolean isIntegral() { return isNumeric() && format < Format.FLOAT; }
- /** Is the wrapped type one of int, boolean, byte, char, or short? */
- public boolean isSubwordOrInt() { return isIntegral() && isSingleWord(); }
- /* Is the wrapped value a signed integral type (one of byte, short, int, or long)? */
- public boolean isSigned() { return format < Format.VOID; }
- /* Is the wrapped value an unsigned integral type (one of boolean or char)? */
- public boolean isUnsigned() { return format >= Format.BOOLEAN && format < Format.FLOAT; }
- /** Is the wrapped type either float or double? */
- public boolean isFloating() { return format >= Format.FLOAT; }
-
- /** Does the JVM verifier allow a variable of this wrapper's
- * primitive type to be assigned from a value of the given wrapper's primitive type?
- * Cases:
- * <ul>
- * <li>unboxing followed by widening primitive conversion
- * <li>any type converted to {@code void}
- * <li>boxing conversion followed by widening reference conversion to {@code Object}
- * <li>conversion of {@code boolean} to any type
- * </ul>
- */
- public boolean isConvertibleFrom(Wrapper source) {
- if (this == source) return true;
- if (this.compareTo(source) < 0) {
- // At best, this is a narrowing conversion.
- return false;
- }
- if ((this.format ^ source.format) == (Format.SHORT ^ Format.CHAR)) {
- assert (this == SHORT && source == CHAR) || (this == CHAR && source == SHORT);
- return false;
- }
- return true;
- }
-
- /** Produce a zero value for the given wrapper type.
- * This will be a numeric zero for a number or character,
- * false for a boolean, and null for a reference or void.
- * The common thread is that this is what is contained
- * in a default-initialized variable of the given primitive
- * type. (For void, it is what a reflective method returns
- * instead of no value at all.)
- */
- public Object zero() { return zero; }
-
- /** Produce a zero value for the given wrapper type T.
- * The optional argument must a type compatible with this wrapper.
- * Equivalent to {@code this.cast(this.zero(), type)}.
- */
- public <T> T zero(Class<T> type) { return convert(zero, type); }
-
-// /** Produce a wrapper for the given wrapper or primitive type. */
-// public static Wrapper valueOf(Class<?> type) {
-// if (isPrimitiveType(type))
-// return forPrimitiveType(type);
-// else
-// return forWrapperType(type);
-// }
-
- /** Return the wrapper that wraps values of the given type.
- * The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
- * Otherwise, the type must be a primitive.
- * @throws IllegalArgumentException for unexpected types
- */
- public static Wrapper forPrimitiveType(Class<?> type) {
- Wrapper w = findPrimitiveType(type);
- if (w != null) return w;
- if (type.isPrimitive())
- throw new InternalError(); // redo hash function
- throw newIllegalArgumentException("not primitive: "+type);
- }
-
- static Wrapper findPrimitiveType(Class<?> type) {
- Wrapper w = FROM_PRIM[hashPrim(type)];
- if (w != null && w.primitiveType == type) {
- return w;
- }
- return null;
- }
-
- /** Return the wrapper that wraps values into the given wrapper type.
- * If it is {@code Object} or an interface, return {@code OBJECT}.
- * Otherwise, it must be a wrapper type.
- * The type must not be a primitive type.
- * @throws IllegalArgumentException for unexpected types
- */
- public static Wrapper forWrapperType(Class<?> type) {
- Wrapper w = findWrapperType(type);
- if (w != null) return w;
- for (Wrapper x : values())
- if (x.wrapperType == type)
- throw new InternalError(); // redo hash function
- throw newIllegalArgumentException("not wrapper: "+type);
- }
-
- static Wrapper findWrapperType(Class<?> type) {
- Wrapper w = FROM_WRAP[hashWrap(type)];
- if (w != null && w.wrapperType == type) {
- return w;
- }
- if (type.isInterface())
- return OBJECT;
- return null;
- }
-
- /** Return the wrapper that corresponds to the given bytecode
- * signature character. Return {@code OBJECT} for the character 'L'.
- * @throws IllegalArgumentException for any non-signature character or {@code '['}.
- */
- public static Wrapper forBasicType(char type) {
- Wrapper w = FROM_CHAR[hashChar(type)];
- if (w != null && w.basicTypeChar == type) {
- return w;
- }
- for (Wrapper x : values())
- if (w.basicTypeChar == type)
- throw new InternalError(); // redo hash function
- throw newIllegalArgumentException("not basic type char: "+type);
- }
-
- /** Return the wrapper for the given type, if it is
- * a primitive type, else return {@code OBJECT}.
- */
- public static Wrapper forBasicType(Class<?> type) {
- if (type.isPrimitive())
- return forPrimitiveType(type);
- return OBJECT; // any reference, including wrappers or arrays
- }
-
- // Note on perfect hashes:
- // for signature chars c, do (c + (c >> 1)) % 16
- // for primitive type names n, do (n[0] + n[2]) % 16
- // The type name hash works for both primitive and wrapper names.
- // You can add "java/lang/Object" to the primitive names.
- // But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16.
- private static final Wrapper[] FROM_PRIM = new Wrapper[16];
- private static final Wrapper[] FROM_WRAP = new Wrapper[16];
- private static final Wrapper[] FROM_CHAR = new Wrapper[16];
- private static int hashPrim(Class<?> x) {
- String xn = x.getName();
- if (xn.length() < 3) return 0;
- return (xn.charAt(0) + xn.charAt(2)) % 16;
- }
- private static int hashWrap(Class<?> x) {
- String xn = x.getName();
- final int offset = 10; assert(offset == "java.lang.".length());
- if (xn.length() < offset+3) return 0;
- return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16;
- }
- private static int hashChar(char x) {
- return (x + (x >> 1)) % 16;
- }
- static {
- for (Wrapper w : values()) {
- int pi = hashPrim(w.primitiveType);
- int wi = hashWrap(w.wrapperType);
- int ci = hashChar(w.basicTypeChar);
- assert(FROM_PRIM[pi] == null);
- assert(FROM_WRAP[wi] == null);
- assert(FROM_CHAR[ci] == null);
- FROM_PRIM[pi] = w;
- FROM_WRAP[wi] = w;
- FROM_CHAR[ci] = w;
- }
- //assert(jdk.sun.dyn.util.WrapperTest.test(false));
- }
-
- /** What is the primitive type wrapped by this wrapper? */
- public Class<?> primitiveType() { return primitiveType; }
-
- /** What is the wrapper type for this wrapper? */
- public Class<?> wrapperType() { return wrapperType; }
-
- /** What is the wrapper type for this wrapper?
- * Otherwise, the example type must be the wrapper type,
- * or the corresponding primitive type.
- * (For {@code OBJECT}, the example type can be any non-primitive,
- * and is normalized to {@code Object.class}.)
- * The resulting class type has the same type parameter.
- */
- public <T> Class<T> wrapperType(Class<T> exampleType) {
- if (exampleType == wrapperType) {
- return exampleType;
- } else if (exampleType == primitiveType ||
- wrapperType == Object.class ||
- exampleType.isInterface()) {
- return forceType(wrapperType, exampleType);
- }
- throw newClassCastException(exampleType, primitiveType);
- }
-
- private static ClassCastException newClassCastException(Class<?> actual, Class<?> expected) {
- return new ClassCastException(actual + " is not compatible with " + expected);
- }
-
- /** If {@code type} is a primitive type, return the corresponding
- * wrapper type, else return {@code type} unchanged.
- */
- public static <T> Class<T> asWrapperType(Class<T> type) {
- if (type.isPrimitive()) {
- return forPrimitiveType(type).wrapperType(type);
- }
- return type;
- }
-
- /** If {@code type} is a wrapper type, return the corresponding
- * primitive type, else return {@code type} unchanged.
- */
- public static <T> Class<T> asPrimitiveType(Class<T> type) {
- Wrapper w = findWrapperType(type);
- if (w != null) {
- return forceType(w.primitiveType(), type);
- }
- return type;
- }
-
- /** Query: Is the given type a wrapper, such as {@code Integer} or {@code Void}? */
- public static boolean isWrapperType(Class<?> type) {
- return findWrapperType(type) != null;
- }
-
- /** Query: Is the given type a primitive, such as {@code int} or {@code void}? */
- public static boolean isPrimitiveType(Class<?> type) {
- return type.isPrimitive();
- }
-
- /** What is the bytecode signature character for this type?
- * All non-primitives, including array types, report as 'L', the signature character for references.
- */
- public static char basicTypeChar(Class<?> type) {
- if (!type.isPrimitive())
- return 'L';
- else
- return forPrimitiveType(type).basicTypeChar();
- }
-
- /** What is the bytecode signature character for this wrapper's
- * primitive type?
- */
- public char basicTypeChar() { return basicTypeChar; }
-
- /** What is the simple name of the wrapper type?
- */
- public String simpleName() { return simpleName; }
-
-// /** Wrap a value in the given type, which may be either a primitive or wrapper type.
-// * Performs standard primitive conversions, including truncation and float conversions.
-// */
-// public static <T> T wrap(Object x, Class<T> type) {
-// return Wrapper.valueOf(type).cast(x, type);
-// }
-
- /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
- * The given target type must be this wrapper's primitive or wrapper type.
- * If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
- * Performs standard primitive conversions, including truncation and float conversions.
- * The given type must be compatible with this wrapper. That is, it must either
- * be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else
- * it must be the wrapper's primitive type.
- * Primitive conversions are only performed if the given type is itself a primitive.
- * @throws ClassCastException if the given type is not compatible with this wrapper
- */
- public <T> T cast(Object x, Class<T> type) {
- return convert(x, type, true);
- }
-
- /** Convert a wrapped value to the given type.
- * The given target type must be this wrapper's primitive or wrapper type.
- * This is equivalent to {@link #cast}, except that it refuses to perform
- * narrowing primitive conversions.
- */
- public <T> T convert(Object x, Class<T> type) {
- return convert(x, type, false);
- }
-
- private <T> T convert(Object x, Class<T> type, boolean isCast) {
- if (this == OBJECT) {
- // If the target wrapper is OBJECT, just do a reference cast.
- // If the target type is an interface, perform no runtime check.
- // (This loophole is safe, and is allowed by the JVM verifier.)
- // If the target type is a primitive, change it to a wrapper.
- @SuppressWarnings("unchecked")
- T result = (T) x; // unchecked warning is expected here
- return result;
- }
- Class<T> wtype = wrapperType(type);
- if (wtype.isInstance(x)) {
- @SuppressWarnings("unchecked")
- T result = (T) x; // unchecked warning is expected here
- return result;
- }
- Class<?> sourceType = x.getClass(); // throw NPE if x is null
- if (!isCast) {
- Wrapper source = findWrapperType(sourceType);
- if (source == null || !this.isConvertibleFrom(source)) {
- throw newClassCastException(wtype, sourceType);
- }
- }
- @SuppressWarnings("unchecked")
- T result = (T) wrap(x); // unchecked warning is expected here
- assert result.getClass() == wtype;
- return result;
- }
-
- /** Cast a reference type to another reference type.
- * If the target type is an interface, perform no runtime check.
- * (This loophole is safe, and is allowed by the JVM verifier.)
- * If the target type is a primitive, change it to a wrapper.
- */
- static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
- boolean z = (type == exampleType ||
- type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
- exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
- type == Object.class && !exampleType.isPrimitive());
- if (!z)
- System.out.println(type+" <= "+exampleType);
- assert(type == exampleType ||
- type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
- exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
- type == Object.class && !exampleType.isPrimitive());
- @SuppressWarnings("unchecked")
- Class<T> result = (Class<T>) type; // unchecked warning is expected here
- return result;
- }
-
- /** Wrap a value in this wrapper's type.
- * Performs standard primitive conversions, including truncation and float conversions.
- * Performs returns the unchanged reference for {@code OBJECT}.
- * Returns null for {@code VOID}.
- * Returns a zero value for a null input.
- * @throws ClassCastException if this wrapper is numeric and the operand
- * is not a number, character, boolean, or null
- */
- public Object wrap(Object x) {
- // do non-numeric wrappers first
- switch (basicTypeChar) {
- case 'L': return x;
- case 'V': return null;
- }
- Number xn = numberValue(x);
- switch (basicTypeChar) {
- case 'I': return Integer.valueOf(xn.intValue());
- case 'J': return Long.valueOf(xn.longValue());
- case 'F': return Float.valueOf(xn.floatValue());
- case 'D': return Double.valueOf(xn.doubleValue());
- case 'S': return Short.valueOf((short) xn.intValue());
- case 'B': return Byte.valueOf((byte) xn.intValue());
- case 'C': return Character.valueOf((char) xn.intValue());
- case 'Z': return Boolean.valueOf(boolValue(xn.longValue()));
- }
- throw new InternalError("bad wrapper");
- }
-
- /** Wrap a value (an int or smaller value) in this wrapper's type.
- * Performs standard primitive conversions, including truncation and float conversions.
- * Produces an {@code Integer} for {@code OBJECT}, although the exact type
- * of the operand is not known.
- * Returns null for {@code VOID}.
- */
- public Object wrap(int x) {
- if (basicTypeChar == 'L') return (Integer)x;
- switch (basicTypeChar) {
- case 'L': throw newIllegalArgumentException("cannot wrap to object type");
- case 'V': return null;
- case 'I': return Integer.valueOf((int)x);
- case 'J': return Long.valueOf(x);
- case 'F': return Float.valueOf(x);
- case 'D': return Double.valueOf(x);
- case 'S': return Short.valueOf((short) x);
- case 'B': return Byte.valueOf((byte) x);
- case 'C': return Character.valueOf((char) x);
- case 'Z': return Boolean.valueOf(boolValue(x));
- }
- throw new InternalError("bad wrapper");
- }
-
- /** Wrap a value (a long or smaller value) in this wrapper's type.
- * Does not perform floating point conversion.
- * Produces a {@code Long} for {@code OBJECT}, although the exact type
- * of the operand is not known.
- * Returns null for {@code VOID}.
- */
- public Object wrapRaw(long x) {
- switch (basicTypeChar) {
- case 'F': return Float.valueOf(Float.intBitsToFloat((int)x));
- case 'D': return Double.valueOf(Double.longBitsToDouble(x));
- case 'L': // same as 'J':
- case 'J': return (Long) x;
- }
- // Other wrapping operations are just the same, given that the
- // operand is already promoted to an int.
- return wrap((int)x);
- }
-
- /** Produce bitwise value which encodes the given wrapped value.
- * Does not perform floating point conversion.
- * Returns zero for {@code VOID}.
- */
- public long unwrapRaw(Object x) {
- switch (basicTypeChar) {
- case 'F': return Float.floatToRawIntBits((Float) x);
- case 'D': return Double.doubleToRawLongBits((Double) x);
-
- case 'L': throw newIllegalArgumentException("cannot unwrap from sobject type");
- case 'V': return 0;
- case 'I': return (int)(Integer) x;
- case 'J': return (long)(Long) x;
- case 'S': return (short)(Short) x;
- case 'B': return (byte)(Byte) x;
- case 'C': return (char)(Character) x;
- case 'Z': return (boolean)(Boolean) x ? 1 : 0;
- }
- throw new InternalError("bad wrapper");
- }
-
- /** Report what primitive type holds this guy's raw value. */
- public Class<?> rawPrimitiveType() {
- return rawPrimitive().primitiveType();
- }
-
- /** Report, as a wrapper, what primitive type holds this guy's raw value.
- * Returns self for INT, LONG, OBJECT; returns LONG for DOUBLE,
- * else returns INT.
- */
- public Wrapper rawPrimitive() {
- switch (basicTypeChar) {
- case 'S': case 'B':
- case 'C': case 'Z':
- case 'V':
- case 'F':
- return INT;
- case 'D':
- return LONG;
- }
- return this;
- }
-
- private static Number numberValue(Object x) {
- if (x instanceof Number) return (Number)x;
- if (x instanceof Character) return (int)(Character)x;
- if (x instanceof Boolean) return (Boolean)x ? 1 : 0;
- // Remaining allowed case of void: Must be a null reference.
- return (Number)x;
- }
-
- private static boolean boolValue(long bits) {
- //bits &= 1; // simple 31-bit zero extension
- return (bits != 0);
- }
-
- private static RuntimeException newIllegalArgumentException(String message, Object x) {
- return newIllegalArgumentException(message + x);
- }
- private static RuntimeException newIllegalArgumentException(String message) {
- return new IllegalArgumentException(message);
- }
-}
--- a/jdk/src/share/classes/sun/dyn/util/package-info.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * Extra support for using JSR 292 RI, package java.dyn.
- * @author jrose
- */
-
-package sun.dyn.util;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/WrapperInstance.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke;
+
+import java.lang.invoke.MethodHandle;
+
+/**
+ * Private API used inside of java.lang.invoke.MethodHandles.
+ * Interface implemented by every object which is produced by
+ * {@link java.lang.invoke.MethodHandles#asInstance MethodHandles.asInstance}.
+ * The methods of this interface allow a caller to recover the parameters
+ * to {@code asInstance}.
+ * This allows applications to repeatedly convert between method handles
+ * and SAM objects, without the risk of creating unbounded delegation chains.
+ */
+public interface WrapperInstance {
+ /** Produce or recover a target method handle which is behaviorally
+ * equivalent to the SAM method of this object.
+ */
+ public MethodHandle getWrapperInstanceTarget();
+ /** Recover the SAM type for which this object was created.
+ */
+ public Class<?> getWrapperInstanceType();
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/anon/AnonymousClassLoader.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.anon;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import sun.misc.IOUtils;
+
+/**
+ * Anonymous class loader. Will load any valid classfile, producing
+ * a {@link Class} metaobject, without installing that class in the
+ * system dictionary. Therefore, {@link Class#forName(String)} will never
+ * produce a reference to an anonymous class.
+ * <p>
+ * The access permissions of the anonymous class are borrowed from
+ * a <em>host class</em>. The new class behaves as if it were an
+ * inner class of the host class. It can access the host's private
+ * members, if the creator of the class loader has permission to
+ * do so (or to create accessible reflective objects).
+ * <p>
+ * When the anonymous class is loaded, elements of its constant pool
+ * can be patched to new values. This provides a hook to pre-resolve
+ * named classes in the constant pool to other classes, including
+ * anonymous ones. Also, string constants can be pre-resolved to
+ * any reference. (The verifier treats non-string, non-class reference
+ * constants as plain objects.)
+ * <p>
+ * Why include the patching function? It makes some use cases much easier.
+ * Second, the constant pool needed some internal patching anyway,
+ * to anonymize the loaded class itself. Finally, if you are going
+ * to use this seriously, you'll want to build anonymous classes
+ * on top of pre-existing anonymous classes, and that requires patching.
+ *
+ * <p>%%% TO-DO:
+ * <ul>
+ * <li>needs better documentation</li>
+ * <li>needs more security work (for safe delegation)</li>
+ * <li>needs a clearer story about error processing</li>
+ * <li>patch member references also (use ';' as delimiter char)</li>
+ * <li>patch method references to (conforming) method handles</li>
+ * </ul>
+ *
+ * @author jrose
+ * @author Remi Forax
+ * @see <a href="http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm">
+ * http://blogs.sun.com/jrose/entry/anonymous_classes_in_the_vm</a>
+ */
+
+public class AnonymousClassLoader {
+ final Class<?> hostClass;
+
+ // Note: Do not refactor the calls to checkHostClass unless you
+ // also adjust this constant:
+ private static int CHC_CALLERS = 3;
+
+ public AnonymousClassLoader() {
+ this.hostClass = checkHostClass(null);
+ }
+ public AnonymousClassLoader(Class<?> hostClass) {
+ this.hostClass = checkHostClass(hostClass);
+ }
+
+ private static Class<?> getTopLevelClass(Class<?> clazz) {
+ for(Class<?> outer = clazz.getDeclaringClass(); outer != null;
+ outer = outer.getDeclaringClass()) {
+ clazz = outer;
+ }
+ return clazz;
+ }
+
+ private static Class<?> checkHostClass(Class<?> hostClass) {
+ // called only from the constructor
+ // does a context-sensitive check on caller class
+ // CC[0..3] = {Reflection, this.checkHostClass, this.<init>, caller}
+ Class<?> caller = sun.reflect.Reflection.getCallerClass(CHC_CALLERS);
+
+ if (caller == null) {
+ // called from the JVM directly
+ if (hostClass == null)
+ return AnonymousClassLoader.class; // anything central will do
+ return hostClass;
+ }
+
+ if (hostClass == null)
+ hostClass = caller; // default value is caller itself
+
+ // anonymous class will access hostClass on behalf of caller
+ Class<?> callee = hostClass;
+
+ if (caller == callee)
+ // caller can always nominate itself to grant caller's own access rights
+ return hostClass;
+
+ // normalize caller and callee to their top-level classes:
+ caller = getTopLevelClass(caller);
+ callee = getTopLevelClass(callee);
+ if (caller == callee)
+ return caller;
+
+ ClassLoader callerCL = caller.getClassLoader();
+ if (callerCL == null) {
+ // caller is trusted code, so accept the proposed hostClass
+ return hostClass;
+ }
+
+ // %%% should do something with doPrivileged, because trusted
+ // code should have a way to execute on behalf of
+ // partially-trusted clients
+
+ // Does the caller have the right to access the private
+ // members of the callee? If not, raise an error.
+ final int ACC_PRIVATE = 2;
+ try {
+ sun.reflect.Reflection.ensureMemberAccess(caller, callee, null, ACC_PRIVATE);
+ } catch (IllegalAccessException ee) {
+ throw new IllegalArgumentException(ee);
+ }
+
+ return hostClass;
+ }
+
+ public Class<?> loadClass(byte[] classFile) {
+ if (defineAnonymousClass == null) {
+ // no JVM support; try to fake an approximation
+ try {
+ return fakeLoadClass(new ConstantPoolParser(classFile).createPatch());
+ } catch (InvalidConstantPoolFormatException ee) {
+ throw new IllegalArgumentException(ee);
+ }
+ }
+ return loadClass(classFile, null);
+ }
+
+ public Class<?> loadClass(ConstantPoolPatch classPatch) {
+ if (defineAnonymousClass == null) {
+ // no JVM support; try to fake an approximation
+ return fakeLoadClass(classPatch);
+ }
+ Object[] patches = classPatch.patchArray;
+ // Convert class names (this late in the game)
+ // to use slash '/' instead of dot '.'.
+ // Java likes dots, but the JVM likes slashes.
+ for (int i = 0; i < patches.length; i++) {
+ Object value = patches[i];
+ if (value != null) {
+ byte tag = classPatch.getTag(i);
+ switch (tag) {
+ case ConstantPoolVisitor.CONSTANT_Class:
+ if (value instanceof String) {
+ if (patches == classPatch.patchArray)
+ patches = patches.clone();
+ patches[i] = ((String)value).replace('.', '/');
+ }
+ break;
+ case ConstantPoolVisitor.CONSTANT_Fieldref:
+ case ConstantPoolVisitor.CONSTANT_Methodref:
+ case ConstantPoolVisitor.CONSTANT_InterfaceMethodref:
+ case ConstantPoolVisitor.CONSTANT_NameAndType:
+ // When/if the JVM supports these patches,
+ // we'll probably need to reformat them also.
+ // Meanwhile, let the class loader create the error.
+ break;
+ }
+ }
+ }
+ return loadClass(classPatch.outer.classFile, classPatch.patchArray);
+ }
+
+ private Class<?> loadClass(byte[] classFile, Object[] patchArray) {
+ try {
+ return (Class<?>)
+ defineAnonymousClass.invoke(unsafe,
+ hostClass, classFile, patchArray);
+ } catch (Exception ex) {
+ throwReflectedException(ex);
+ throw new RuntimeException("error loading into "+hostClass, ex);
+ }
+ }
+
+ private static void throwReflectedException(Exception ex) {
+ if (ex instanceof InvocationTargetException) {
+ Throwable tex = ((InvocationTargetException)ex).getTargetException();
+ if (tex instanceof Error)
+ throw (Error) tex;
+ ex = (Exception) tex;
+ }
+ if (ex instanceof RuntimeException) {
+ throw (RuntimeException) ex;
+ }
+ }
+
+ private Class<?> fakeLoadClass(ConstantPoolPatch classPatch) {
+ // Implementation:
+ // 1. Make up a new name nobody has used yet.
+ // 2. Inspect the tail-header of the class to find the this_class index.
+ // 3. Patch the CONSTANT_Class for this_class to the new name.
+ // 4. Add other CP entries required by (e.g.) string patches.
+ // 5. Flatten Class constants down to their names, making sure that
+ // the host class loader can pick them up again accurately.
+ // 6. Generate the edited class file bytes.
+ //
+ // Potential limitations:
+ // * The class won't be truly anonymous, and may interfere with others.
+ // * Flattened class constants might not work, because of loader issues.
+ // * Pseudo-string constants will not flatten down to real strings.
+ // * Method handles will (of course) fail to flatten to linkage strings.
+ if (true) throw new UnsupportedOperationException("NYI");
+ Object[] cpArray;
+ try {
+ cpArray = classPatch.getOriginalCP();
+ } catch (InvalidConstantPoolFormatException ex) {
+ throw new RuntimeException(ex);
+ }
+ int thisClassIndex = classPatch.getParser().getThisClassIndex();
+ String thisClassName = (String) cpArray[thisClassIndex];
+ synchronized (AnonymousClassLoader.class) {
+ thisClassName = thisClassName+"\\|"+(++fakeNameCounter);
+ }
+ classPatch.putUTF8(thisClassIndex, thisClassName);
+ byte[] classFile = null;
+ return unsafe.defineClass(null, classFile, 0, classFile.length,
+ hostClass.getClassLoader(),
+ hostClass.getProtectionDomain());
+ }
+ private static int fakeNameCounter = 99999;
+
+ // ignore two warnings on this line:
+ static sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
+ // preceding line requires that this class be on the boot class path
+
+ static private final Method defineAnonymousClass;
+ static {
+ Method dac = null;
+ Class<? extends sun.misc.Unsafe> unsafeClass = unsafe.getClass();
+ try {
+ dac = unsafeClass.getMethod("defineAnonymousClass",
+ Class.class,
+ byte[].class,
+ Object[].class);
+ } catch (Exception ee) {
+ dac = null;
+ }
+ defineAnonymousClass = dac;
+ }
+
+ private static void noJVMSupport() {
+ throw new UnsupportedOperationException("no JVM support for anonymous classes");
+ }
+
+
+ private static native Class<?> loadClassInternal(Class<?> hostClass,
+ byte[] classFile,
+ Object[] patchArray);
+
+ public static byte[] readClassFile(Class<?> templateClass) throws IOException {
+ String templateName = templateClass.getName();
+ int lastDot = templateName.lastIndexOf('.');
+ java.net.URL url = templateClass.getResource(templateName.substring(lastDot+1)+".class");
+ java.net.URLConnection connection = url.openConnection();
+ int contentLength = connection.getContentLength();
+ if (contentLength < 0)
+ throw new IOException("invalid content length "+contentLength);
+
+ return IOUtils.readFully(connection.getInputStream(), contentLength, true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolParser.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.anon;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+
+import static sun.invoke.anon.ConstantPoolVisitor.*;
+
+/** A constant pool parser.
+ */
+public class ConstantPoolParser {
+ final byte[] classFile;
+ final byte[] tags;
+ final char[] firstHeader; // maghi, maglo, minor, major, cplen
+
+ // these are filled in on first parse:
+ int endOffset;
+ char[] secondHeader; // flags, this_class, super_class, intlen
+
+ // used to decode UTF8 array
+ private char[] charArray = new char[80];
+
+ /** Creates a constant pool parser.
+ * @param classFile an array of bytes containing a class.
+ * @throws InvalidConstantPoolFormatException if the header of the class has errors.
+ */
+ public ConstantPoolParser(byte[] classFile) throws InvalidConstantPoolFormatException {
+ this.classFile = classFile;
+ this.firstHeader = parseHeader(classFile);
+ this.tags = new byte[firstHeader[4]];
+ }
+
+ /** Create a constant pool parser by loading the bytecodes of the
+ * class taken as argument.
+ *
+ * @param templateClass the class to parse.
+ *
+ * @throws IOException raised if an I/O occurs when loading
+ * the bytecode of the template class.
+ * @throws InvalidConstantPoolFormatException if the header of the class has errors.
+ *
+ * @see #ConstantPoolParser(byte[])
+ * @see AnonymousClassLoader#readClassFile(Class)
+ */
+ public ConstantPoolParser(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
+ this(AnonymousClassLoader.readClassFile(templateClass));
+ }
+
+ /** Creates an empty patch to patch the class file
+ * used by the current parser.
+ * @return a new class patch.
+ */
+ public ConstantPoolPatch createPatch() {
+ return new ConstantPoolPatch(this);
+ }
+
+ /** Report the tag of the indicated CP entry.
+ * @param index
+ * @return one of {@link ConstantPoolVisitor#CONSTANT_Utf8}, etc.
+ */
+ public byte getTag(int index) {
+ getEndOffset(); // trigger an exception if we haven't parsed yet
+ return tags[index];
+ }
+
+ /** Report the length of the constant pool. */
+ public int getLength() {
+ return firstHeader[4];
+ }
+
+ /** Report the offset, within the class file, of the start of the constant pool. */
+ public int getStartOffset() {
+ return firstHeader.length * 2;
+ }
+
+ /** Report the offset, within the class file, of the end of the constant pool. */
+ public int getEndOffset() {
+ if (endOffset == 0)
+ throw new IllegalStateException("class file has not yet been parsed");
+ return endOffset;
+ }
+
+ /** Report the CP index of this class's own name. */
+ public int getThisClassIndex() {
+ getEndOffset(); // provoke exception if not yet parsed
+ return secondHeader[1];
+ }
+
+ /** Report the total size of the class file. */
+ public int getTailLength() {
+ return classFile.length - getEndOffset();
+ }
+
+ /** Write the head (header plus constant pool)
+ * of the class file to the indicated stream.
+ */
+ public void writeHead(OutputStream out) throws IOException {
+ out.write(classFile, 0, getEndOffset());
+ }
+
+ /** Write the head (header plus constant pool)
+ * of the class file to the indicated stream,
+ * incorporating the non-null entries of the given array
+ * as patches.
+ */
+ void writePatchedHead(OutputStream out, Object[] patchArray) {
+ // this will be useful to partially emulate the class loader on old JVMs
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ /** Write the tail (everything after the constant pool)
+ * of the class file to the indicated stream.
+ */
+ public void writeTail(OutputStream out) throws IOException {
+ out.write(classFile, getEndOffset(), getTailLength());
+ }
+
+ private static char[] parseHeader(byte[] classFile) throws InvalidConstantPoolFormatException {
+ char[] result = new char[5];
+ ByteBuffer buffer = ByteBuffer.wrap(classFile);
+ for (int i = 0; i < result.length; i++)
+ result[i] = (char) getUnsignedShort(buffer);
+ int magic = result[0] << 16 | result[1] << 0;
+ if (magic != 0xCAFEBABE)
+ throw new InvalidConstantPoolFormatException("invalid magic number "+magic);
+ // skip major, minor version
+ int len = result[4];
+ if (len < 1)
+ throw new InvalidConstantPoolFormatException("constant pool length < 1");
+ return result;
+ }
+
+ /** Parse the constant pool of the class
+ * calling a method visit* each time a constant pool entry is parsed.
+ *
+ * The order of the calls to visit* is not guaranteed to be the same
+ * than the order of the constant pool entry in the bytecode array.
+ *
+ * @param visitor
+ * @throws InvalidConstantPoolFormatException
+ */
+ public void parse(ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
+ ByteBuffer buffer = ByteBuffer.wrap(classFile);
+ buffer.position(getStartOffset()); //skip header
+
+ Object[] values = new Object[getLength()];
+ try {
+ parseConstantPool(buffer, values, visitor);
+ } catch(BufferUnderflowException e) {
+ throw new InvalidConstantPoolFormatException(e);
+ }
+ if (endOffset == 0) {
+ endOffset = buffer.position();
+ secondHeader = new char[4];
+ for (int i = 0; i < secondHeader.length; i++) {
+ secondHeader[i] = (char) getUnsignedShort(buffer);
+ }
+ }
+ resolveConstantPool(values, visitor);
+ }
+
+ private char[] getCharArray(int utfLength) {
+ if (utfLength <= charArray.length)
+ return charArray;
+ return charArray = new char[utfLength];
+ }
+
+ private void parseConstantPool(ByteBuffer buffer, Object[] values, ConstantPoolVisitor visitor) throws InvalidConstantPoolFormatException {
+ for (int i = 1; i < tags.length; ) {
+ byte tag = (byte) getUnsignedByte(buffer);
+ assert(tags[i] == 0 || tags[i] == tag);
+ tags[i] = tag;
+ switch (tag) {
+ case CONSTANT_Utf8:
+ int utfLen = getUnsignedShort(buffer);
+ String value = getUTF8(buffer, utfLen, getCharArray(utfLen));
+ visitor.visitUTF8(i, CONSTANT_Utf8, value);
+ tags[i] = tag;
+ values[i++] = value;
+ break;
+ case CONSTANT_Integer:
+ visitor.visitConstantValue(i, tag, buffer.getInt());
+ i++;
+ break;
+ case CONSTANT_Float:
+ visitor.visitConstantValue(i, tag, buffer.getFloat());
+ i++;
+ break;
+ case CONSTANT_Long:
+ visitor.visitConstantValue(i, tag, buffer.getLong());
+ i+=2;
+ break;
+ case CONSTANT_Double:
+ visitor.visitConstantValue(i, tag, buffer.getDouble());
+ i+=2;
+ break;
+
+ case CONSTANT_Class: // fall through:
+ case CONSTANT_String:
+ tags[i] = tag;
+ values[i++] = new int[] { getUnsignedShort(buffer) };
+ break;
+
+ case CONSTANT_Fieldref: // fall through:
+ case CONSTANT_Methodref: // fall through:
+ case CONSTANT_InterfaceMethodref: // fall through:
+ case CONSTANT_NameAndType:
+ tags[i] = tag;
+ values[i++] = new int[] { getUnsignedShort(buffer), getUnsignedShort(buffer) };
+ break;
+ default:
+ throw new AssertionError("invalid constant "+tag);
+ }
+ }
+ }
+
+ private void resolveConstantPool(Object[] values, ConstantPoolVisitor visitor) {
+ // clean out the int[] values, which are temporary
+ for (int beg = 1, end = values.length-1, beg2, end2;
+ beg <= end;
+ beg = beg2, end = end2) {
+ beg2 = end; end2 = beg-1;
+ //System.out.println("CP resolve pass: "+beg+".."+end);
+ for (int i = beg; i <= end; i++) {
+ Object value = values[i];
+ if (!(value instanceof int[]))
+ continue;
+ int[] array = (int[]) value;
+ byte tag = tags[i];
+ switch (tag) {
+ case CONSTANT_String:
+ String stringBody = (String) values[array[0]];
+ visitor.visitConstantString(i, tag, stringBody, array[0]);
+ values[i] = null;
+ break;
+ case CONSTANT_Class: {
+ String className = (String) values[array[0]];
+ // use the external form favored by Class.forName:
+ className = className.replace('/', '.');
+ visitor.visitConstantString(i, tag, className, array[0]);
+ values[i] = className;
+ break;
+ }
+ case CONSTANT_NameAndType: {
+ String memberName = (String) values[array[0]];
+ String signature = (String) values[array[1]];
+ visitor.visitDescriptor(i, tag, memberName, signature,
+ array[0], array[1]);
+ values[i] = new String[] {memberName, signature};
+ break;
+ }
+ case CONSTANT_Fieldref: // fall through:
+ case CONSTANT_Methodref: // fall through:
+ case CONSTANT_InterfaceMethodref: {
+ Object className = values[array[0]];
+ Object nameAndType = values[array[1]];
+ if (!(className instanceof String) ||
+ !(nameAndType instanceof String[])) {
+ // one more pass is needed
+ if (beg2 > i) beg2 = i;
+ if (end2 < i) end2 = i;
+ continue;
+ }
+ String[] nameAndTypeArray = (String[]) nameAndType;
+ visitor.visitMemberRef(i, tag,
+ (String)className,
+ nameAndTypeArray[0],
+ nameAndTypeArray[1],
+ array[0], array[1]);
+ values[i] = null;
+ }
+ break;
+ default:
+ continue;
+ }
+ }
+ }
+ }
+
+ private static int getUnsignedByte(ByteBuffer buffer) {
+ return buffer.get() & 0xFF;
+ }
+
+ private static int getUnsignedShort(ByteBuffer buffer) {
+ int b1 = getUnsignedByte(buffer);
+ int b2 = getUnsignedByte(buffer);
+ return (b1 << 8) + (b2 << 0);
+ }
+
+ private static String getUTF8(ByteBuffer buffer, int utfLen, char[] charArray) throws InvalidConstantPoolFormatException {
+ int utfLimit = buffer.position() + utfLen;
+ int index = 0;
+ while (buffer.position() < utfLimit) {
+ int c = buffer.get() & 0xff;
+ if (c > 127) {
+ buffer.position(buffer.position() - 1);
+ return getUTF8Extended(buffer, utfLimit, charArray, index);
+ }
+ charArray[index++] = (char)c;
+ }
+ return new String(charArray, 0, index);
+ }
+
+ private static String getUTF8Extended(ByteBuffer buffer, int utfLimit, char[] charArray, int index) throws InvalidConstantPoolFormatException {
+ int c, c2, c3;
+ while (buffer.position() < utfLimit) {
+ c = buffer.get() & 0xff;
+ switch (c >> 4) {
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ /* 0xxxxxxx*/
+ charArray[index++] = (char)c;
+ break;
+ case 12: case 13:
+ /* 110x xxxx 10xx xxxx*/
+ c2 = buffer.get();
+ if ((c2 & 0xC0) != 0x80)
+ throw new InvalidConstantPoolFormatException(
+ "malformed input around byte " + buffer.position());
+ charArray[index++] = (char)(((c & 0x1F) << 6) |
+ (c2 & 0x3F));
+ break;
+ case 14:
+ /* 1110 xxxx 10xx xxxx 10xx xxxx */
+ c2 = buffer.get();
+ c3 = buffer.get();
+ if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80))
+ throw new InvalidConstantPoolFormatException(
+ "malformed input around byte " + (buffer.position()));
+ charArray[index++] = (char)(((c & 0x0F) << 12) |
+ ((c2 & 0x3F) << 6) |
+ ((c3 & 0x3F) << 0));
+ break;
+ default:
+ /* 10xx xxxx, 1111 xxxx */
+ throw new InvalidConstantPoolFormatException(
+ "malformed input around byte " + buffer.position());
+ }
+ }
+ // The number of chars produced may be less than utflen
+ return new String(charArray, 0, index);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolPatch.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.anon;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import static sun.invoke.anon.ConstantPoolVisitor.*;
+
+/** A class and its patched constant pool.
+ *
+ * This class allow to modify (patch) a constant pool
+ * by changing the value of its entry.
+ * Entry are referenced using index that can be get
+ * by parsing the constant pool using
+ * {@link ConstantPoolParser#parse(ConstantPoolVisitor)}.
+ *
+ * @see ConstantPoolVisitor
+ * @see ConstantPoolParser#createPatch()
+ */
+public class ConstantPoolPatch {
+ final ConstantPoolParser outer;
+ final Object[] patchArray;
+
+ ConstantPoolPatch(ConstantPoolParser outer) {
+ this.outer = outer;
+ this.patchArray = new Object[outer.getLength()];
+ }
+
+ /** Create a {@link ConstantPoolParser} and
+ * a {@link ConstantPoolPatch} in one step.
+ * Equivalent to {@code new ConstantPoolParser(classFile).createPatch()}.
+ *
+ * @param classFile an array of bytes containing a class.
+ * @see #ConstantPoolParser(Class)
+ */
+ public ConstantPoolPatch(byte[] classFile) throws InvalidConstantPoolFormatException {
+ this(new ConstantPoolParser(classFile));
+ }
+
+ /** Create a {@link ConstantPoolParser} and
+ * a {@link ConstantPoolPatch} in one step.
+ * Equivalent to {@code new ConstantPoolParser(templateClass).createPatch()}.
+ *
+ * @param templateClass the class to parse.
+ * @see #ConstantPoolParser(Class)
+ */
+ public ConstantPoolPatch(Class<?> templateClass) throws IOException, InvalidConstantPoolFormatException {
+ this(new ConstantPoolParser(templateClass));
+ }
+
+
+ /** Creates a patch from an existing patch.
+ * All changes are copied from that patch.
+ * @param patch a patch
+ *
+ * @see ConstantPoolParser#createPatch()
+ */
+ public ConstantPoolPatch(ConstantPoolPatch patch) {
+ outer = patch.outer;
+ patchArray = patch.patchArray.clone();
+ }
+
+ /** Which parser built this patch? */
+ public ConstantPoolParser getParser() {
+ return outer;
+ }
+
+ /** Report the tag at the given index in the constant pool. */
+ public byte getTag(int index) {
+ return outer.getTag(index);
+ }
+
+ /** Report the current patch at the given index of the constant pool.
+ * Null means no patch will be made.
+ * To observe the unpatched entry at the given index, use
+ * {@link #getParser()}{@code .}@link ConstantPoolParser#parse(ConstantPoolVisitor)}
+ */
+ public Object getPatch(int index) {
+ Object value = patchArray[index];
+ if (value == null) return null;
+ switch (getTag(index)) {
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ if (value instanceof String)
+ value = stripSemis(2, (String) value);
+ break;
+ case CONSTANT_NameAndType:
+ if (value instanceof String)
+ value = stripSemis(1, (String) value);
+ break;
+ }
+ return value;
+ }
+
+ /** Clear all patches. */
+ public void clear() {
+ Arrays.fill(patchArray, null);
+ }
+
+ /** Clear one patch. */
+ public void clear(int index) {
+ patchArray[index] = null;
+ }
+
+ /** Produce the patches as an array. */
+ public Object[] getPatches() {
+ return patchArray.clone();
+ }
+
+ /** Produce the original constant pool as an array. */
+ public Object[] getOriginalCP() throws InvalidConstantPoolFormatException {
+ return getOriginalCP(0, patchArray.length, -1);
+ }
+
+ /** Walk the constant pool, applying patches using the given map.
+ *
+ * @param utf8Map Utf8 strings to modify, if encountered
+ * @param classMap Classes (or their names) to modify, if encountered
+ * @param valueMap Constant values to modify, if encountered
+ * @param deleteUsedEntries if true, delete map entries that are used
+ */
+ public void putPatches(final Map<String,String> utf8Map,
+ final Map<String,Object> classMap,
+ final Map<Object,Object> valueMap,
+ boolean deleteUsedEntries) throws InvalidConstantPoolFormatException {
+ final HashSet<String> usedUtf8Keys;
+ final HashSet<String> usedClassKeys;
+ final HashSet<Object> usedValueKeys;
+ if (deleteUsedEntries) {
+ usedUtf8Keys = (utf8Map == null) ? null : new HashSet<String>();
+ usedClassKeys = (classMap == null) ? null : new HashSet<String>();
+ usedValueKeys = (valueMap == null) ? null : new HashSet<Object>();
+ } else {
+ usedUtf8Keys = null;
+ usedClassKeys = null;
+ usedValueKeys = null;
+ }
+
+ outer.parse(new ConstantPoolVisitor() {
+
+ @Override
+ public void visitUTF8(int index, byte tag, String utf8) {
+ putUTF8(index, utf8Map.get(utf8));
+ if (usedUtf8Keys != null) usedUtf8Keys.add(utf8);
+ }
+
+ @Override
+ public void visitConstantValue(int index, byte tag, Object value) {
+ putConstantValue(index, tag, valueMap.get(value));
+ if (usedValueKeys != null) usedValueKeys.add(value);
+ }
+
+ @Override
+ public void visitConstantString(int index, byte tag, String name, int nameIndex) {
+ if (tag == CONSTANT_Class) {
+ putConstantValue(index, tag, classMap.get(name));
+ if (usedClassKeys != null) usedClassKeys.add(name);
+ } else {
+ assert(tag == CONSTANT_String);
+ visitConstantValue(index, tag, name);
+ }
+ }
+ });
+ if (usedUtf8Keys != null) utf8Map.keySet().removeAll(usedUtf8Keys);
+ if (usedClassKeys != null) classMap.keySet().removeAll(usedClassKeys);
+ if (usedValueKeys != null) valueMap.keySet().removeAll(usedValueKeys);
+ }
+
+ Object[] getOriginalCP(final int startIndex,
+ final int endIndex,
+ final int tagMask) throws InvalidConstantPoolFormatException {
+ final Object[] cpArray = new Object[endIndex - startIndex];
+ outer.parse(new ConstantPoolVisitor() {
+
+ void show(int index, byte tag, Object value) {
+ if (index < startIndex || index >= endIndex) return;
+ if (((1 << tag) & tagMask) == 0) return;
+ cpArray[index - startIndex] = value;
+ }
+
+ @Override
+ public void visitUTF8(int index, byte tag, String utf8) {
+ show(index, tag, utf8);
+ }
+
+ @Override
+ public void visitConstantValue(int index, byte tag, Object value) {
+ assert(tag != CONSTANT_String);
+ show(index, tag, value);
+ }
+
+ @Override
+ public void visitConstantString(int index, byte tag,
+ String value, int j) {
+ show(index, tag, value);
+ }
+
+ @Override
+ public void visitMemberRef(int index, byte tag,
+ String className, String memberName,
+ String signature,
+ int j, int k) {
+ show(index, tag, new String[]{ className, memberName, signature });
+ }
+
+ @Override
+ public void visitDescriptor(int index, byte tag,
+ String memberName, String signature,
+ int j, int k) {
+ show(index, tag, new String[]{ memberName, signature });
+ }
+ });
+ return cpArray;
+ }
+
+ /** Write the head (header plus constant pool)
+ * of the patched class file to the indicated stream.
+ */
+ void writeHead(OutputStream out) throws IOException {
+ outer.writePatchedHead(out, patchArray);
+ }
+
+ /** Write the tail (everything after the constant pool)
+ * of the patched class file to the indicated stream.
+ */
+ void writeTail(OutputStream out) throws IOException {
+ outer.writeTail(out);
+ }
+
+ private void checkConstantTag(byte tag, Object value) {
+ if (value == null)
+ throw new IllegalArgumentException(
+ "invalid null constant value");
+ if (classForTag(tag) != value.getClass())
+ throw new IllegalArgumentException(
+ "invalid constant value"
+ + (tag == CONSTANT_None ? ""
+ : " for tag "+tagName(tag))
+ + " of class "+value.getClass());
+ }
+
+ private void checkTag(int index, byte putTag) {
+ byte tag = outer.tags[index];
+ if (tag != putTag)
+ throw new IllegalArgumentException(
+ "invalid put operation"
+ + " for " + tagName(putTag)
+ + " at index " + index + " found " + tagName(tag));
+ }
+
+ private void checkTagMask(int index, int tagBitMask) {
+ byte tag = outer.tags[index];
+ int tagBit = ((tag & 0x1F) == tag) ? (1 << tag) : 0;
+ if ((tagBit & tagBitMask) == 0)
+ throw new IllegalArgumentException(
+ "invalid put operation"
+ + " at index " + index + " found " + tagName(tag));
+ }
+
+ private static void checkMemberName(String memberName) {
+ if (memberName.indexOf(';') >= 0)
+ throw new IllegalArgumentException("memberName " + memberName + " contains a ';'");
+ }
+
+ /** Set the entry of the constant pool indexed by index to
+ * a new string.
+ *
+ * @param index an index to a constant pool entry containing a
+ * {@link ConstantPoolVisitor#CONSTANT_Utf8} value.
+ * @param utf8 a string
+ *
+ * @see ConstantPoolVisitor#visitUTF8(int, byte, String)
+ */
+ public void putUTF8(int index, String utf8) {
+ if (utf8 == null) { clear(index); return; }
+ checkTag(index, CONSTANT_Utf8);
+ patchArray[index] = utf8;
+ }
+
+ /** Set the entry of the constant pool indexed by index to
+ * a new value, depending on its dynamic type.
+ *
+ * @param index an index to a constant pool entry containing a
+ * one of the following structures:
+ * {@link ConstantPoolVisitor#CONSTANT_Integer},
+ * {@link ConstantPoolVisitor#CONSTANT_Float},
+ * {@link ConstantPoolVisitor#CONSTANT_Long},
+ * {@link ConstantPoolVisitor#CONSTANT_Double},
+ * {@link ConstantPoolVisitor#CONSTANT_String}, or
+ * {@link ConstantPoolVisitor#CONSTANT_Class}
+ * @param value a boxed int, float, long or double; or a string or class object
+ * @throws IllegalArgumentException if the type of the constant does not
+ * match the constant pool entry type,
+ * as reported by {@link #getTag(int)}
+ *
+ * @see #putConstantValue(int, byte, Object)
+ * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
+ * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
+ */
+ public void putConstantValue(int index, Object value) {
+ if (value == null) { clear(index); return; }
+ byte tag = tagForConstant(value.getClass());
+ checkConstantTag(tag, value);
+ checkTag(index, tag);
+ patchArray[index] = value;
+ }
+
+ /** Set the entry of the constant pool indexed by index to
+ * a new value.
+ *
+ * @param index an index to a constant pool entry matching the given tag
+ * @param tag one of the following values:
+ * {@link ConstantPoolVisitor#CONSTANT_Integer},
+ * {@link ConstantPoolVisitor#CONSTANT_Float},
+ * {@link ConstantPoolVisitor#CONSTANT_Long},
+ * {@link ConstantPoolVisitor#CONSTANT_Double},
+ * {@link ConstantPoolVisitor#CONSTANT_String}, or
+ * {@link ConstantPoolVisitor#CONSTANT_Class}
+ * @param value a boxed number, string, or class object
+ * @throws IllegalArgumentException if the type of the constant does not
+ * match the constant pool entry type, or if a class name contains
+ * '/' or ';'
+ *
+ * @see #putConstantValue(int, Object)
+ * @see ConstantPoolVisitor#visitConstantValue(int, byte, Object)
+ * @see ConstantPoolVisitor#visitConstantString(int, byte, String, int)
+ */
+ public void putConstantValue(int index, byte tag, Object value) {
+ if (value == null) { clear(index); return; }
+ checkTag(index, tag);
+ if (tag == CONSTANT_Class && value instanceof String) {
+ checkClassName((String) value);
+ } else if (tag == CONSTANT_String) {
+ // the JVM accepts any object as a patch for a string
+ } else {
+ // make sure the incoming value is the right type
+ checkConstantTag(tag, value);
+ }
+ checkTag(index, tag);
+ patchArray[index] = value;
+ }
+
+ /** Set the entry of the constant pool indexed by index to
+ * a new {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
+ *
+ * @param index an index to a constant pool entry containing a
+ * {@link ConstantPoolVisitor#CONSTANT_NameAndType} value.
+ * @param memberName a memberName
+ * @param signature a signature
+ * @throws IllegalArgumentException if memberName contains the character ';'
+ *
+ * @see ConstantPoolVisitor#visitDescriptor(int, byte, String, String, int, int)
+ */
+ public void putDescriptor(int index, String memberName, String signature) {
+ checkTag(index, CONSTANT_NameAndType);
+ checkMemberName(memberName);
+ patchArray[index] = addSemis(memberName, signature);
+ }
+
+ /** Set the entry of the constant pool indexed by index to
+ * a new {@link ConstantPoolVisitor#CONSTANT_Fieldref},
+ * {@link ConstantPoolVisitor#CONSTANT_Methodref}, or
+ * {@link ConstantPoolVisitor#CONSTANT_InterfaceMethodref} value.
+ *
+ * @param index an index to a constant pool entry containing a member reference
+ * @param className a class name
+ * @param memberName a field or method name
+ * @param signature a field or method signature
+ * @throws IllegalArgumentException if memberName contains the character ';'
+ * or signature is not a correct signature
+ *
+ * @see ConstantPoolVisitor#visitMemberRef(int, byte, String, String, String, int, int)
+ */
+ public void putMemberRef(int index, byte tag,
+ String className, String memberName, String signature) {
+ checkTagMask(tag, CONSTANT_MemberRef_MASK);
+ checkTag(index, tag);
+ checkClassName(className);
+ checkMemberName(memberName);
+ if (signature.startsWith("(") == (tag == CONSTANT_Fieldref))
+ throw new IllegalArgumentException("bad signature: "+signature);
+ patchArray[index] = addSemis(className, memberName, signature);
+ }
+
+ static private final int CONSTANT_MemberRef_MASK =
+ CONSTANT_Fieldref
+ | CONSTANT_Methodref
+ | CONSTANT_InterfaceMethodref;
+
+ private static final Map<Class<?>, Byte> CONSTANT_VALUE_CLASS_TAG
+ = new IdentityHashMap<Class<?>, Byte>();
+ private static final Class[] CONSTANT_VALUE_CLASS = new Class[16];
+ static {
+ Object[][] values = {
+ {Integer.class, CONSTANT_Integer},
+ {Long.class, CONSTANT_Long},
+ {Float.class, CONSTANT_Float},
+ {Double.class, CONSTANT_Double},
+ {String.class, CONSTANT_String},
+ {Class.class, CONSTANT_Class}
+ };
+ for (Object[] value : values) {
+ Class<?> cls = (Class<?>)value[0];
+ Byte tag = (Byte) value[1];
+ CONSTANT_VALUE_CLASS_TAG.put(cls, tag);
+ CONSTANT_VALUE_CLASS[(byte)tag] = cls;
+ }
+ }
+
+ static Class<?> classForTag(byte tag) {
+ if ((tag & 0xFF) >= CONSTANT_VALUE_CLASS.length)
+ return null;
+ return CONSTANT_VALUE_CLASS[tag];
+ }
+
+ static byte tagForConstant(Class<?> cls) {
+ Byte tag = CONSTANT_VALUE_CLASS_TAG.get(cls);
+ return (tag == null) ? CONSTANT_None : (byte)tag;
+ }
+
+ private static void checkClassName(String className) {
+ if (className.indexOf('/') >= 0 || className.indexOf(';') >= 0)
+ throw new IllegalArgumentException("invalid class name " + className);
+ }
+
+ static String addSemis(String name, String... names) {
+ StringBuilder buf = new StringBuilder(name.length() * 5);
+ buf.append(name);
+ for (String name2 : names) {
+ buf.append(';').append(name2);
+ }
+ String res = buf.toString();
+ assert(stripSemis(names.length, res)[0].equals(name));
+ assert(stripSemis(names.length, res)[1].equals(names[0]));
+ assert(names.length == 1 ||
+ stripSemis(names.length, res)[2].equals(names[1]));
+ return res;
+ }
+
+ static String[] stripSemis(int count, String string) {
+ String[] res = new String[count+1];
+ int pos = 0;
+ for (int i = 0; i < count; i++) {
+ int pos2 = string.indexOf(';', pos);
+ if (pos2 < 0) pos2 = string.length(); // yuck
+ res[i] = string.substring(pos, pos2);
+ pos = pos2;
+ }
+ res[count] = string.substring(pos);
+ return res;
+ }
+
+ public String toString() {
+ StringBuilder buf = new StringBuilder(this.getClass().getName());
+ buf.append("{");
+ Object[] origCP = null;
+ for (int i = 0; i < patchArray.length; i++) {
+ if (patchArray[i] == null) continue;
+ if (origCP != null) {
+ buf.append(", ");
+ } else {
+ try {
+ origCP = getOriginalCP();
+ } catch (InvalidConstantPoolFormatException ee) {
+ origCP = new Object[0];
+ }
+ }
+ Object orig = (i < origCP.length) ? origCP[i] : "?";
+ buf.append(orig).append("=").append(patchArray[i]);
+ }
+ buf.append("}");
+ return buf.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/anon/ConstantPoolVisitor.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.anon;
+
+/**
+ * A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
+ * when a constant pool entry is parsed.
+ * <p>
+ * A visit* method is called when a constant pool entry is parsed.
+ * The first argument is always the constant pool index.
+ * The second argument is always the constant pool tag,
+ * even for methods like {@link #visitUTF8(int, byte, String)} which only apply to one tag.
+ * String arguments refer to Utf8 or NameAndType entries declared elsewhere,
+ * and are always accompanied by the indexes of those entries.
+ * <p>
+ * The order of the calls to the visit* methods is not necessarily related
+ * to the order of the entries in the constant pool.
+ * If one entry has a reference to another entry, the latter (lower-level)
+ * entry will be visited first.
+ * <p>
+ * The following table shows the relation between constant pool entry
+ * types and the corresponding visit* methods:
+ *
+ * <table border=1 cellpadding=5 summary="constant pool visitor methods">
+ * <tr><th>Tag(s)</th><th>Method</th></tr>
+ * <tr>
+ * <td>{@link #CONSTANT_Utf8}</td>
+ * <td>{@link #visitUTF8(int, byte, String)}</td>
+ * </tr><tr>
+ * <td>{@link #CONSTANT_Integer}, {@link #CONSTANT_Float},
+ * {@link #CONSTANT_Long}, {@link #CONSTANT_Double}</td>
+ * <td>{@link #visitConstantValue(int, byte, Object)}</td>
+ * </tr><tr>
+ * <td>{@link #CONSTANT_String}, {@link #CONSTANT_Class}</td>
+ * <td>{@link #visitConstantString(int, byte, String, int)}</td>
+ * </tr><tr>
+ * <td>{@link #CONSTANT_NameAndType}</td>
+ * <td>{@link #visitDescriptor(int, byte, String, String, int, int)}</td>
+ * </tr><tr>
+ * <td>{@link #CONSTANT_Fieldref},
+ * {@link #CONSTANT_Methodref},
+ * {@link #CONSTANT_InterfaceMethodref}</td>
+ * <td>{@link #visitMemberRef(int, byte, String, String, String, int, int)}</td>
+ * </tr>
+ * </table>
+ *
+ * @see ConstantPoolPatch
+ * @author Remi Forax
+ * @author jrose
+ */
+public class ConstantPoolVisitor {
+ /** Called each time an UTF8 constant pool entry is found.
+ * @param index the constant pool index
+ * @param tag always {@link #CONSTANT_Utf8}
+ * @param utf8 string encoded in modified UTF-8 format passed as a {@code String}
+ *
+ * @see ConstantPoolPatch#putUTF8(int, String)
+ */
+ public void visitUTF8(int index, byte tag, String utf8) {
+ // do nothing
+ }
+
+ /** Called for each constant pool entry that encodes an integer,
+ * a float, a long, or a double.
+ * Constant strings and classes are not managed by this method but
+ * by {@link #visitConstantString(int, byte, String, int)}.
+ *
+ * @param index the constant pool index
+ * @param tag one of {@link #CONSTANT_Integer},
+ * {@link #CONSTANT_Float},
+ * {@link #CONSTANT_Long},
+ * or {@link #CONSTANT_Double}
+ * @param value encoded value
+ *
+ * @see ConstantPoolPatch#putConstantValue(int, Object)
+ */
+ public void visitConstantValue(int index, byte tag, Object value) {
+ // do nothing
+ }
+
+ /** Called for each constant pool entry that encodes a string or a class.
+ * @param index the constant pool index
+ * @param tag one of {@link #CONSTANT_String},
+ * {@link #CONSTANT_Class},
+ * @param name string body or class name (using dot separator)
+ * @param nameIndex the index of the Utf8 string for the name
+ *
+ * @see ConstantPoolPatch#putConstantValue(int, byte, Object)
+ */
+ public void visitConstantString(int index, byte tag,
+ String name, int nameIndex) {
+ // do nothing
+ }
+
+ /** Called for each constant pool entry that encodes a name and type.
+ * @param index the constant pool index
+ * @param tag always {@link #CONSTANT_NameAndType}
+ * @param memberName a field or method name
+ * @param signature the member signature
+ * @param memberNameIndex index of the Utf8 string for the member name
+ * @param signatureIndex index of the Utf8 string for the signature
+ *
+ * @see ConstantPoolPatch#putDescriptor(int, String, String)
+ */
+ public void visitDescriptor(int index, byte tag,
+ String memberName, String signature,
+ int memberNameIndex, int signatureIndex) {
+ // do nothing
+ }
+
+ /** Called for each constant pool entry that encodes a field or method.
+ * @param index the constant pool index
+ * @param tag one of {@link #CONSTANT_Fieldref},
+ * or {@link #CONSTANT_Methodref},
+ * or {@link #CONSTANT_InterfaceMethodref}
+ * @param className the class name (using dot separator)
+ * @param memberName name of the field or method
+ * @param signature the field or method signature
+ * @param classNameIndex index of the Utf8 string for the class name
+ * @param descriptorIndex index of the NameAndType descriptor constant
+ *
+ * @see ConstantPoolPatch#putMemberRef(int, byte, String, String, String)
+ */
+ public void visitMemberRef(int index, byte tag,
+ String className, String memberName, String signature,
+ int classNameIndex, int descriptorIndex) {
+ // do nothing
+ }
+
+ public static final byte
+ CONSTANT_None = 0,
+ CONSTANT_Utf8 = 1,
+ //CONSTANT_Unicode = 2, /* unused */
+ CONSTANT_Integer = 3,
+ CONSTANT_Float = 4,
+ CONSTANT_Long = 5,
+ CONSTANT_Double = 6,
+ CONSTANT_Class = 7,
+ CONSTANT_String = 8,
+ CONSTANT_Fieldref = 9,
+ CONSTANT_Methodref = 10,
+ CONSTANT_InterfaceMethodref = 11,
+ CONSTANT_NameAndType = 12;
+
+ private static String[] TAG_NAMES = {
+ "Empty",
+ "Utf8",
+ null, //"Unicode",
+ "Integer",
+ "Float",
+ "Long",
+ "Double",
+ "Class",
+ "String",
+ "Fieldref",
+ "Methodref",
+ "InterfaceMethodref",
+ "NameAndType"
+ };
+
+ public static String tagName(byte tag) {
+ String name = null;
+ if ((tag & 0xFF) < TAG_NAMES.length)
+ name = TAG_NAMES[tag];
+ if (name == null)
+ name = "Unknown#"+(tag&0xFF);
+ return name;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/anon/InvalidConstantPoolFormatException.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.anon;
+
+/** Exception used when there is an error in the constant pool
+ * format.
+ */
+public class InvalidConstantPoolFormatException extends Exception {
+ private static final long serialVersionUID=-6103888330523770949L;
+
+ public InvalidConstantPoolFormatException(String message,Throwable cause) {
+ super(message,cause);
+ }
+
+ public InvalidConstantPoolFormatException(String message) {
+ super(message);
+ }
+
+ public InvalidConstantPoolFormatException(Throwable cause) {
+ super(cause);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/empty/Empty.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.empty;
+
+/**
+ * An empty class in an empty package.
+ * Used as a proxy for unprivileged code, since making access checks
+ * against it will only succeed against public methods in public types.
+ * <p>
+ * This class also stands (internally to sun.invoke) for the type of a
+ * value that cannot be produced, because the expression of this type
+ * always returns abnormally. (Cf. Nothing in the closures proposal.)
+ * @author jrose
+ */
+public class Empty {
+ private Empty() { throw new InternalError(); }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/package-info.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Implementation details for JSR 292 RI, package java.lang.invoke.
+ * @author jrose
+ */
+
+package sun.invoke;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/BytecodeDescriptor.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility routines for dealing with bytecode-level signatures.
+ * @author jrose
+ */
+public class BytecodeDescriptor {
+
+ private BytecodeDescriptor() { } // cannot instantiate
+
+ public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
+ return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
+ }
+
+ static List<Class<?>> parseMethod(String bytecodeSignature,
+ int start, int end, ClassLoader loader) {
+ if (loader == null)
+ loader = ClassLoader.getSystemClassLoader();
+ String str = bytecodeSignature;
+ int[] i = {start};
+ ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>();
+ if (i[0] < end && str.charAt(i[0]) == '(') {
+ ++i[0]; // skip '('
+ while (i[0] < end && str.charAt(i[0]) != ')') {
+ Class<?> pt = parseSig(str, i, end, loader);
+ if (pt == null || pt == void.class)
+ parseError(str, "bad argument type");
+ ptypes.add(pt);
+ }
+ ++i[0]; // skip ')'
+ } else {
+ parseError(str, "not a method type");
+ }
+ Class<?> rtype = parseSig(str, i, end, loader);
+ if (rtype == null || i[0] != end)
+ parseError(str, "bad return type");
+ ptypes.add(rtype);
+ return ptypes;
+ }
+
+ static private void parseError(String str, String msg) {
+ throw new IllegalArgumentException("bad signature: "+str+": "+msg);
+ }
+
+ static private Class<?> parseSig(String str, int[] i, int end, ClassLoader loader) {
+ if (i[0] == end) return null;
+ char c = str.charAt(i[0]++);
+ if (c == 'L') {
+ int begc = i[0], endc = str.indexOf(';', begc);
+ if (endc < 0) return null;
+ i[0] = endc+1;
+ String name = str.substring(begc, endc).replace('/', '.');
+ try {
+ return loader.loadClass(name);
+ } catch (ClassNotFoundException ex) {
+ throw new TypeNotPresentException(name, ex);
+ }
+ } else if (c == '[') {
+ Class<?> t = parseSig(str, i, end, loader);
+ if (t != null)
+ t = java.lang.reflect.Array.newInstance(t, 0).getClass();
+ return t;
+ } else {
+ return Wrapper.forBasicType(c).primitiveType();
+ }
+ }
+
+ public static String unparse(Class<?> type) {
+ StringBuilder sb = new StringBuilder();
+ unparseSig(type, sb);
+ return sb.toString();
+ }
+
+ public static String unparse(MethodType type) {
+ return unparseMethod(type.returnType(), type.parameterList());
+ }
+
+ public static String unparse(Object type) {
+ if (type instanceof Class<?>)
+ return unparse((Class<?>) type);
+ if (type instanceof MethodType)
+ return unparse((MethodType) type);
+ return (String) type;
+ }
+
+ public static String unparseMethod(Class<?> rtype, List<Class<?>> ptypes) {
+ StringBuilder sb = new StringBuilder();
+ sb.append('(');
+ for (Class<?> pt : ptypes)
+ unparseSig(pt, sb);
+ sb.append(')');
+ unparseSig(rtype, sb);
+ return sb.toString();
+ }
+
+ static private void unparseSig(Class<?> t, StringBuilder sb) {
+ char c = Wrapper.forBasicType(t).basicTypeChar();
+ if (c != 'L') {
+ sb.append(c);
+ } else {
+ boolean lsemi = (!t.isArray());
+ if (lsemi) sb.append('L');
+ sb.append(t.getName().replace('.', '/'));
+ if (lsemi) sb.append(';');
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/BytecodeName.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,627 @@
+/*
+ * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+/**
+ * Utility routines for dealing with bytecode-level names.
+ * Includes universal mangling rules for the JVM.
+ *
+ * <h3>Avoiding Dangerous Characters </h3>
+ *
+ * <p>
+ * The JVM defines a very small set of characters which are illegal
+ * in name spellings. We will slightly extend and regularize this set
+ * into a group of <cite>dangerous characters</cite>.
+ * These characters will then be replaced, in mangled names, by escape sequences.
+ * In addition, accidental escape sequences must be further escaped.
+ * Finally, a special prefix will be applied if and only if
+ * the mangling would otherwise fail to begin with the escape character.
+ * This happens to cover the corner case of the null string,
+ * and also clearly marks symbols which need demangling.
+ * </p>
+ * <p>
+ * Dangerous characters are the union of all characters forbidden
+ * or otherwise restricted by the JVM specification,
+ * plus their mates, if they are brackets
+ * (<code><big><b>[</b></big></code> and <code><big><b>]</b></big></code>,
+ * <code><big><b><</b></big></code> and <code><big><b>></b></big></code>),
+ * plus, arbitrarily, the colon character <code><big><b>:</b></big></code>.
+ * There is no distinction between type, method, and field names.
+ * This makes it easier to convert between mangled names of different
+ * types, since they do not need to be decoded (demangled).
+ * </p>
+ * <p>
+ * The escape character is backslash <code><big><b>\</b></big></code>
+ * (also known as reverse solidus).
+ * This character is, until now, unheard of in bytecode names,
+ * but traditional in the proposed role.
+ *
+ * </p>
+ * <h3> Replacement Characters </h3>
+ *
+ *
+ * <p>
+ * Every escape sequence is two characters
+ * (in fact, two UTF8 bytes) beginning with
+ * the escape character and followed by a
+ * <cite>replacement character</cite>.
+ * (Since the replacement character is never a backslash,
+ * iterated manglings do not double in size.)
+ * </p>
+ * <p>
+ * Each dangerous character has some rough visual similarity
+ * to its corresponding replacement character.
+ * This makes mangled symbols easier to recognize by sight.
+ * </p>
+ * <p>
+ * The dangerous characters are
+ * <code><big><b>/</b></big></code> (forward slash, used to delimit package components),
+ * <code><big><b>.</b></big></code> (dot, also a package delimiter),
+ * <code><big><b>;</b></big></code> (semicolon, used in signatures),
+ * <code><big><b>$</b></big></code> (dollar, used in inner classes and synthetic members),
+ * <code><big><b><</b></big></code> (left angle),
+ * <code><big><b>></b></big></code> (right angle),
+ * <code><big><b>[</b></big></code> (left square bracket, used in array types),
+ * <code><big><b>]</b></big></code> (right square bracket, reserved in this scheme for language use),
+ * and <code><big><b>:</b></big></code> (colon, reserved in this scheme for language use).
+ * Their replacements are, respectively,
+ * <code><big><b>|</b></big></code> (vertical bar),
+ * <code><big><b>,</b></big></code> (comma),
+ * <code><big><b>?</b></big></code> (question mark),
+ * <code><big><b>%</b></big></code> (percent),
+ * <code><big><b>^</b></big></code> (caret),
+ * <code><big><b>_</b></big></code> (underscore), and
+ * <code><big><b>{</b></big></code> (left curly bracket),
+ * <code><big><b>}</b></big></code> (right curly bracket),
+ * <code><big><b>!</b></big></code> (exclamation mark).
+ * In addition, the replacement character for the escape character itself is
+ * <code><big><b>-</b></big></code> (hyphen),
+ * and the replacement character for the null prefix is
+ * <code><big><b>=</b></big></code> (equal sign).
+ * </p>
+ * <p>
+ * An escape character <code><big><b>\</b></big></code>
+ * followed by any of these replacement characters
+ * is an escape sequence, and there are no other escape sequences.
+ * An equal sign is only part of an escape sequence
+ * if it is the second character in the whole string, following a backslash.
+ * Two consecutive backslashes do <em>not</em> form an escape sequence.
+ * </p>
+ * <p>
+ * Each escape sequence replaces a so-called <cite>original character</cite>
+ * which is either one of the dangerous characters or the escape character.
+ * A null prefix replaces an initial null string, not a character.
+ * </p>
+ * <p>
+ * All this implies that escape sequences cannot overlap and may be
+ * determined all at once for a whole string. Note that a spelling
+ * string can contain <cite>accidental escapes</cite>, apparent escape
+ * sequences which must not be interpreted as manglings.
+ * These are disabled by replacing their leading backslash with an
+ * escape sequence (<code><big><b>\-</b></big></code>). To mangle a string, three logical steps
+ * are required, though they may be carried out in one pass:
+ * </p>
+ * <ol>
+ * <li>In each accidental escape, replace the backslash with an escape sequence
+ * (<code><big><b>\-</b></big></code>).</li>
+ * <li>Replace each dangerous character with an escape sequence
+ * (<code><big><b>\|</b></big></code> for <code><big><b>/</b></big></code>, etc.).</li>
+ * <li>If the first two steps introduced any change, <em>and</em>
+ * if the string does not already begin with a backslash, prepend a null prefix (<code><big><b>\=</b></big></code>).</li>
+ * </ol>
+ *
+ * To demangle a mangled string that begins with an escape,
+ * remove any null prefix, and then replace (in parallel)
+ * each escape sequence by its original character.
+ * <p>Spelling strings which contain accidental
+ * escapes <em>must</em> have them replaced, even if those
+ * strings do not contain dangerous characters.
+ * This restriction means that mangling a string always
+ * requires a scan of the string for escapes.
+ * But then, a scan would be required anyway,
+ * to check for dangerous characters.
+ *
+ * </p>
+ * <h3> Nice Properties </h3>
+ *
+ * <p>
+ * If a bytecode name does not contain any escape sequence,
+ * demangling is a no-op: The string demangles to itself.
+ * Such a string is called <cite>self-mangling</cite>.
+ * Almost all strings are self-mangling.
+ * In practice, to demangle almost any name “found in nature”,
+ * simply verify that it does not begin with a backslash.
+ * </p>
+ * <p>
+ * Mangling is a one-to-one function, while demangling
+ * is a many-to-one function.
+ * A mangled string is defined as <cite>validly mangled</cite> if
+ * it is in fact the unique mangling of its spelling string.
+ * Three examples of invalidly mangled strings are <code><big><b>\=foo</b></big></code>,
+ * <code><big><b>\-bar</b></big></code>, and <code><big><b>baz\!</b></big></code>, which demangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and
+ * <code><big><b>baz\!</b></big></code>, but then remangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and <code><big><b>\=baz\-!</b></big></code>.
+ * If a language back-end or runtime is using mangled names,
+ * it should never present an invalidly mangled bytecode
+ * name to the JVM. If the runtime encounters one,
+ * it should also report an error, since such an occurrence
+ * probably indicates a bug in name encoding which
+ * will lead to errors in linkage.
+ * However, this note does not propose that the JVM verifier
+ * detect invalidly mangled names.
+ * </p>
+ * <p>
+ * As a result of these rules, it is a simple matter to
+ * compute validly mangled substrings and concatenations
+ * of validly mangled strings, and (with a little care)
+ * these correspond to corresponding operations on their
+ * spelling strings.
+ * </p>
+ * <ul>
+ * <li>Any prefix of a validly mangled string is also validly mangled,
+ * although a null prefix may need to be removed.</li>
+ * <li>Any suffix of a validly mangled string is also validly mangled,
+ * although a null prefix may need to be added.</li>
+ * <li>Two validly mangled strings, when concatenated,
+ * are also validly mangled, although any null prefix
+ * must be removed from the second string,
+ * and a trailing backslash on the first string may need escaping,
+ * if it would participate in an accidental escape when followed
+ * by the first character of the second string.</li>
+ * </ul>
+ * <p>If languages that include non-Java symbol spellings use this
+ * mangling convention, they will enjoy the following advantages:
+ * </p>
+ * <ul>
+ * <li>They can interoperate via symbols they share in common.</li>
+ * <li>Low-level tools, such as backtrace printers, will have readable displays.</li>
+ * <li>Future JVM and language extensions can safely use the dangerous characters
+ * for structuring symbols, but will never interfere with valid spellings.</li>
+ * <li>Runtimes and compilers can use standard libraries for mangling and demangling.</li>
+ * <li>Occasional transliterations and name composition will be simple and regular,
+ * for classes, methods, and fields.</li>
+ * <li>Bytecode names will continue to be compact.
+ * When mangled, spellings will at most double in length, either in
+ * UTF8 or UTF16 format, and most will not change at all.</li>
+ * </ul>
+ *
+ *
+ * <h3> Suggestions for Human Readable Presentations </h3>
+ *
+ *
+ * <p>
+ * For human readable displays of symbols,
+ * it will be better to present a string-like quoted
+ * representation of the spelling, because JVM users
+ * are generally familiar with such tokens.
+ * We suggest using single or double quotes before and after
+ * mangled symbols which are not valid Java identifiers,
+ * with quotes, backslashes, and non-printing characters
+ * escaped as if for literals in the Java language.
+ * </p>
+ * <p>
+ * For example, an HTML-like spelling
+ * <code><big><b><pre></b></big></code> mangles to
+ * <code><big><b>\^pre\_</b></big></code> and could
+ * display more cleanly as
+ * <code><big><b>'<pre>'</b></big></code>,
+ * with the quotes included.
+ * Such string-like conventions are <em>not</em> suitable
+ * for mangled bytecode names, in part because
+ * dangerous characters must be eliminated, rather
+ * than just quoted. Otherwise internally structured
+ * strings like package prefixes and method signatures
+ * could not be reliably parsed.
+ * </p>
+ * <p>
+ * In such human-readable displays, invalidly mangled
+ * names should <em>not</em> be demangled and quoted,
+ * for this would be misleading. Likewise, JVM symbols
+ * which contain dangerous characters (like dots in field
+ * names or brackets in method names) should not be
+ * simply quoted. The bytecode names
+ * <code><big><b>\=phase\,1</b></big></code> and
+ * <code><big><b>phase.1</b></big></code> are distinct,
+ * and in demangled displays they should be presented as
+ * <code><big><b>'phase.1'</b></big></code> and something like
+ * <code><big><b>'phase'.1</b></big></code>, respectively.
+ * </p>
+ *
+ * @author John Rose
+ * @version 1.2, 02/06/2008
+ * @see http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm
+ */
+public class BytecodeName {
+ private BytecodeName() { } // static only class
+
+ /** Given a source name, produce the corresponding bytecode name.
+ * The source name should not be qualified, because any syntactic
+ * markers (dots, slashes, dollar signs, colons, etc.) will be mangled.
+ * @param s the source name
+ * @return a valid bytecode name which represents the source name
+ */
+ public static String toBytecodeName(String s) {
+ String bn = mangle(s);
+ assert((Object)bn == s || looksMangled(bn)) : bn;
+ assert(s.equals(toSourceName(bn))) : s;
+ return bn;
+ }
+
+ /** Given an unqualified bytecode name, produce the corresponding source name.
+ * The bytecode name must not contain dangerous characters.
+ * In particular, it must not be qualified or segmented by colon {@code ':'}.
+ * @param s the bytecode name
+ * @return the source name, which may possibly have unsafe characters
+ * @throws IllegalArgumentException if the bytecode name is not {@link #isSafeBytecodeName safe}
+ * @see #isSafeBytecodeName(java.lang.String)
+ */
+ public static String toSourceName(String s) {
+ checkSafeBytecodeName(s);
+ String sn = s;
+ if (looksMangled(s)) {
+ sn = demangle(s);
+ assert(s.equals(mangle(sn))) : s+" => "+sn+" => "+mangle(sn);
+ }
+ return sn;
+ }
+
+ /**
+ * Given a bytecode name from a classfile, separate it into
+ * components delimited by dangerous characters.
+ * Each resulting array element will be either a dangerous character,
+ * or else a safe bytecode name.
+ * (The safe name might possibly be mangled to hide further dangerous characters.)
+ * For example, the qualified class name {@code java/lang/String}
+ * will be parsed into the array {@code {"java", '/', "lang", '/', "String"}}.
+ * The name {@code <init>} will be parsed into { '<', "init", '>'}}
+ * The name {@code foo/bar$:baz} will be parsed into
+ * {@code {"foo", '/', "bar", '$', ':', "baz"}}.
+ * The name {@code ::\=:foo:\=bar\!baz} will be parsed into
+ * {@code {':', ':', "", ':', "foo", ':', "bar:baz"}}.
+ */
+ public static Object[] parseBytecodeName(String s) {
+ int slen = s.length();
+ Object[] res = null;
+ for (int pass = 0; pass <= 1; pass++) {
+ int fillp = 0;
+ int lasti = 0;
+ for (int i = 0; i <= slen; i++) {
+ int whichDC = -1;
+ if (i < slen) {
+ whichDC = DANGEROUS_CHARS.indexOf(s.charAt(i));
+ if (whichDC < DANGEROUS_CHAR_FIRST_INDEX) continue;
+ }
+ // got to end of string or next dangerous char
+ if (lasti < i) {
+ // normal component
+ if (pass != 0)
+ res[fillp] = toSourceName(s.substring(lasti, i));
+ fillp++;
+ lasti = i+1;
+ }
+ if (whichDC >= DANGEROUS_CHAR_FIRST_INDEX) {
+ if (pass != 0)
+ res[fillp] = DANGEROUS_CHARS_CA[whichDC];
+ fillp++;
+ lasti = i+1;
+ }
+ }
+ if (pass != 0) break;
+ // between passes, build the result array
+ res = new Object[fillp];
+ if (fillp <= 1 && lasti == 0) {
+ if (fillp != 0) res[0] = toSourceName(s);
+ break;
+ }
+ }
+ return res;
+ }
+
+ /**
+ * Given a series of components, create a bytecode name for a classfile.
+ * This is the inverse of {@link #parseBytecodeName(java.lang.String)}.
+ * Each component must either be an interned one-character string of
+ * a dangerous character, or else a safe bytecode name.
+ * @param components a series of name components
+ * @return the concatenation of all components
+ * @throws IllegalArgumentException if any component contains an unsafe
+ * character, and is not an interned one-character string
+ * @throws NullPointerException if any component is null
+ */
+ public static String unparseBytecodeName(Object[] components) {
+ Object[] components0 = components;
+ for (int i = 0; i < components.length; i++) {
+ Object c = components[i];
+ if (c instanceof String) {
+ String mc = toBytecodeName((String) c);
+ if (i == 0 && components.length == 1)
+ return mc; // usual case
+ if ((Object)mc != c) {
+ if (components == components0)
+ components = components.clone();
+ components[i] = c = mc;
+ }
+ }
+ }
+ return appendAll(components);
+ }
+ private static String appendAll(Object[] components) {
+ if (components.length <= 1) {
+ if (components.length == 1) {
+ return String.valueOf(components[0]);
+ }
+ return "";
+ }
+ int slen = 0;
+ for (Object c : components) {
+ if (c instanceof String)
+ slen += String.valueOf(c).length();
+ else
+ slen += 1;
+ }
+ StringBuilder sb = new StringBuilder(slen);
+ for (Object c : components) {
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Given a bytecode name, produce the corresponding display name.
+ * This is the source name, plus quotes if needed.
+ * If the bytecode name contains dangerous characters,
+ * assume that they are being used as punctuation,
+ * and pass them through unchanged.
+ * Non-empty runs of non-dangerous characters are demangled
+ * if necessary, and the resulting names are quoted if
+ * they are not already valid Java identifiers, or if
+ * they contain a dangerous character (i.e., dollar sign "$").
+ * Single quotes are used when quoting.
+ * Within quoted names, embedded single quotes and backslashes
+ * are further escaped by prepended backslashes.
+ *
+ * @param s the original bytecode name (which may be qualified)
+ * @return a human-readable presentation
+ */
+ public static String toDisplayName(String s) {
+ Object[] components = parseBytecodeName(s);
+ for (int i = 0; i < components.length; i++) {
+ if (!(components[i] instanceof String))
+ continue;
+ String sn = (String) components[i];
+ // note that the name is already demangled!
+ //sn = toSourceName(sn);
+ if (!isJavaIdent(sn) || sn.indexOf('$') >=0 ) {
+ components[i] = quoteDisplay(sn);
+ }
+ }
+ return appendAll(components);
+ }
+ private static boolean isJavaIdent(String s) {
+ int slen = s.length();
+ if (slen == 0) return false;
+ if (!Character.isJavaIdentifierStart(s.charAt(0)))
+ return false;
+ for (int i = 1; i < slen; i++) {
+ if (!Character.isJavaIdentifierPart(s.charAt(i)))
+ return false;
+ }
+ return true;
+ }
+ private static String quoteDisplay(String s) {
+ // TO DO: Replace wierd characters in s by C-style escapes.
+ return "'"+s.replaceAll("['\\\\]", "\\\\$0")+"'";
+ }
+
+ private static void checkSafeBytecodeName(String s)
+ throws IllegalArgumentException {
+ if (!isSafeBytecodeName(s)) {
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Report whether a simple name is safe as a bytecode name.
+ * Such names are acceptable in class files as class, method, and field names.
+ * Additionally, they are free of "dangerous" characters, even if those
+ * characters are legal in some (or all) names in class files.
+ * @param s the proposed bytecode name
+ * @return true if the name is non-empty and all of its characters are safe
+ */
+ public static boolean isSafeBytecodeName(String s) {
+ if (s.length() == 0) return false;
+ // check occurrences of each DANGEROUS char
+ for (char xc : DANGEROUS_CHARS_A) {
+ if (xc == ESCAPE_C) continue; // not really that dangerous
+ if (s.indexOf(xc) >= 0) return false;
+ }
+ return true;
+ }
+
+ /**
+ * Report whether a character is safe in a bytecode name.
+ * This is true of any unicode character except the following
+ * <em>dangerous characters</em>: {@code ".;:$[]<>/"}.
+ * @param s the proposed character
+ * @return true if the character is safe to use in classfiles
+ */
+ public static boolean isSafeBytecodeChar(char c) {
+ return DANGEROUS_CHARS.indexOf(c) < DANGEROUS_CHAR_FIRST_INDEX;
+ }
+
+ private static boolean looksMangled(String s) {
+ return s.charAt(0) == ESCAPE_C;
+ }
+
+ private static String mangle(String s) {
+ if (s.length() == 0)
+ return NULL_ESCAPE;
+
+ // build this lazily, when we first need an escape:
+ StringBuilder sb = null;
+
+ for (int i = 0, slen = s.length(); i < slen; i++) {
+ char c = s.charAt(i);
+
+ boolean needEscape = false;
+ if (c == ESCAPE_C) {
+ if (i+1 < slen) {
+ char c1 = s.charAt(i+1);
+ if ((i == 0 && c1 == NULL_ESCAPE_C)
+ || c1 != originalOfReplacement(c1)) {
+ // an accidental escape
+ needEscape = true;
+ }
+ }
+ } else {
+ needEscape = isDangerous(c);
+ }
+
+ if (!needEscape) {
+ if (sb != null) sb.append(c);
+ continue;
+ }
+
+ // build sb if this is the first escape
+ if (sb == null) {
+ sb = new StringBuilder(s.length()+10);
+ // mangled names must begin with a backslash:
+ if (s.charAt(0) != ESCAPE_C && i > 0)
+ sb.append(NULL_ESCAPE);
+ // append the string so far, which is unremarkable:
+ sb.append(s.substring(0, i));
+ }
+
+ // rewrite \ to \-, / to \|, etc.
+ sb.append(ESCAPE_C);
+ sb.append(replacementOf(c));
+ }
+
+ if (sb != null) return sb.toString();
+
+ return s;
+ }
+
+ private static String demangle(String s) {
+ // build this lazily, when we first meet an escape:
+ StringBuilder sb = null;
+
+ int stringStart = 0;
+ if (s.startsWith(NULL_ESCAPE))
+ stringStart = 2;
+
+ for (int i = stringStart, slen = s.length(); i < slen; i++) {
+ char c = s.charAt(i);
+
+ if (c == ESCAPE_C && i+1 < slen) {
+ // might be an escape sequence
+ char rc = s.charAt(i+1);
+ char oc = originalOfReplacement(rc);
+ if (oc != rc) {
+ // build sb if this is the first escape
+ if (sb == null) {
+ sb = new StringBuilder(s.length());
+ // append the string so far, which is unremarkable:
+ sb.append(s.substring(stringStart, i));
+ }
+ ++i; // skip both characters
+ c = oc;
+ }
+ }
+
+ if (sb != null)
+ sb.append(c);
+ }
+
+ if (sb != null) return sb.toString();
+
+ return s.substring(stringStart);
+ }
+
+ static char ESCAPE_C = '\\';
+ // empty escape sequence to avoid a null name or illegal prefix
+ static char NULL_ESCAPE_C = '=';
+ static String NULL_ESCAPE = ESCAPE_C+""+NULL_ESCAPE_C;
+
+ static final String DANGEROUS_CHARS = "\\/.;:$[]<>"; // \\ must be first
+ static final String REPLACEMENT_CHARS = "-|,?!%{}^_";
+ static final int DANGEROUS_CHAR_FIRST_INDEX = 1; // index after \\
+ static char[] DANGEROUS_CHARS_A = DANGEROUS_CHARS.toCharArray();
+ static char[] REPLACEMENT_CHARS_A = REPLACEMENT_CHARS.toCharArray();
+ static final Character[] DANGEROUS_CHARS_CA;
+ static {
+ Character[] dcca = new Character[DANGEROUS_CHARS.length()];
+ for (int i = 0; i < dcca.length; i++)
+ dcca[i] = Character.valueOf(DANGEROUS_CHARS.charAt(i));
+ DANGEROUS_CHARS_CA = dcca;
+ }
+
+ static final long[] SPECIAL_BITMAP = new long[2]; // 128 bits
+ static {
+ String SPECIAL = DANGEROUS_CHARS + REPLACEMENT_CHARS;
+ //System.out.println("SPECIAL = "+SPECIAL);
+ for (char c : SPECIAL.toCharArray()) {
+ SPECIAL_BITMAP[c >>> 6] |= 1L << c;
+ }
+ }
+ static boolean isSpecial(char c) {
+ if ((c >>> 6) < SPECIAL_BITMAP.length)
+ return ((SPECIAL_BITMAP[c >>> 6] >> c) & 1) != 0;
+ else
+ return false;
+ }
+ static char replacementOf(char c) {
+ if (!isSpecial(c)) return c;
+ int i = DANGEROUS_CHARS.indexOf(c);
+ if (i < 0) return c;
+ return REPLACEMENT_CHARS.charAt(i);
+ }
+ static char originalOfReplacement(char c) {
+ if (!isSpecial(c)) return c;
+ int i = REPLACEMENT_CHARS.indexOf(c);
+ if (i < 0) return c;
+ return DANGEROUS_CHARS.charAt(i);
+ }
+ static boolean isDangerous(char c) {
+ if (!isSpecial(c)) return false;
+ return (DANGEROUS_CHARS.indexOf(c) >= DANGEROUS_CHAR_FIRST_INDEX);
+ }
+ static int indexOfDangerousChar(String s, int from) {
+ for (int i = from, slen = s.length(); i < slen; i++) {
+ if (isDangerous(s.charAt(i)))
+ return i;
+ }
+ return -1;
+ }
+ static int lastIndexOfDangerousChar(String s, int from) {
+ for (int i = Math.min(from, s.length()-1); i >= 0; i--) {
+ if (isDangerous(s.charAt(i)))
+ return i;
+ }
+ return -1;
+ }
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,817 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.List;
+
+public class ValueConversions {
+ private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
+
+ private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
+ @SuppressWarnings("unchecked")
+ EnumMap<Wrapper, MethodHandle>[] caches
+ = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap[n]; // unchecked warning expected here
+ for (int i = 0; i < n; i++)
+ caches[i] = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
+ return caches;
+ }
+
+ /// Converting references to values.
+
+ static int unboxInteger(Object x) {
+ if (x == null) return 0; // never NPE
+ return ((Integer) x).intValue();
+ }
+
+ static byte unboxByte(Object x) {
+ if (x == null) return 0; // never NPE
+ return ((Byte) x).byteValue();
+ }
+
+ static short unboxShort(Object x) {
+ if (x == null) return 0; // never NPE
+ return ((Short) x).shortValue();
+ }
+
+ static boolean unboxBoolean(Object x) {
+ if (x == null) return false; // never NPE
+ return ((Boolean) x).booleanValue();
+ }
+
+ static char unboxCharacter(Object x) {
+ if (x == null) return 0; // never NPE
+ return ((Character) x).charValue();
+ }
+
+ static long unboxLong(Object x) {
+ if (x == null) return 0; // never NPE
+ return ((Long) x).longValue();
+ }
+
+ static float unboxFloat(Object x) {
+ if (x == null) return 0; // never NPE
+ return ((Float) x).floatValue();
+ }
+
+ static double unboxDouble(Object x) {
+ if (x == null) return 0; // never NPE
+ return ((Double) x).doubleValue();
+ }
+
+ /// Converting references to "raw" values.
+ /// A raw primitive value is always an int or long.
+
+ static int unboxByteRaw(Object x) {
+ return unboxByte(x);
+ }
+
+ static int unboxShortRaw(Object x) {
+ return unboxShort(x);
+ }
+
+ static int unboxBooleanRaw(Object x) {
+ return unboxBoolean(x) ? 1 : 0;
+ }
+
+ static int unboxCharacterRaw(Object x) {
+ return unboxCharacter(x);
+ }
+
+ static int unboxFloatRaw(Object x) {
+ return Float.floatToIntBits(unboxFloat(x));
+ }
+
+ static long unboxDoubleRaw(Object x) {
+ return Double.doubleToRawLongBits(unboxDouble(x));
+ }
+
+ private static MethodType unboxType(Wrapper wrap, boolean raw) {
+ return MethodType.methodType(rawWrapper(wrap, raw).primitiveType(), wrap.wrapperType());
+ }
+
+ private static final EnumMap<Wrapper, MethodHandle>[]
+ UNBOX_CONVERSIONS = newWrapperCaches(4);
+
+ private static MethodHandle unbox(Wrapper wrap, boolean exact, boolean raw) {
+ EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
+ MethodHandle mh = cache.get(wrap);
+ if (mh != null) {
+ return mh;
+ }
+ // slow path
+ switch (wrap) {
+ case OBJECT:
+ mh = IDENTITY; break;
+ case VOID:
+ mh = raw ? ALWAYS_ZERO : IGNORE; break;
+ case INT: case LONG:
+ // these guys don't need separate raw channels
+ if (raw) mh = unbox(wrap, exact, false);
+ break;
+ }
+ if (mh != null) {
+ cache.put(wrap, mh);
+ return mh;
+ }
+ // look up the method
+ String name = "unbox" + wrap.simpleName() + (raw ? "Raw" : "");
+ MethodType type = unboxType(wrap, raw);
+ if (!exact) {
+ try {
+ // actually, type is wrong; the Java method takes Object
+ mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type.erase());
+ } catch (ReflectiveOperationException ex) {
+ mh = null;
+ }
+ } else {
+ mh = unbox(wrap, !exact, raw).asType(type);
+ }
+ if (mh != null) {
+ cache.put(wrap, mh);
+ return mh;
+ }
+ throw new IllegalArgumentException("cannot find unbox adapter for " + wrap + (raw ? " (raw)" : ""));
+ }
+
+ public static MethodHandle unbox(Wrapper type, boolean exact) {
+ return unbox(type, exact, false);
+ }
+
+ public static MethodHandle unboxRaw(Wrapper type, boolean exact) {
+ return unbox(type, exact, true);
+ }
+
+ public static MethodHandle unbox(Class<?> type, boolean exact) {
+ return unbox(Wrapper.forPrimitiveType(type), exact, false);
+ }
+
+ public static MethodHandle unboxRaw(Class<?> type, boolean exact) {
+ return unbox(Wrapper.forPrimitiveType(type), exact, true);
+ }
+
+ /// Converting primitives to references
+
+ static Integer boxInteger(int x) {
+ return x;
+ }
+
+ static Byte boxByte(byte x) {
+ return x;
+ }
+
+ static Short boxShort(short x) {
+ return x;
+ }
+
+ static Boolean boxBoolean(boolean x) {
+ return x;
+ }
+
+ static Character boxCharacter(char x) {
+ return x;
+ }
+
+ static Long boxLong(long x) {
+ return x;
+ }
+
+ static Float boxFloat(float x) {
+ return x;
+ }
+
+ static Double boxDouble(double x) {
+ return x;
+ }
+
+ /// Converting raw primitives to references
+
+ static Byte boxByteRaw(int x) {
+ return boxByte((byte)x);
+ }
+
+ static Short boxShortRaw(int x) {
+ return boxShort((short)x);
+ }
+
+ static Boolean boxBooleanRaw(int x) {
+ return boxBoolean(x != 0);
+ }
+
+ static Character boxCharacterRaw(int x) {
+ return boxCharacter((char)x);
+ }
+
+ static Float boxFloatRaw(int x) {
+ return boxFloat(Float.intBitsToFloat(x));
+ }
+
+ static Double boxDoubleRaw(long x) {
+ return boxDouble(Double.longBitsToDouble(x));
+ }
+
+ // a raw void value is (arbitrarily) a garbage int
+ static Void boxVoidRaw(int x) {
+ return null;
+ }
+
+ private static MethodType boxType(Wrapper wrap, boolean raw) {
+ // be exact, since return casts are hard to compose
+ Class<?> boxType = wrap.wrapperType();
+ return MethodType.methodType(boxType, rawWrapper(wrap, raw).primitiveType());
+ }
+
+ private static Wrapper rawWrapper(Wrapper wrap, boolean raw) {
+ if (raw) return wrap.isDoubleWord() ? Wrapper.LONG : Wrapper.INT;
+ return wrap;
+ }
+
+ private static final EnumMap<Wrapper, MethodHandle>[]
+ BOX_CONVERSIONS = newWrapperCaches(4);
+
+ private static MethodHandle box(Wrapper wrap, boolean exact, boolean raw) {
+ EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)+(raw?2:0)];
+ MethodHandle mh = cache.get(wrap);
+ if (mh != null) {
+ return mh;
+ }
+ // slow path
+ switch (wrap) {
+ case OBJECT:
+ mh = IDENTITY; break;
+ case VOID:
+ if (!raw) mh = ZERO_OBJECT;
+ break;
+ case INT: case LONG:
+ // these guys don't need separate raw channels
+ if (raw) mh = box(wrap, exact, false);
+ break;
+ }
+ if (mh != null) {
+ cache.put(wrap, mh);
+ return mh;
+ }
+ // look up the method
+ String name = "box" + wrap.simpleName() + (raw ? "Raw" : "");
+ MethodType type = boxType(wrap, raw);
+ if (exact) {
+ try {
+ mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
+ } catch (ReflectiveOperationException ex) {
+ mh = null;
+ }
+ } else {
+ mh = box(wrap, !exact, raw).asType(type.erase());
+ }
+ if (mh != null) {
+ cache.put(wrap, mh);
+ return mh;
+ }
+ throw new IllegalArgumentException("cannot find box adapter for " + wrap + (raw ? " (raw)" : ""));
+ }
+
+ public static MethodHandle box(Class<?> type, boolean exact) {
+ return box(Wrapper.forPrimitiveType(type), exact, false);
+ }
+
+ public static MethodHandle boxRaw(Class<?> type, boolean exact) {
+ return box(Wrapper.forPrimitiveType(type), exact, true);
+ }
+
+ public static MethodHandle box(Wrapper type, boolean exact) {
+ return box(type, exact, false);
+ }
+
+ public static MethodHandle boxRaw(Wrapper type, boolean exact) {
+ return box(type, exact, true);
+ }
+
+ /// Kludges for when raw values get accidentally boxed.
+
+ static int unboxRawInteger(Object x) {
+ if (x instanceof Integer)
+ return unboxInteger(x);
+ else
+ return (int) unboxLong(x);
+ }
+
+ static Integer reboxRawInteger(Object x) {
+ if (x instanceof Integer)
+ return (Integer) x;
+ else
+ return (int) unboxLong(x);
+ }
+
+ static Byte reboxRawByte(Object x) {
+ if (x instanceof Byte) return (Byte) x;
+ return boxByteRaw(unboxRawInteger(x));
+ }
+
+ static Short reboxRawShort(Object x) {
+ if (x instanceof Short) return (Short) x;
+ return boxShortRaw(unboxRawInteger(x));
+ }
+
+ static Boolean reboxRawBoolean(Object x) {
+ if (x instanceof Boolean) return (Boolean) x;
+ return boxBooleanRaw(unboxRawInteger(x));
+ }
+
+ static Character reboxRawCharacter(Object x) {
+ if (x instanceof Character) return (Character) x;
+ return boxCharacterRaw(unboxRawInteger(x));
+ }
+
+ static Float reboxRawFloat(Object x) {
+ if (x instanceof Float) return (Float) x;
+ return boxFloatRaw(unboxRawInteger(x));
+ }
+
+ static Long reboxRawLong(Object x) {
+ return (Long) x; //never a rebox
+ }
+
+ static Double reboxRawDouble(Object x) {
+ if (x instanceof Double) return (Double) x;
+ return boxDoubleRaw(unboxLong(x));
+ }
+
+ private static MethodType reboxType(Wrapper wrap) {
+ Class<?> boxType = wrap.wrapperType();
+ return MethodType.methodType(boxType, Object.class);
+ }
+
+ private static final EnumMap<Wrapper, MethodHandle>[]
+ REBOX_CONVERSIONS = newWrapperCaches(2);
+
+ /**
+ * Because we normalize primitive types to reduce the number of signatures,
+ * primitives are sometimes manipulated under an "erased" type,
+ * either int (for types other than long/double) or long (for all types).
+ * When the erased primitive value is then boxed into an Integer or Long,
+ * the final boxed primitive is sometimes required. This transformation
+ * is called a "rebox". It takes an Integer or Long and produces some
+ * other boxed value.
+ */
+ public static MethodHandle rebox(Wrapper wrap, boolean exact) {
+ EnumMap<Wrapper, MethodHandle> cache = REBOX_CONVERSIONS[exact?1:0];
+ MethodHandle mh = cache.get(wrap);
+ if (mh != null) {
+ return mh;
+ }
+ // slow path
+ switch (wrap) {
+ case OBJECT:
+ mh = IDENTITY; break;
+ case VOID:
+ throw new IllegalArgumentException("cannot rebox a void");
+ }
+ if (mh != null) {
+ cache.put(wrap, mh);
+ return mh;
+ }
+ // look up the method
+ String name = "reboxRaw" + wrap.simpleName();
+ MethodType type = reboxType(wrap);
+ if (exact) {
+ try {
+ mh = IMPL_LOOKUP.findStatic(ValueConversions.class, name, type);
+ } catch (ReflectiveOperationException ex) {
+ mh = null;
+ }
+ } else {
+ mh = rebox(wrap, !exact).asType(IDENTITY.type());
+ }
+ if (mh != null) {
+ cache.put(wrap, mh);
+ return mh;
+ }
+ throw new IllegalArgumentException("cannot find rebox adapter for " + wrap);
+ }
+
+ public static MethodHandle rebox(Class<?> type, boolean exact) {
+ return rebox(Wrapper.forPrimitiveType(type), exact);
+ }
+
+ /// Width-changing conversions between int and long.
+
+ static long widenInt(int x) {
+ return (long) x;
+ }
+
+ static Long widenBoxedInt(Integer x) {
+ return (long)(int)x;
+ }
+
+ static int narrowLong(long x) {
+ return (int) x;
+ }
+
+ static Integer narrowBoxedLong(Long x) {
+ return (int)(long) x;
+ }
+
+ /// Constant functions
+
+ static void ignore(Object x) {
+ // no value to return; this is an unbox of null
+ return;
+ }
+
+ static void empty() {
+ return;
+ }
+
+ static Object zeroObject() {
+ return null;
+ }
+
+ static int zeroInteger() {
+ return 0;
+ }
+
+ static long zeroLong() {
+ return 0;
+ }
+
+ static float zeroFloat() {
+ return 0;
+ }
+
+ static double zeroDouble() {
+ return 0;
+ }
+
+ private static final EnumMap<Wrapper, MethodHandle>[]
+ CONSTANT_FUNCTIONS = newWrapperCaches(2);
+
+ public static MethodHandle zeroConstantFunction(Wrapper wrap) {
+ EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
+ MethodHandle mh = cache.get(wrap);
+ if (mh != null) {
+ return mh;
+ }
+ // slow path
+ MethodType type = MethodType.methodType(wrap.primitiveType());
+ switch (wrap) {
+ case VOID:
+ mh = EMPTY;
+ break;
+ case INT: case LONG: case FLOAT: case DOUBLE:
+ try {
+ mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "zero"+wrap.simpleName(), type);
+ } catch (ReflectiveOperationException ex) {
+ mh = null;
+ }
+ break;
+ }
+ if (mh != null) {
+ cache.put(wrap, mh);
+ return mh;
+ }
+
+ // use the raw method
+ Wrapper rawWrap = wrap.rawPrimitive();
+ if (mh == null && rawWrap != wrap) {
+ mh = MethodHandles.explicitCastArguments(zeroConstantFunction(rawWrap), type);
+ }
+ if (mh != null) {
+ cache.put(wrap, mh);
+ return mh;
+ }
+ throw new IllegalArgumentException("cannot find zero constant for " + wrap);
+ }
+
+ /// Converting references to references.
+
+ /**
+ * Value-killing function.
+ * @param x an arbitrary reference value
+ * @return a null
+ */
+ static Object alwaysNull(Object x) {
+ return null;
+ }
+
+ /**
+ * Value-killing function.
+ * @param x an arbitrary reference value
+ * @return a zero
+ */
+ static int alwaysZero(Object x) {
+ return 0;
+ }
+
+ /**
+ * Identity function.
+ * @param x an arbitrary reference value
+ * @return the same value x
+ */
+ static <T> T identity(T x) {
+ return x;
+ }
+
+ /**
+ * Identity function on ints.
+ * @param x an arbitrary int value
+ * @return the same value x
+ */
+ static int identity(int x) {
+ return x;
+ }
+
+ static byte identity(byte x) {
+ return x;
+ }
+
+ static short identity(short x) {
+ return x;
+ }
+
+ static boolean identity(boolean x) {
+ return x;
+ }
+
+ static char identity(char x) {
+ return x;
+ }
+
+ /**
+ * Identity function on longs.
+ * @param x an arbitrary long value
+ * @return the same value x
+ */
+ static long identity(long x) {
+ return x;
+ }
+
+ static float identity(float x) {
+ return x;
+ }
+
+ static double identity(double x) {
+ return x;
+ }
+
+ /**
+ * Identity function, with reference cast.
+ * @param t an arbitrary reference type
+ * @param x an arbitrary reference value
+ * @return the same value x
+ */
+ static <T,U> T castReference(Class<? extends T> t, U x) {
+ return t.cast(x);
+ }
+
+ private static final MethodHandle IDENTITY, IDENTITY_I, IDENTITY_J, CAST_REFERENCE, ALWAYS_NULL, ALWAYS_ZERO, ZERO_OBJECT, IGNORE, EMPTY;
+ static {
+ try {
+ MethodType idType = MethodType.genericMethodType(1);
+ MethodType castType = idType.insertParameterTypes(0, Class.class);
+ MethodType alwaysZeroType = idType.changeReturnType(int.class);
+ MethodType ignoreType = idType.changeReturnType(void.class);
+ MethodType zeroObjectType = MethodType.genericMethodType(0);
+ IDENTITY = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", idType);
+ IDENTITY_I = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(int.class, int.class));
+ IDENTITY_J = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", MethodType.methodType(long.class, long.class));
+ //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
+ CAST_REFERENCE = IMPL_LOOKUP.findStatic(ValueConversions.class, "castReference", castType);
+ ALWAYS_NULL = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysNull", idType);
+ ALWAYS_ZERO = IMPL_LOOKUP.findStatic(ValueConversions.class, "alwaysZero", alwaysZeroType);
+ ZERO_OBJECT = IMPL_LOOKUP.findStatic(ValueConversions.class, "zeroObject", zeroObjectType);
+ IGNORE = IMPL_LOOKUP.findStatic(ValueConversions.class, "ignore", ignoreType);
+ EMPTY = IMPL_LOOKUP.findStatic(ValueConversions.class, "empty", ignoreType.dropParameterTypes(0, 1));
+ } catch (Exception ex) {
+ Error err = new InternalError("uncaught exception");
+ err.initCause(ex);
+ throw err;
+ }
+ }
+
+ private static final EnumMap<Wrapper, MethodHandle> WRAPPER_CASTS
+ = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
+
+ private static final EnumMap<Wrapper, MethodHandle> EXACT_WRAPPER_CASTS
+ = new EnumMap<Wrapper, MethodHandle>(Wrapper.class);
+
+ /** Return a method that casts its sole argument (an Object) to the given type
+ * and returns it as the given type (if exact is true), or as plain Object (if erase is true).
+ */
+ public static MethodHandle cast(Class<?> type, boolean exact) {
+ if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type);
+ MethodHandle mh = null;
+ Wrapper wrap = null;
+ EnumMap<Wrapper, MethodHandle> cache = null;
+ if (Wrapper.isWrapperType(type)) {
+ wrap = Wrapper.forWrapperType(type);
+ cache = (exact ? EXACT_WRAPPER_CASTS : WRAPPER_CASTS);
+ mh = cache.get(wrap);
+ if (mh != null) return mh;
+ }
+ if (VerifyType.isNullReferenceConversion(Object.class, type))
+ mh = IDENTITY;
+ else if (VerifyType.isNullType(type))
+ mh = ALWAYS_NULL;
+ else
+ mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
+ if (exact) {
+ MethodType xmt = MethodType.methodType(type, Object.class);
+ mh = MethodHandles.explicitCastArguments(mh, xmt);
+ //mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh);
+ }
+ if (cache != null)
+ cache.put(wrap, mh);
+ return mh;
+ }
+
+ public static MethodHandle identity() {
+ return IDENTITY;
+ }
+
+ public static MethodHandle identity(Class<?> type) {
+ // This stuff has been moved into MethodHandles:
+ return MethodHandles.identity(type);
+ }
+
+ public static MethodHandle identity(Wrapper wrap) {
+ EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
+ MethodHandle mh = cache.get(wrap);
+ if (mh != null) {
+ return mh;
+ }
+ // slow path
+ MethodType type = MethodType.methodType(wrap.primitiveType());
+ if (wrap != Wrapper.VOID)
+ type = type.appendParameterTypes(wrap.primitiveType());
+ try {
+ mh = IMPL_LOOKUP.findStatic(ValueConversions.class, "identity", type);
+ } catch (ReflectiveOperationException ex) {
+ mh = null;
+ }
+ if (mh == null && wrap == Wrapper.VOID) {
+ mh = EMPTY; // #(){} : #()void
+ }
+ if (mh != null) {
+ cache.put(wrap, mh);
+ return mh;
+ }
+
+ if (mh != null) {
+ cache.put(wrap, mh);
+ return mh;
+ }
+ throw new IllegalArgumentException("cannot find identity for " + wrap);
+ }
+
+ private static final Object[] NO_ARGS_ARRAY = {};
+ private static Object[] makeArray(Object... args) { return args; }
+ private static Object[] array() { return NO_ARGS_ARRAY; }
+ private static Object[] array(Object a0)
+ { return makeArray(a0); }
+ private static Object[] array(Object a0, Object a1)
+ { return makeArray(a0, a1); }
+ private static Object[] array(Object a0, Object a1, Object a2)
+ { return makeArray(a0, a1, a2); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3)
+ { return makeArray(a0, a1, a2, a3); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4)
+ { return makeArray(a0, a1, a2, a3, a4); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5)
+ { return makeArray(a0, a1, a2, a3, a4, a5); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6)
+ { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7)
+ { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8)
+ { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9)
+ { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ static MethodHandle[] makeArrays() {
+ ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
+ MethodHandles.Lookup lookup = IMPL_LOOKUP;
+ for (;;) {
+ int nargs = arrays.size();
+ MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class);
+ String name = "array";
+ MethodHandle array = null;
+ try {
+ array = lookup.findStatic(ValueConversions.class, name, type);
+ } catch (ReflectiveOperationException ex) {
+ }
+ if (array == null) break;
+ arrays.add(array);
+ }
+ assert(arrays.size() == 11); // current number of methods
+ return arrays.toArray(new MethodHandle[0]);
+ }
+ static final MethodHandle[] ARRAYS = makeArrays();
+
+ /** Return a method handle that takes the indicated number of Object
+ * arguments and returns an Object array of them, as if for varargs.
+ */
+ public static MethodHandle varargsArray(int nargs) {
+ if (nargs < ARRAYS.length)
+ return ARRAYS[nargs];
+ // else need to spin bytecode or do something else fancy
+ throw new UnsupportedOperationException("NYI: cannot form a varargs array of length "+nargs);
+ }
+
+ private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
+ private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
+ private static List<Object> list() { return NO_ARGS_LIST; }
+ private static List<Object> list(Object a0)
+ { return makeList(a0); }
+ private static List<Object> list(Object a0, Object a1)
+ { return makeList(a0, a1); }
+ private static List<Object> list(Object a0, Object a1, Object a2)
+ { return makeList(a0, a1, a2); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
+ { return makeList(a0, a1, a2, a3); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4)
+ { return makeList(a0, a1, a2, a3, a4); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5)
+ { return makeList(a0, a1, a2, a3, a4, a5); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6)
+ { return makeList(a0, a1, a2, a3, a4, a5, a6); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7)
+ { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8)
+ { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9)
+ { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ static MethodHandle[] makeLists() {
+ ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
+ MethodHandles.Lookup lookup = IMPL_LOOKUP;
+ for (;;) {
+ int nargs = arrays.size();
+ MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
+ String name = "list";
+ MethodHandle array = null;
+ try {
+ array = lookup.findStatic(ValueConversions.class, name, type);
+ } catch (ReflectiveOperationException ex) {
+ }
+ if (array == null) break;
+ arrays.add(array);
+ }
+ assert(arrays.size() == 11); // current number of methods
+ return arrays.toArray(new MethodHandle[0]);
+ }
+ static final MethodHandle[] LISTS = makeLists();
+
+ /** Return a method handle that takes the indicated number of Object
+ * arguments and returns List.
+ */
+ public static MethodHandle varargsList(int nargs) {
+ if (nargs < LISTS.length)
+ return LISTS[nargs];
+ // else need to spin bytecode or do something else fancy
+ throw new UnsupportedOperationException("NYI");
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/VerifyAccess.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+import java.lang.reflect.Modifier;
+import static java.lang.reflect.Modifier.*;
+
+/**
+ * This class centralizes information about the JVM's linkage access control.
+ * @author jrose
+ */
+public class VerifyAccess {
+
+ private VerifyAccess() { } // cannot instantiate
+
+ private static final int PACKAGE_ONLY = 0;
+ private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
+ private static final boolean ALLOW_NESTMATE_ACCESS = false;
+
+ /**
+ * Evaluate the JVM linkage rules for access to the given method
+ * on behalf of a caller class which proposes to perform the access.
+ * Return true if the caller class has privileges to invoke a method
+ * or access a field with the given properties.
+ * This requires an accessibility check of the referencing class,
+ * plus an accessibility check of the member within the class,
+ * which depends on the member's modifier flags.
+ * <p>
+ * The relevant properties include the defining class ({@code defc})
+ * of the member, and its modifier flags ({@code mods}).
+ * Also relevant is the class used to make the initial symbolic reference
+ * to the member ({@code refc}). If this latter class is not distinguished,
+ * the defining class should be passed for both arguments ({@code defc == refc}).
+ * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
+ * A field or method R is accessible to a class or interface D if
+ * and only if any of the following conditions is true:<ul>
+ * <li>R is public.
+ * <li>R is protected and is declared in a class C, and D is either
+ * a subclass of C or C itself. Furthermore, if R is not
+ * static, then the symbolic reference to R must contain a
+ * symbolic reference to a class T, such that T is either a
+ * subclass of D, a superclass of D or D itself.
+ * <li>R is either protected or has default access (that is,
+ * neither public nor protected nor private), and is declared
+ * by a class in the same runtime package as D.
+ * <li>R is private and is declared in D.
+ * </ul>
+ * This discussion of access control omits a related restriction
+ * on the target of a protected field access or method invocation
+ * (the target must be of class D or a subtype of D). That
+ * requirement is checked as part of the verification process
+ * (5.4.1); it is not part of link-time access control.
+ * @param refc the class used in the symbolic reference to the proposed member
+ * @param defc the class in which the proposed member is actually defined
+ * @param mods modifier flags for the proposed member
+ * @param lookupClass the class for which the access check is being made
+ * @return true iff the the accessing class can access such a member
+ */
+ public static boolean isMemberAccessible(Class<?> refc, // symbolic ref class
+ Class<?> defc, // actual def class
+ int mods, // actual member mods
+ Class<?> lookupClass) {
+ // Usually refc and defc are the same, but if they differ, verify them both.
+ if (refc != defc) {
+ if (!isClassAccessible(refc, lookupClass)) {
+ // Note that defc is verified in the switch below.
+ return false;
+ }
+ if ((mods & (ALL_ACCESS_MODES|STATIC)) == (PROTECTED|STATIC)) {
+ // Apply the special rules for refc here.
+ if (!isRelatedClass(refc, lookupClass))
+ return isSamePackage(defc, lookupClass);
+ // If refc == defc, the call to isPublicSuperClass will do
+ // the whole job, since in that case refc (as defc) will be
+ // a superclass of the lookup class.
+ }
+ }
+ if (defc == lookupClass)
+ return true; // easy check; all self-access is OK
+ switch (mods & ALL_ACCESS_MODES) {
+ case PUBLIC:
+ if (refc != defc) return true; // already checked above
+ return isClassAccessible(refc, lookupClass);
+ case PROTECTED:
+ return isSamePackage(defc, lookupClass) || isPublicSuperClass(defc, lookupClass);
+ case PACKAGE_ONLY:
+ return isSamePackage(defc, lookupClass);
+ case PRIVATE:
+ // Loosened rules for privates follows access rules for inner classes.
+ return (ALLOW_NESTMATE_ACCESS &&
+ isSamePackageMember(defc, lookupClass));
+ default:
+ throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
+ }
+ }
+
+ static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
+ return (refc == lookupClass ||
+ refc.isAssignableFrom(lookupClass) ||
+ lookupClass.isAssignableFrom(refc));
+ }
+
+ static boolean isPublicSuperClass(Class<?> defc, Class<?> lookupClass) {
+ return isPublic(defc.getModifiers()) && defc.isAssignableFrom(lookupClass);
+ }
+
+ /**
+ * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
+ * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
+ * A class or interface C is accessible to a class or interface D
+ * if and only if either of the following conditions are true:<ul>
+ * <li>C is public.
+ * <li>C and D are members of the same runtime package.
+ * </ul>
+ * @param refc the symbolic reference class to which access is being checked (C)
+ * @param lookupClass the class performing the lookup (D)
+ */
+ public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass) {
+ int mods = refc.getModifiers();
+ if (isPublic(mods))
+ return true;
+ if (isSamePackage(lookupClass, refc))
+ return true;
+ return false;
+ }
+
+ /**
+ * Test if two classes have the same class loader and package qualifier.
+ * @param class1
+ * @param class2
+ * @return whether they are in the same package
+ */
+ public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
+ if (class1 == class2)
+ return true;
+ if (!loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
+ return false;
+ String name1 = class1.getName(), name2 = class2.getName();
+ int dot = name1.lastIndexOf('.');
+ if (dot != name2.lastIndexOf('.'))
+ return false;
+ for (int i = 0; i < dot; i++) {
+ if (name1.charAt(i) != name2.charAt(i))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Test if two classes are defined as part of the same package member (top-level class).
+ * If this is true, they can share private access with each other.
+ * @param class1
+ * @param class2
+ * @return whether they are identical or nested together
+ */
+ public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
+ if (class1 == class2)
+ return true;
+ if (!isSamePackage(class1, class2))
+ return false;
+ if (getOutermostEnclosingClass(class1) != getOutermostEnclosingClass(class2))
+ return false;
+ return true;
+ }
+
+ private static Class<?> getOutermostEnclosingClass(Class<?> c) {
+ Class<?> pkgmem = c;
+ for (Class<?> enc = c; (enc = enc.getEnclosingClass()) != null; )
+ pkgmem = enc;
+ return pkgmem;
+ }
+
+ private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2) {
+ if (loader1 == loader2 || loader1 == null || loader2 == null) {
+ return true;
+ }
+ for (ClassLoader scan1 = loader1;
+ scan1 != null; scan1 = scan1.getParent()) {
+ if (scan1 == loader2) return true;
+ }
+ for (ClassLoader scan2 = loader2;
+ scan2 != null; scan2 = scan2.getParent()) {
+ if (scan2 == loader1) return true;
+ }
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/VerifyType.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+import java.lang.invoke.MethodType;
+import sun.invoke.empty.Empty;
+
+/**
+ * This class centralizes information about the JVM verifier
+ * and its requirements about type correctness.
+ * @author jrose
+ */
+public class VerifyType {
+
+ private VerifyType() { } // cannot instantiate
+
+ /**
+ * True if a value can be stacked as the source type and unstacked as the
+ * destination type, without violating the JVM's type consistency.
+ *
+ * @param call the type of a stacked value
+ * @param recv the type by which we'd like to treat it
+ * @return whether the retyping can be done without motion or reformatting
+ */
+ public static boolean isNullConversion(Class<?> src, Class<?> dst) {
+ if (src == dst) return true;
+ // Verifier allows any interface to be treated as Object:
+ if (dst.isInterface()) dst = Object.class;
+ if (src.isInterface()) src = Object.class;
+ if (src == dst) return true; // check again
+ if (dst == void.class) return true; // drop any return value
+ if (isNullType(src)) return !dst.isPrimitive();
+ if (!src.isPrimitive()) return dst.isAssignableFrom(src);
+ // Verifier allows an int to carry byte, short, char, or even boolean:
+ if (dst == int.class) return Wrapper.forPrimitiveType(src).isSubwordOrInt();
+ return false;
+ }
+
+ /**
+ * Specialization of isNullConversion to reference types.
+
+ * @param call the type of a stacked value
+ * @param recv the reference type by which we'd like to treat it
+ * @return whether the retyping can be done without a cast
+ */
+ public static boolean isNullReferenceConversion(Class<?> src, Class<?> dst) {
+ assert(!dst.isPrimitive());
+ if (dst.isInterface()) return true; // verifier allows this
+ if (isNullType(src)) return true;
+ return dst.isAssignableFrom(src);
+ }
+
+ /**
+ * Is the given type java.lang.Null or an equivalent null-only type?
+ */
+ public static boolean isNullType(Class<?> type) {
+ if (type == null) return false;
+ return type == NULL_CLASS
+ // This one may also be used as a null type.
+ // TO DO: Decide if we really want to legitimize it here.
+ // Probably we do, unless java.lang.Null really makes it into Java 7
+ //|| type == Void.class
+ // Locally known null-only class:
+ || type == Empty.class
+ ;
+ }
+ private static final Class<?> NULL_CLASS;
+ static {
+ Class<?> nullClass = null;
+ try {
+ nullClass = Class.forName("java.lang.Null");
+ } catch (ClassNotFoundException ex) {
+ // OK, we'll cope
+ }
+ NULL_CLASS = nullClass;
+ }
+
+ /**
+ * True if a method handle can receive a call under a slightly different
+ * method type, without moving or reformatting any stack elements.
+ *
+ * @param call the type of call being made
+ * @param recv the type of the method handle receiving the call
+ * @return whether the retyping can be done without motion or reformatting
+ */
+ public static boolean isNullConversion(MethodType call, MethodType recv) {
+ if (call == recv) return true;
+ int len = call.parameterCount();
+ if (len != recv.parameterCount()) return false;
+ for (int i = 0; i < len; i++)
+ if (!isNullConversion(call.parameterType(i), recv.parameterType(i)))
+ return false;
+ return isNullConversion(recv.returnType(), call.returnType());
+ }
+
+ //TO DO: isRawConversion
+
+ /**
+ * Determine if the JVM verifier allows a value of type call to be
+ * passed to a formal parameter (or return variable) of type recv.
+ * Returns 1 if the verifier allows the types to match without conversion.
+ * Returns -1 if the types can be made to match by a JVM-supported adapter.
+ * Cases supported are:
+ * <ul><li>checkcast
+ * </li><li>conversion between any two integral types (but not floats)
+ * </li><li>unboxing from a wrapper to its corresponding primitive type
+ * </li><li>conversion in either direction between float and double
+ * </li></ul>
+ * (Autoboxing is not supported here; it must be done via Java code.)
+ * Returns 0 otherwise.
+ */
+ public static int canPassUnchecked(Class<?> src, Class<?> dst) {
+ if (src == dst)
+ return 1;
+
+ if (dst.isPrimitive()) {
+ if (dst == void.class)
+ // Return anything to a caller expecting void.
+ // This is a property of the implementation, which links
+ // return values via a register rather than via a stack push.
+ // This makes it possible to ignore cleanly.
+ return 1;
+ if (src == void.class)
+ return 0; // void-to-something?
+ if (!src.isPrimitive())
+ // Cannot pass a reference to any primitive type (exc. void).
+ return 0;
+ Wrapper sw = Wrapper.forPrimitiveType(src);
+ Wrapper dw = Wrapper.forPrimitiveType(dst);
+ if (sw.isSubwordOrInt() && dw.isSubwordOrInt()) {
+ if (sw.bitWidth() >= dw.bitWidth())
+ return -1; // truncation may be required
+ if (!dw.isSigned() && sw.isSigned())
+ return -1; // sign elimination may be required
+ }
+ if (src == float.class || dst == float.class) {
+ if (src == double.class || dst == double.class)
+ return -1; // floating conversion may be required
+ else
+ return 0; // other primitive conversions NYI
+ } else {
+ // all fixed-point conversions are supported
+ return 0;
+ }
+ } else if (src.isPrimitive()) {
+ // Cannot pass a primitive to any reference type.
+ // (Maybe allow null.class?)
+ return 0;
+ }
+
+ // Handle reference types in the rest of the block:
+
+ // The verifier treats interfaces exactly like Object.
+ if (isNullReferenceConversion(src, dst))
+ // pass any reference to object or an arb. interface
+ return 1;
+ // else it's a definite "maybe" (cast is required)
+ return -1;
+ }
+
+ public static int canPassRaw(Class<?> src, Class<?> dst) {
+ if (dst.isPrimitive()) {
+ if (dst == void.class)
+ // As above, return anything to a caller expecting void.
+ return 1;
+ if (src == void.class)
+ // Special permission for raw conversions: allow a void
+ // to be captured as a garbage int.
+ // Caller promises that the actual value will be disregarded.
+ return dst == int.class ? 1 : 0;
+ if (isNullType(src))
+ // Special permission for raw conversions: allow a null
+ // to be reinterpreted as anything. For objects, it is safe,
+ // and for primitives you get a garbage value (probably zero).
+ return 1;
+ if (!src.isPrimitive())
+ return 0;
+ Wrapper sw = Wrapper.forPrimitiveType(src);
+ Wrapper dw = Wrapper.forPrimitiveType(dst);
+ if (sw.stackSlots() == dw.stackSlots())
+ return 1; // can do a reinterpret-cast on a stacked primitive
+ if (sw.isSubwordOrInt() && dw == Wrapper.VOID)
+ return 1; // can drop an outgoing int value
+ return 0;
+ } else if (src.isPrimitive()) {
+ return 0;
+ }
+
+ // Both references.
+ if (isNullReferenceConversion(src, dst))
+ return 1;
+ return -1;
+ }
+
+ public static boolean isSpreadArgType(Class<?> spreadArg) {
+ return spreadArg.isArray();
+ }
+ public static Class<?> spreadArgElementType(Class<?> spreadArg, int i) {
+ return spreadArg.getComponentType();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/Wrapper.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,562 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.invoke.util;
+
+public enum Wrapper {
+ BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, Format.unsigned(1)),
+ // These must be in the order defined for widening primitive conversions in JLS 5.1.2
+ BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, Format.signed(8)),
+ SHORT(Short.class, short.class, 'S', (Short)(short)0, Format.signed(16)),
+ CHAR(Character.class, char.class, 'C', (Character)(char)0, Format.unsigned(16)),
+ INT(Integer.class, int.class, 'I', (Integer)(int)0, Format.signed(32)),
+ LONG(Long.class, long.class, 'J', (Long)(long)0, Format.signed(64)),
+ FLOAT(Float.class, float.class, 'F', (Float)(float)0, Format.floating(32)),
+ DOUBLE(Double.class, double.class, 'D', (Double)(double)0, Format.floating(64)),
+ //NULL(Null.class, null.class, 'N', null, Format.other(1)),
+ OBJECT(Object.class, Object.class, 'L', null, Format.other(1)),
+ // VOID must be the last type, since it is "assignable" from any other type:
+ VOID(Void.class, void.class, 'V', null, Format.other(0)),
+ ;
+
+ private final Class<?> wrapperType;
+ private final Class<?> primitiveType;
+ private final char basicTypeChar;
+ private final Object zero;
+ private final int format;
+ private final String simpleName;
+
+ private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, int format) {
+ this.wrapperType = wtype;
+ this.primitiveType = ptype;
+ this.basicTypeChar = tchar;
+ this.zero = zero;
+ this.format = format;
+ this.simpleName = wtype.getSimpleName();
+ }
+
+ private static abstract class Format {
+ static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
+ static final int
+ SIGNED = (-1) << KIND_SHIFT,
+ UNSIGNED = 0 << KIND_SHIFT,
+ FLOATING = 1 << KIND_SHIFT;
+ static final int
+ SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
+ SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
+ static int format(int kind, int size, int slots) {
+ assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
+ assert((size & (size-1)) == 0); // power of two
+ assert((kind == SIGNED) ? (size > 0) :
+ (kind == UNSIGNED) ? (size > 0) :
+ (kind == FLOATING) ? (size == 32 || size == 64) :
+ false);
+ assert((slots == 2) ? (size == 64) :
+ (slots == 1) ? (size <= 32) :
+ false);
+ return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT);
+ }
+ static final int
+ INT = SIGNED | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
+ SHORT = SIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
+ BOOLEAN = UNSIGNED | (1 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
+ CHAR = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
+ FLOAT = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
+ VOID = UNSIGNED | (0 << SIZE_SHIFT) | (0 << SLOT_SHIFT),
+ NUM_MASK = (-1) << SIZE_SHIFT;
+ static int signed(int size) { return format(SIGNED, size, (size > 32 ? 2 : 1)); }
+ static int unsigned(int size) { return format(UNSIGNED, size, (size > 32 ? 2 : 1)); }
+ static int floating(int size) { return format(FLOATING, size, (size > 32 ? 2 : 1)); }
+ static int other(int slots) { return slots << SLOT_SHIFT; }
+ }
+
+ /// format queries:
+
+ /** How many bits are in the wrapped value? Returns 0 for OBJECT or VOID. */
+ public int bitWidth() { return (format >> Format.SIZE_SHIFT) & Format.SIZE_MASK; }
+ /** How many JVM stack slots occupied by the wrapped value? Returns 0 for VOID. */
+ public int stackSlots() { return (format >> Format.SLOT_SHIFT) & Format.SLOT_MASK; }
+ /** Does the wrapped value occupy a single JVM stack slot? */
+ public boolean isSingleWord() { return (format & (1 << Format.SLOT_SHIFT)) != 0; }
+ /** Does the wrapped value occupy two JVM stack slots? */
+ public boolean isDoubleWord() { return (format & (2 << Format.SLOT_SHIFT)) != 0; }
+ /** Is the wrapped type numeric (not void or object)? */
+ public boolean isNumeric() { return (format & Format.NUM_MASK) != 0; }
+ /** Is the wrapped type a primitive other than float, double, or void? */
+ public boolean isIntegral() { return isNumeric() && format < Format.FLOAT; }
+ /** Is the wrapped type one of int, boolean, byte, char, or short? */
+ public boolean isSubwordOrInt() { return isIntegral() && isSingleWord(); }
+ /* Is the wrapped value a signed integral type (one of byte, short, int, or long)? */
+ public boolean isSigned() { return format < Format.VOID; }
+ /* Is the wrapped value an unsigned integral type (one of boolean or char)? */
+ public boolean isUnsigned() { return format >= Format.BOOLEAN && format < Format.FLOAT; }
+ /** Is the wrapped type either float or double? */
+ public boolean isFloating() { return format >= Format.FLOAT; }
+
+ /** Does the JVM verifier allow a variable of this wrapper's
+ * primitive type to be assigned from a value of the given wrapper's primitive type?
+ * Cases:
+ * <ul>
+ * <li>unboxing followed by widening primitive conversion
+ * <li>any type converted to {@code void}
+ * <li>boxing conversion followed by widening reference conversion to {@code Object}
+ * <li>conversion of {@code boolean} to any type
+ * </ul>
+ */
+ public boolean isConvertibleFrom(Wrapper source) {
+ if (this == source) return true;
+ if (this.compareTo(source) < 0) {
+ // At best, this is a narrowing conversion.
+ return false;
+ }
+ if ((this.format ^ source.format) == (Format.SHORT ^ Format.CHAR)) {
+ assert (this == SHORT && source == CHAR) || (this == CHAR && source == SHORT);
+ return false;
+ }
+ return true;
+ }
+
+ /** Produce a zero value for the given wrapper type.
+ * This will be a numeric zero for a number or character,
+ * false for a boolean, and null for a reference or void.
+ * The common thread is that this is what is contained
+ * in a default-initialized variable of the given primitive
+ * type. (For void, it is what a reflective method returns
+ * instead of no value at all.)
+ */
+ public Object zero() { return zero; }
+
+ /** Produce a zero value for the given wrapper type T.
+ * The optional argument must a type compatible with this wrapper.
+ * Equivalent to {@code this.cast(this.zero(), type)}.
+ */
+ public <T> T zero(Class<T> type) { return convert(zero, type); }
+
+// /** Produce a wrapper for the given wrapper or primitive type. */
+// public static Wrapper valueOf(Class<?> type) {
+// if (isPrimitiveType(type))
+// return forPrimitiveType(type);
+// else
+// return forWrapperType(type);
+// }
+
+ /** Return the wrapper that wraps values of the given type.
+ * The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
+ * Otherwise, the type must be a primitive.
+ * @throws IllegalArgumentException for unexpected types
+ */
+ public static Wrapper forPrimitiveType(Class<?> type) {
+ Wrapper w = findPrimitiveType(type);
+ if (w != null) return w;
+ if (type.isPrimitive())
+ throw new InternalError(); // redo hash function
+ throw newIllegalArgumentException("not primitive: "+type);
+ }
+
+ static Wrapper findPrimitiveType(Class<?> type) {
+ Wrapper w = FROM_PRIM[hashPrim(type)];
+ if (w != null && w.primitiveType == type) {
+ return w;
+ }
+ return null;
+ }
+
+ /** Return the wrapper that wraps values into the given wrapper type.
+ * If it is {@code Object} or an interface, return {@code OBJECT}.
+ * Otherwise, it must be a wrapper type.
+ * The type must not be a primitive type.
+ * @throws IllegalArgumentException for unexpected types
+ */
+ public static Wrapper forWrapperType(Class<?> type) {
+ Wrapper w = findWrapperType(type);
+ if (w != null) return w;
+ for (Wrapper x : values())
+ if (x.wrapperType == type)
+ throw new InternalError(); // redo hash function
+ throw newIllegalArgumentException("not wrapper: "+type);
+ }
+
+ static Wrapper findWrapperType(Class<?> type) {
+ Wrapper w = FROM_WRAP[hashWrap(type)];
+ if (w != null && w.wrapperType == type) {
+ return w;
+ }
+ if (type.isInterface())
+ return OBJECT;
+ return null;
+ }
+
+ /** Return the wrapper that corresponds to the given bytecode
+ * signature character. Return {@code OBJECT} for the character 'L'.
+ * @throws IllegalArgumentException for any non-signature character or {@code '['}.
+ */
+ public static Wrapper forBasicType(char type) {
+ Wrapper w = FROM_CHAR[hashChar(type)];
+ if (w != null && w.basicTypeChar == type) {
+ return w;
+ }
+ for (Wrapper x : values())
+ if (w.basicTypeChar == type)
+ throw new InternalError(); // redo hash function
+ throw newIllegalArgumentException("not basic type char: "+type);
+ }
+
+ /** Return the wrapper for the given type, if it is
+ * a primitive type, else return {@code OBJECT}.
+ */
+ public static Wrapper forBasicType(Class<?> type) {
+ if (type.isPrimitive())
+ return forPrimitiveType(type);
+ return OBJECT; // any reference, including wrappers or arrays
+ }
+
+ // Note on perfect hashes:
+ // for signature chars c, do (c + (c >> 1)) % 16
+ // for primitive type names n, do (n[0] + n[2]) % 16
+ // The type name hash works for both primitive and wrapper names.
+ // You can add "java/lang/Object" to the primitive names.
+ // But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16.
+ private static final Wrapper[] FROM_PRIM = new Wrapper[16];
+ private static final Wrapper[] FROM_WRAP = new Wrapper[16];
+ private static final Wrapper[] FROM_CHAR = new Wrapper[16];
+ private static int hashPrim(Class<?> x) {
+ String xn = x.getName();
+ if (xn.length() < 3) return 0;
+ return (xn.charAt(0) + xn.charAt(2)) % 16;
+ }
+ private static int hashWrap(Class<?> x) {
+ String xn = x.getName();
+ final int offset = 10; assert(offset == "java.lang.".length());
+ if (xn.length() < offset+3) return 0;
+ return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16;
+ }
+ private static int hashChar(char x) {
+ return (x + (x >> 1)) % 16;
+ }
+ static {
+ for (Wrapper w : values()) {
+ int pi = hashPrim(w.primitiveType);
+ int wi = hashWrap(w.wrapperType);
+ int ci = hashChar(w.basicTypeChar);
+ assert(FROM_PRIM[pi] == null);
+ assert(FROM_WRAP[wi] == null);
+ assert(FROM_CHAR[ci] == null);
+ FROM_PRIM[pi] = w;
+ FROM_WRAP[wi] = w;
+ FROM_CHAR[ci] = w;
+ }
+ //assert(jdk.sun.invoke.util.WrapperTest.test(false));
+ }
+
+ /** What is the primitive type wrapped by this wrapper? */
+ public Class<?> primitiveType() { return primitiveType; }
+
+ /** What is the wrapper type for this wrapper? */
+ public Class<?> wrapperType() { return wrapperType; }
+
+ /** What is the wrapper type for this wrapper?
+ * Otherwise, the example type must be the wrapper type,
+ * or the corresponding primitive type.
+ * (For {@code OBJECT}, the example type can be any non-primitive,
+ * and is normalized to {@code Object.class}.)
+ * The resulting class type has the same type parameter.
+ */
+ public <T> Class<T> wrapperType(Class<T> exampleType) {
+ if (exampleType == wrapperType) {
+ return exampleType;
+ } else if (exampleType == primitiveType ||
+ wrapperType == Object.class ||
+ exampleType.isInterface()) {
+ return forceType(wrapperType, exampleType);
+ }
+ throw newClassCastException(exampleType, primitiveType);
+ }
+
+ private static ClassCastException newClassCastException(Class<?> actual, Class<?> expected) {
+ return new ClassCastException(actual + " is not compatible with " + expected);
+ }
+
+ /** If {@code type} is a primitive type, return the corresponding
+ * wrapper type, else return {@code type} unchanged.
+ */
+ public static <T> Class<T> asWrapperType(Class<T> type) {
+ if (type.isPrimitive()) {
+ return forPrimitiveType(type).wrapperType(type);
+ }
+ return type;
+ }
+
+ /** If {@code type} is a wrapper type, return the corresponding
+ * primitive type, else return {@code type} unchanged.
+ */
+ public static <T> Class<T> asPrimitiveType(Class<T> type) {
+ Wrapper w = findWrapperType(type);
+ if (w != null) {
+ return forceType(w.primitiveType(), type);
+ }
+ return type;
+ }
+
+ /** Query: Is the given type a wrapper, such as {@code Integer} or {@code Void}? */
+ public static boolean isWrapperType(Class<?> type) {
+ return findWrapperType(type) != null;
+ }
+
+ /** Query: Is the given type a primitive, such as {@code int} or {@code void}? */
+ public static boolean isPrimitiveType(Class<?> type) {
+ return type.isPrimitive();
+ }
+
+ /** What is the bytecode signature character for this type?
+ * All non-primitives, including array types, report as 'L', the signature character for references.
+ */
+ public static char basicTypeChar(Class<?> type) {
+ if (!type.isPrimitive())
+ return 'L';
+ else
+ return forPrimitiveType(type).basicTypeChar();
+ }
+
+ /** What is the bytecode signature character for this wrapper's
+ * primitive type?
+ */
+ public char basicTypeChar() { return basicTypeChar; }
+
+ /** What is the simple name of the wrapper type?
+ */
+ public String simpleName() { return simpleName; }
+
+// /** Wrap a value in the given type, which may be either a primitive or wrapper type.
+// * Performs standard primitive conversions, including truncation and float conversions.
+// */
+// public static <T> T wrap(Object x, Class<T> type) {
+// return Wrapper.valueOf(type).cast(x, type);
+// }
+
+ /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
+ * The given target type must be this wrapper's primitive or wrapper type.
+ * If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
+ * Performs standard primitive conversions, including truncation and float conversions.
+ * The given type must be compatible with this wrapper. That is, it must either
+ * be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else
+ * it must be the wrapper's primitive type.
+ * Primitive conversions are only performed if the given type is itself a primitive.
+ * @throws ClassCastException if the given type is not compatible with this wrapper
+ */
+ public <T> T cast(Object x, Class<T> type) {
+ return convert(x, type, true);
+ }
+
+ /** Convert a wrapped value to the given type.
+ * The given target type must be this wrapper's primitive or wrapper type.
+ * This is equivalent to {@link #cast}, except that it refuses to perform
+ * narrowing primitive conversions.
+ */
+ public <T> T convert(Object x, Class<T> type) {
+ return convert(x, type, false);
+ }
+
+ private <T> T convert(Object x, Class<T> type, boolean isCast) {
+ if (this == OBJECT) {
+ // If the target wrapper is OBJECT, just do a reference cast.
+ // If the target type is an interface, perform no runtime check.
+ // (This loophole is safe, and is allowed by the JVM verifier.)
+ // If the target type is a primitive, change it to a wrapper.
+ @SuppressWarnings("unchecked")
+ T result = (T) x; // unchecked warning is expected here
+ return result;
+ }
+ Class<T> wtype = wrapperType(type);
+ if (wtype.isInstance(x)) {
+ @SuppressWarnings("unchecked")
+ T result = (T) x; // unchecked warning is expected here
+ return result;
+ }
+ Class<?> sourceType = x.getClass(); // throw NPE if x is null
+ if (!isCast) {
+ Wrapper source = findWrapperType(sourceType);
+ if (source == null || !this.isConvertibleFrom(source)) {
+ throw newClassCastException(wtype, sourceType);
+ }
+ }
+ @SuppressWarnings("unchecked")
+ T result = (T) wrap(x); // unchecked warning is expected here
+ assert result.getClass() == wtype;
+ return result;
+ }
+
+ /** Cast a reference type to another reference type.
+ * If the target type is an interface, perform no runtime check.
+ * (This loophole is safe, and is allowed by the JVM verifier.)
+ * If the target type is a primitive, change it to a wrapper.
+ */
+ static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
+ boolean z = (type == exampleType ||
+ type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
+ exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
+ type == Object.class && !exampleType.isPrimitive());
+ if (!z)
+ System.out.println(type+" <= "+exampleType);
+ assert(type == exampleType ||
+ type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
+ exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
+ type == Object.class && !exampleType.isPrimitive());
+ @SuppressWarnings("unchecked")
+ Class<T> result = (Class<T>) type; // unchecked warning is expected here
+ return result;
+ }
+
+ /** Wrap a value in this wrapper's type.
+ * Performs standard primitive conversions, including truncation and float conversions.
+ * Performs returns the unchanged reference for {@code OBJECT}.
+ * Returns null for {@code VOID}.
+ * Returns a zero value for a null input.
+ * @throws ClassCastException if this wrapper is numeric and the operand
+ * is not a number, character, boolean, or null
+ */
+ public Object wrap(Object x) {
+ // do non-numeric wrappers first
+ switch (basicTypeChar) {
+ case 'L': return x;
+ case 'V': return null;
+ }
+ Number xn = numberValue(x);
+ switch (basicTypeChar) {
+ case 'I': return Integer.valueOf(xn.intValue());
+ case 'J': return Long.valueOf(xn.longValue());
+ case 'F': return Float.valueOf(xn.floatValue());
+ case 'D': return Double.valueOf(xn.doubleValue());
+ case 'S': return Short.valueOf((short) xn.intValue());
+ case 'B': return Byte.valueOf((byte) xn.intValue());
+ case 'C': return Character.valueOf((char) xn.intValue());
+ case 'Z': return Boolean.valueOf(boolValue(xn.longValue()));
+ }
+ throw new InternalError("bad wrapper");
+ }
+
+ /** Wrap a value (an int or smaller value) in this wrapper's type.
+ * Performs standard primitive conversions, including truncation and float conversions.
+ * Produces an {@code Integer} for {@code OBJECT}, although the exact type
+ * of the operand is not known.
+ * Returns null for {@code VOID}.
+ */
+ public Object wrap(int x) {
+ if (basicTypeChar == 'L') return (Integer)x;
+ switch (basicTypeChar) {
+ case 'L': throw newIllegalArgumentException("cannot wrap to object type");
+ case 'V': return null;
+ case 'I': return Integer.valueOf((int)x);
+ case 'J': return Long.valueOf(x);
+ case 'F': return Float.valueOf(x);
+ case 'D': return Double.valueOf(x);
+ case 'S': return Short.valueOf((short) x);
+ case 'B': return Byte.valueOf((byte) x);
+ case 'C': return Character.valueOf((char) x);
+ case 'Z': return Boolean.valueOf(boolValue(x));
+ }
+ throw new InternalError("bad wrapper");
+ }
+
+ /** Wrap a value (a long or smaller value) in this wrapper's type.
+ * Does not perform floating point conversion.
+ * Produces a {@code Long} for {@code OBJECT}, although the exact type
+ * of the operand is not known.
+ * Returns null for {@code VOID}.
+ */
+ public Object wrapRaw(long x) {
+ switch (basicTypeChar) {
+ case 'F': return Float.valueOf(Float.intBitsToFloat((int)x));
+ case 'D': return Double.valueOf(Double.longBitsToDouble(x));
+ case 'L': // same as 'J':
+ case 'J': return (Long) x;
+ }
+ // Other wrapping operations are just the same, given that the
+ // operand is already promoted to an int.
+ return wrap((int)x);
+ }
+
+ /** Produce bitwise value which encodes the given wrapped value.
+ * Does not perform floating point conversion.
+ * Returns zero for {@code VOID}.
+ */
+ public long unwrapRaw(Object x) {
+ switch (basicTypeChar) {
+ case 'F': return Float.floatToRawIntBits((Float) x);
+ case 'D': return Double.doubleToRawLongBits((Double) x);
+
+ case 'L': throw newIllegalArgumentException("cannot unwrap from sobject type");
+ case 'V': return 0;
+ case 'I': return (int)(Integer) x;
+ case 'J': return (long)(Long) x;
+ case 'S': return (short)(Short) x;
+ case 'B': return (byte)(Byte) x;
+ case 'C': return (char)(Character) x;
+ case 'Z': return (boolean)(Boolean) x ? 1 : 0;
+ }
+ throw new InternalError("bad wrapper");
+ }
+
+ /** Report what primitive type holds this guy's raw value. */
+ public Class<?> rawPrimitiveType() {
+ return rawPrimitive().primitiveType();
+ }
+
+ /** Report, as a wrapper, what primitive type holds this guy's raw value.
+ * Returns self for INT, LONG, OBJECT; returns LONG for DOUBLE,
+ * else returns INT.
+ */
+ public Wrapper rawPrimitive() {
+ switch (basicTypeChar) {
+ case 'S': case 'B':
+ case 'C': case 'Z':
+ case 'V':
+ case 'F':
+ return INT;
+ case 'D':
+ return LONG;
+ }
+ return this;
+ }
+
+ private static Number numberValue(Object x) {
+ if (x instanceof Number) return (Number)x;
+ if (x instanceof Character) return (int)(Character)x;
+ if (x instanceof Boolean) return (Boolean)x ? 1 : 0;
+ // Remaining allowed case of void: Must be a null reference.
+ return (Number)x;
+ }
+
+ private static boolean boolValue(long bits) {
+ //bits &= 1; // simple 31-bit zero extension
+ return (bits != 0);
+ }
+
+ private static RuntimeException newIllegalArgumentException(String message, Object x) {
+ return newIllegalArgumentException(message + x);
+ }
+ private static RuntimeException newIllegalArgumentException(String message) {
+ return new IllegalArgumentException(message);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/invoke/util/package-info.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Extra support for using JSR 292 RI, package java.lang.invoke.
+ * @author jrose
+ */
+
+package sun.invoke.util;
--- a/jdk/src/share/native/common/check_code.c Fri Mar 18 00:03:24 2011 -0700
+++ b/jdk/src/share/native/common/check_code.c Wed Mar 23 23:02:31 2011 -0700
@@ -2685,11 +2685,11 @@
switch (type_table[operand]) {
case JVM_CONSTANT_MethodType:
full_info = make_class_info_from_name(context,
- "java/dyn/MethodType");
+ "java/lang/invoke/MethodType");
break;
default: //JVM_CONSTANT_MethodHandle
full_info = make_class_info_from_name(context,
- "java/dyn/MethodHandle");
+ "java/lang/invoke/MethodHandle");
break;
}
break;
--- a/jdk/test/java/dyn/6987555/Test6987555.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/**
- * @test
- * @bug 6987555
- * @summary JSR 292 unboxing to a boolean value fails on big-endian SPARC
- *
- * @run main/othervm -Xint -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6987555
- */
-
-import java.dyn.*;
-
-public class Test6987555 {
- private static final Class CLASS = Test6987555.class;
- private static final String NAME = "foo";
- private static final boolean DEBUG = false;
-
- public static void main(String[] args) throws Throwable {
- testboolean();
- testbyte();
- testchar();
- testshort();
- testint();
- }
-
- // boolean
- static void testboolean() throws Throwable {
- doboolean(false);
- doboolean(true);
- }
- static void doboolean(boolean x) throws Throwable {
- if (DEBUG) System.out.println("boolean=" + x);
- MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(boolean.class, boolean.class));
- MethodHandle mh2 = mh1.asType(MethodType.methodType(boolean.class, Boolean.class));
- boolean a = (boolean) mh1.invokeExact(x);
- boolean b = (boolean) mh2.invokeExact(Boolean.valueOf(x));
- assert a == b : a + " != " + b;
- }
-
- // byte
- static void testbyte() throws Throwable {
- byte[] a = new byte[] {
- Byte.MIN_VALUE,
- Byte.MIN_VALUE + 1,
- -0x0F,
- -1,
- 0,
- 1,
- 0x0F,
- Byte.MAX_VALUE - 1,
- Byte.MAX_VALUE
- };
- for (int i = 0; i < a.length; i++) {
- dobyte(a[i]);
- }
- }
- static void dobyte(byte x) throws Throwable {
- if (DEBUG) System.out.println("byte=" + x);
- MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(byte.class, byte.class));
- MethodHandle mh2 = mh1.asType(MethodType.methodType(byte.class, Byte.class));
- byte a = (byte) mh1.invokeExact(x);
- byte b = (byte) mh2.invokeExact(Byte.valueOf(x));
- assert a == b : a + " != " + b;
- }
-
- // char
- static void testchar() throws Throwable {
- char[] a = new char[] {
- Character.MIN_VALUE,
- Character.MIN_VALUE + 1,
- 0x000F,
- 0x00FF,
- 0x0FFF,
- Character.MAX_VALUE - 1,
- Character.MAX_VALUE
- };
- for (int i = 0; i < a.length; i++) {
- dochar(a[i]);
- }
- }
- static void dochar(char x) throws Throwable {
- if (DEBUG) System.out.println("char=" + x);
- MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(char.class, char.class));
- MethodHandle mh2 = mh1.asType(MethodType.methodType(char.class, Character.class));
- char a = (char) mh1.invokeExact(x);
- char b = (char) mh2.invokeExact(Character.valueOf(x));
- assert a == b : a + " != " + b;
- }
-
- // short
- static void testshort() throws Throwable {
- short[] a = new short[] {
- Short.MIN_VALUE,
- Short.MIN_VALUE + 1,
- -0x0FFF,
- -0x00FF,
- -0x000F,
- -1,
- 0,
- 1,
- 0x000F,
- 0x00FF,
- 0x0FFF,
- Short.MAX_VALUE - 1,
- Short.MAX_VALUE
- };
- for (int i = 0; i < a.length; i++) {
- doshort(a[i]);
- }
- }
- static void doshort(short x) throws Throwable {
- if (DEBUG) System.out.println("short=" + x);
- MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(short.class, short.class));
- MethodHandle mh2 = mh1.asType(MethodType.methodType(short.class, Short.class));
- short a = (short) mh1.invokeExact(x);
- short b = (short) mh2.invokeExact(Short.valueOf(x));
- assert a == b : a + " != " + b;
- }
-
- // int
- static void testint() throws Throwable {
- int[] a = new int[] {
- Integer.MIN_VALUE,
- Integer.MIN_VALUE + 1,
- -0x00000FFF,
- -0x000000FF,
- -0x0000000F,
- -1,
- 0,
- 1,
- 0x0000000F,
- 0x000000FF,
- 0x00000FFF,
- Integer.MAX_VALUE - 1,
- Integer.MAX_VALUE
- };
- for (int i = 0; i < a.length; i++) {
- doint(a[i]);
- }
- }
- static void doint(int x) throws Throwable {
- if (DEBUG) System.out.println("int=" + x);
- MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(int.class, int.class));
- MethodHandle mh2 = mh1.asType(MethodType.methodType(int.class, Integer.class));
- int a = (int) mh1.invokeExact(x);
- int b = (int) mh2.invokeExact(Integer.valueOf(x));
- assert a == b : a + " != " + b;
- }
-
- public static boolean foo(boolean i) { return i; }
- public static byte foo(byte i) { return i; }
- public static char foo(char i) { return i; }
- public static short foo(short i) { return i; }
- public static int foo(int i) { return i; }
-}
--- a/jdk/test/java/dyn/6991596/Test6991596.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,465 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-/**
- * @test
- * @bug 6991596
- * @summary JSR 292 unimplemented adapter_opt_i2i and adapter_opt_l2i on SPARC
- *
- * @run main/othervm -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6991596
- */
-
-import java.dyn.*;
-
-public class Test6991596 {
- private static final Class CLASS = Test6991596.class;
- private static final String NAME = "foo";
- private static final boolean DEBUG = System.getProperty("DEBUG", "false").equals("true");
-
- public static void main(String[] args) throws Throwable {
- testboolean();
- testbyte();
- testchar();
- testshort();
- testint();
- testlong();
- }
-
- // Helpers to get various methods.
- static MethodHandle getmh1(Class ret, Class arg) throws ReflectiveOperationException {
- return MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(ret, arg));
- }
- static MethodHandle getmh2(MethodHandle mh1, Class ret, Class arg) {
- return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
- }
- static MethodHandle getmh3(MethodHandle mh1, Class ret, Class arg) {
- return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
- }
-
- // test adapter_opt_i2i
- static void testboolean() throws Throwable {
- boolean[] a = new boolean[] {
- true,
- false
- };
- for (int i = 0; i < a.length; i++) {
- doboolean(a[i]);
- }
- }
- static void doboolean(boolean x) throws Throwable {
- if (DEBUG) System.out.println("boolean=" + x);
-
- // boolean
- {
- MethodHandle mh1 = getmh1( boolean.class, boolean.class);
- MethodHandle mh2 = getmh2(mh1, boolean.class, boolean.class);
- // TODO add this for all cases when the bugs are fixed.
- //MethodHandle mh3 = getmh3(mh1, boolean.class, boolean.class);
- boolean a = (boolean) mh1.invokeExact((boolean) x);
- boolean b = (boolean) mh2.invokeExact(x);
- //boolean c = mh3.<boolean>invokeExact((boolean) x);
- check(x, a, b);
- //check(x, c, x);
- }
-
- // byte
- {
- MethodHandle mh1 = getmh1( byte.class, byte.class );
- MethodHandle mh2 = getmh2(mh1, byte.class, boolean.class);
- byte a = (byte) mh1.invokeExact((byte) (x ? 1 : 0));
- byte b = (byte) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // char
- {
- MethodHandle mh1 = getmh1( char.class, char.class);
- MethodHandle mh2 = getmh2(mh1, char.class, boolean.class);
- char a = (char) mh1.invokeExact((char) (x ? 1 : 0));
- char b = (char) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // short
- {
- MethodHandle mh1 = getmh1( short.class, short.class);
- MethodHandle mh2 = getmh2(mh1, short.class, boolean.class);
- short a = (short) mh1.invokeExact((short) (x ? 1 : 0));
- short b = (short) mh2.invokeExact(x);
- check(x, a, b);
- }
- }
-
- static void testbyte() throws Throwable {
- byte[] a = new byte[] {
- Byte.MIN_VALUE,
- Byte.MIN_VALUE + 1,
- -0x0F,
- -1,
- 0,
- 1,
- 0x0F,
- Byte.MAX_VALUE - 1,
- Byte.MAX_VALUE
- };
- for (int i = 0; i < a.length; i++) {
- dobyte(a[i]);
- }
- }
- static void dobyte(byte x) throws Throwable {
- if (DEBUG) System.out.println("byte=" + x);
-
- // boolean
- {
- MethodHandle mh1 = getmh1( boolean.class, boolean.class);
- MethodHandle mh2 = getmh2(mh1, boolean.class, byte.class);
- boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
- boolean b = (boolean) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // byte
- {
- MethodHandle mh1 = getmh1( byte.class, byte.class);
- MethodHandle mh2 = getmh2(mh1, byte.class, byte.class);
- byte a = (byte) mh1.invokeExact((byte) x);
- byte b = (byte) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // char
- {
- MethodHandle mh1 = getmh1( char.class, char.class);
- MethodHandle mh2 = getmh2(mh1, char.class, byte.class);
- char a = (char) mh1.invokeExact((char) x);
- char b = (char) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // short
- {
- MethodHandle mh1 = getmh1( short.class, short.class);
- MethodHandle mh2 = getmh2(mh1, short.class, byte.class);
- short a = (short) mh1.invokeExact((short) x);
- short b = (short) mh2.invokeExact(x);
- check(x, a, b);
- }
- }
-
- static void testchar() throws Throwable {
- char[] a = new char[] {
- Character.MIN_VALUE,
- Character.MIN_VALUE + 1,
- 0x000F,
- 0x00FF,
- 0x0FFF,
- Character.MAX_VALUE - 1,
- Character.MAX_VALUE
- };
- for (int i = 0; i < a.length; i++) {
- dochar(a[i]);
- }
- }
- static void dochar(char x) throws Throwable {
- if (DEBUG) System.out.println("char=" + x);
-
- // boolean
- {
- MethodHandle mh1 = getmh1( boolean.class, boolean.class);
- MethodHandle mh2 = getmh2(mh1, boolean.class, char.class);
- boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
- boolean b = (boolean) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // byte
- {
- MethodHandle mh1 = getmh1( byte.class, byte.class);
- MethodHandle mh2 = getmh2(mh1, byte.class, char.class);
- byte a = (byte) mh1.invokeExact((byte) x);
- byte b = (byte) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // char
- {
- MethodHandle mh1 = getmh1( char.class, char.class);
- MethodHandle mh2 = getmh2(mh1, char.class, char.class);
- char a = (char) mh1.invokeExact((char) x);
- char b = (char) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // short
- {
- MethodHandle mh1 = getmh1( short.class, short.class);
- MethodHandle mh2 = getmh2(mh1, short.class, char.class);
- short a = (short) mh1.invokeExact((short) x);
- short b = (short) mh2.invokeExact(x);
- check(x, a, b);
- }
- }
-
- static void testshort() throws Throwable {
- short[] a = new short[] {
- Short.MIN_VALUE,
- Short.MIN_VALUE + 1,
- -0x0FFF,
- -0x00FF,
- -0x000F,
- -1,
- 0,
- 1,
- 0x000F,
- 0x00FF,
- 0x0FFF,
- Short.MAX_VALUE - 1,
- Short.MAX_VALUE
- };
- for (int i = 0; i < a.length; i++) {
- doshort(a[i]);
- }
- }
- static void doshort(short x) throws Throwable {
- if (DEBUG) System.out.println("short=" + x);
-
- // boolean
- {
- MethodHandle mh1 = getmh1( boolean.class, boolean.class);
- MethodHandle mh2 = getmh2(mh1, boolean.class, short.class);
- boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
- boolean b = (boolean) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // byte
- {
- MethodHandle mh1 = getmh1( byte.class, byte.class);
- MethodHandle mh2 = getmh2(mh1, byte.class, short.class);
- byte a = (byte) mh1.invokeExact((byte) x);
- byte b = (byte) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // char
- {
- MethodHandle mh1 = getmh1( char.class, char.class);
- MethodHandle mh2 = getmh2(mh1, char.class, short.class);
- char a = (char) mh1.invokeExact((char) x);
- char b = (char) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // short
- {
- MethodHandle mh1 = getmh1( short.class, short.class);
- MethodHandle mh2 = getmh2(mh1, short.class, short.class);
- short a = (short) mh1.invokeExact((short) x);
- short b = (short) mh2.invokeExact(x);
- check(x, a, b);
- }
- }
-
- static void testint() throws Throwable {
- int[] a = new int[] {
- Integer.MIN_VALUE,
- Integer.MIN_VALUE + 1,
- -0x0FFFFFFF,
- -0x00FFFFFF,
- -0x000FFFFF,
- -0x0000FFFF,
- -0x00000FFF,
- -0x000000FF,
- -0x0000000F,
- -1,
- 0,
- 1,
- 0x0000000F,
- 0x000000FF,
- 0x00000FFF,
- 0x0000FFFF,
- 0x000FFFFF,
- 0x00FFFFFF,
- 0x0FFFFFFF,
- Integer.MAX_VALUE - 1,
- Integer.MAX_VALUE
- };
- for (int i = 0; i < a.length; i++) {
- doint(a[i]);
- }
- }
- static void doint(int x) throws Throwable {
- if (DEBUG) System.out.println("int=" + x);
-
- // boolean
- {
- MethodHandle mh1 = getmh1( boolean.class, boolean.class);
- MethodHandle mh2 = getmh2(mh1, boolean.class, int.class);
- boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
- boolean b = (boolean) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // byte
- {
- MethodHandle mh1 = getmh1( byte.class, byte.class);
- MethodHandle mh2 = getmh2(mh1, byte.class, int.class);
- byte a = (byte) mh1.invokeExact((byte) x);
- byte b = (byte) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // char
- {
- MethodHandle mh1 = getmh1( char.class, char.class);
- MethodHandle mh2 = getmh2(mh1, char.class, int.class);
- char a = (char) mh1.invokeExact((char) x);
- char b = (char) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // short
- {
- MethodHandle mh1 = getmh1( short.class, short.class);
- MethodHandle mh2 = getmh2(mh1, short.class, int.class);
- short a = (short) mh1.invokeExact((short) x);
- short b = (short) mh2.invokeExact(x);
- assert a == b : a + " != " + b;
- check(x, a, b);
- }
-
- // int
- {
- MethodHandle mh1 = getmh1( int.class, int.class);
- MethodHandle mh2 = getmh2(mh1, int.class, int.class);
- int a = (int) mh1.invokeExact((int) x);
- int b = (int) mh2.invokeExact(x);
- check(x, a, b);
- }
- }
-
- // test adapter_opt_l2i
- static void testlong() throws Throwable {
- long[] a = new long[] {
- Long.MIN_VALUE,
- Long.MIN_VALUE + 1,
- -0x000000000FFFFFFFL,
- -0x0000000000FFFFFFL,
- -0x00000000000FFFFFL,
- -0x000000000000FFFFL,
- -0x0000000000000FFFL,
- -0x00000000000000FFL,
- -0x000000000000000FL,
- -1L,
- 0L,
- 1L,
- 0x000000000000000FL,
- 0x00000000000000FFL,
- 0x0000000000000FFFL,
- 0x0000000000000FFFL,
- 0x000000000000FFFFL,
- 0x00000000000FFFFFL,
- 0x0000000000FFFFFFL,
- 0x000000000FFFFFFFL,
- Long.MAX_VALUE - 1,
- Long.MAX_VALUE
- };
- for (int i = 0; i < a.length; i++) {
- dolong(a[i]);
- }
- }
- static void dolong(long x) throws Throwable {
- if (DEBUG) System.out.println("long=" + x);
-
- // boolean
- {
- MethodHandle mh1 = getmh1( boolean.class, boolean.class);
- MethodHandle mh2 = getmh2(mh1, boolean.class, long.class);
- boolean a = (boolean) mh1.invokeExact((x & 1L) == 1L);
- boolean b = (boolean) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // byte
- {
- MethodHandle mh1 = getmh1( byte.class, byte.class);
- MethodHandle mh2 = getmh2(mh1, byte.class, long.class);
- byte a = (byte) mh1.invokeExact((byte) x);
- byte b = (byte) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // char
- {
- MethodHandle mh1 = getmh1( char.class, char.class);
- MethodHandle mh2 = getmh2(mh1, char.class, long.class);
- char a = (char) mh1.invokeExact((char) x);
- char b = (char) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // short
- {
- MethodHandle mh1 = getmh1( short.class, short.class);
- MethodHandle mh2 = getmh2(mh1, short.class, long.class);
- short a = (short) mh1.invokeExact((short) x);
- short b = (short) mh2.invokeExact(x);
- check(x, a, b);
- }
-
- // int
- {
- MethodHandle mh1 = getmh1( int.class, int.class);
- MethodHandle mh2 = getmh2(mh1, int.class, long.class);
- int a = (int) mh1.invokeExact((int) x);
- int b = (int) mh2.invokeExact(x);
- check(x, a, b);
- }
- }
-
- static void check(boolean x, boolean e, boolean a) { p(z2h(x), z2h(e), z2h(a)); assert e == a : z2h(x) + ": " + z2h(e) + " != " + z2h(a); }
- static void check(boolean x, byte e, byte a) { p(z2h(x), i2h(e), i2h(a)); assert e == a : z2h(x) + ": " + i2h(e) + " != " + i2h(a); }
- static void check(boolean x, int e, int a) { p(z2h(x), i2h(e), i2h(a)); assert e == a : z2h(x) + ": " + i2h(e) + " != " + i2h(a); }
-
- static void check(int x, boolean e, boolean a) { p(i2h(x), z2h(e), z2h(a)); assert e == a : i2h(x) + ": " + z2h(e) + " != " + z2h(a); }
- static void check(int x, byte e, byte a) { p(i2h(x), i2h(e), i2h(a)); assert e == a : i2h(x) + ": " + i2h(e) + " != " + i2h(a); }
- static void check(int x, int e, int a) { p(i2h(x), i2h(e), i2h(a)); assert e == a : i2h(x) + ": " + i2h(e) + " != " + i2h(a); }
-
- static void check(long x, boolean e, boolean a) { p(l2h(x), z2h(e), z2h(a)); assert e == a : l2h(x) + ": " + z2h(e) + " != " + z2h(a); }
- static void check(long x, byte e, byte a) { p(l2h(x), i2h(e), i2h(a)); assert e == a : l2h(x) + ": " + i2h(e) + " != " + i2h(a); }
- static void check(long x, int e, int a) { p(l2h(x), i2h(e), i2h(a)); assert e == a : l2h(x) + ": " + i2h(e) + " != " + i2h(a); }
-
- static void p(String x, String e, String a) { if (DEBUG) System.out.println(x + ": expected: " + e + ", actual: " + a); }
-
- static String z2h(boolean x) { return x ? "1" : "0"; }
- static String i2h(int x) { return Integer.toHexString(x); }
- static String l2h(long x) { return Long.toHexString(x); }
-
- // to int
- public static boolean foo(boolean i) { return i; }
- public static byte foo(byte i) { return i; }
- public static char foo(char i) { return i; }
- public static short foo(short i) { return i; }
- public static int foo(int i) { return i; }
-}
--- a/jdk/test/java/dyn/ClassValueTest.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary tests for class-specific values
- * @compile ClassValueTest.java
- * @run junit/othervm test.java.dyn.ClassValueTest
- */
-
-/*
- Manually:
- $ $JAVA7X_HOME/bin/javac -d foo -cp $JUNIT4_JAR test/java/dyn/ClassValueTest.java
- $ $JAVA7X_HOME/bin/java -cp foo:$JUNIT4_JAR org.junit.runner.JUnitCore test.java.dyn.ClassValueTest
- Output: .testAdd => 1000 : Integer
- */
-
-package test.java.dyn;
-
-import java.util.*;
-
-import java.dyn.*;
-
-import org.junit.*;
-import static org.junit.Assert.*;
-
-/**
- * @author jrose
- */
-public class ClassValueTest {
- static String nameForCV1(Class<?> type) {
- return "CV1:" + type.getName();
- }
- static int countForCV1;
- static final ClassValue<String> CV1 = new CV1();
- private static class CV1 extends ClassValue<String> {
- protected String computeValue(Class<?> type) {
- countForCV1++;
- return nameForCV1(type);
- }
- }
-
- static final Class[] CLASSES = {
- String.class,
- Integer.class,
- int.class,
- boolean[].class,
- char[][].class,
- ClassValueTest.class
- };
-
- @Test
- public void testGet() {
- countForCV1 = 0;
- for (Class c : CLASSES) {
- assertEquals(nameForCV1(c), CV1.get(c));
- }
- assertEquals(CLASSES.length, countForCV1);
- for (Class c : CLASSES) {
- assertEquals(nameForCV1(c), CV1.get(c));
- }
- assertEquals(CLASSES.length, countForCV1);
- }
-
- @Test
- public void testRemove() {
- for (Class c : CLASSES) {
- CV1.get(c);
- }
- countForCV1 = 0;
- int REMCOUNT = 3;
- for (int i = 0; i < REMCOUNT; i++) {
- CV1.remove(CLASSES[i]);
- }
- assertEquals(0, countForCV1); // no change
- for (Class c : CLASSES) {
- assertEquals(nameForCV1(c), CV1.get(c));
- }
- assertEquals(REMCOUNT, countForCV1);
- }
-
- static String nameForCVN(Class<?> type, int n) {
- return "CV[" + n + "]" + type.getName();
- }
- static int countForCVN;
- static class CVN extends ClassValue<String> {
- final int n;
- CVN(int n) { this.n = n; }
- protected String computeValue(Class<?> type) {
- countForCVN++;
- return nameForCVN(type, n);
- }
- };
-
- @Test
- public void testGetMany() {
- int CVN_COUNT1 = 100, CVN_COUNT2 = 100;
- CVN cvns[] = new CVN[CVN_COUNT1 * CVN_COUNT2];
- for (int n = 0; n < cvns.length; n++) {
- cvns[n] = new CVN(n);
- }
- countForCVN = 0;
- for (int pass = 0; pass <= 2; pass++) {
- for (int i1 = 0; i1 < CVN_COUNT1; i1++) {
- eachClass:
- for (Class c : CLASSES) {
- for (int i2 = 0; i2 < CVN_COUNT2; i2++) {
- int n = i1*CVN_COUNT2 + i2;
- assertEquals(0, countForCVN);
- assertEquals(nameForCVN(c, n), cvns[n].get(c));
- cvns[n].get(c); //get it again
- //System.out.println("getting "+n+":"+cvns[n].get(c));
- boolean doremove = (((i1 + i2) & 3) == 0);
- switch (pass) {
- case 0:
- assertEquals(1, countForCVN);
- break;
- case 1:
- // remove on middle pass
- assertEquals(0, countForCVN);
- if (doremove) {
- //System.out.println("removing "+n+":"+cvns[n].get(c));
- cvns[n].remove(c);
- assertEquals(0, countForCVN);
- }
- break;
- case 2:
- assertEquals(doremove ? 1 : 0, countForCVN);
- break;
- }
- countForCVN = 0;
- if (i1 > i2 && i1 < i2+5) continue eachClass; // leave diagonal gap
- }
- }
- }
- }
- assertEquals(countForCVN, 0);
- for (int n = 0; n < cvns.length; n++) {
- for (Class c : CLASSES) {
- assertEquals(nameForCVN(c, n), cvns[n].get(c));
- }
- }
- }
-}
--- a/jdk/test/java/dyn/InvokeDynamicPrintArgs.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary smoke test for invokedynamic instructions
- * @build indify.Indify
- * @compile InvokeDynamicPrintArgs.java
- * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic
- * indify.Indify
- * --verify-specifier-count=3 --transitionalJSR292=false
- * --expand-properties --classpath ${test.classes}
- * --java test.java.dyn.InvokeDynamicPrintArgs --check-output
- */
-
-package test.java.dyn;
-
-import org.junit.Test;
-
-import java.util.*;
-import java.io.*;
-
-import java.dyn.*;
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-
-public class InvokeDynamicPrintArgs {
- public static void main(String... av) throws Throwable {
- if (av.length > 0) openBuf(); // --check-output mode
- System.out.println("Printing some argument lists, starting with a empty one:");
- INDY_nothing().invokeExact(); // BSM specifier #0 = {bsm}
- INDY_bar().invokeExact("bar arg", 1); // BSM specifier #1 = {bsm2, Void.class, "void type"}
- INDY_bar2().invokeExact("bar2 arg", 222); // BSM specifier #1 = (same)
- INDY_baz().invokeExact("baz arg", 2, 3.14); // BSM specifier #2 = {bsm2, 1234.5}
- INDY_foo().invokeExact("foo arg"); // BSM specifier #0 = (same)
- // Hence, BSM specifier count should be 3. See "--verify-specifier-count=3" above.
- System.out.println("Done printing argument lists.");
- closeBuf();
- }
-
- @Test
- public void testInvokeDynamicPrintArgs() throws IOException {
- System.err.println(System.getProperties());
- String testClassPath = System.getProperty("build.test.classes.dir");
- if (testClassPath == null) throw new RuntimeException();
- String[] args = new String[]{
- "--verify-specifier-count=3", "--transitionalJSR292=false",
- "--expand-properties", "--classpath", testClassPath,
- "--java", "test.java.dyn.InvokeDynamicPrintArgs", "--check-output"
- };
- System.err.println("Indify: "+Arrays.toString(args));
- indify.Indify.main(args);
- }
-
- private static PrintStream oldOut;
- private static ByteArrayOutputStream buf;
- private static void openBuf() {
- oldOut = System.out;
- buf = new ByteArrayOutputStream();
- System.setOut(new PrintStream(buf));
- }
- private static void closeBuf() {
- if (buf == null) return;
- System.out.flush();
- System.setOut(oldOut);
- String[] haveLines = new String(buf.toByteArray()).split("[\n\r]+");
- for (String line : haveLines) System.out.println(line);
- Iterator<String> iter = Arrays.asList(haveLines).iterator();
- for (String want : EXPECT_OUTPUT) {
- String have = iter.hasNext() ? iter.next() : "[EOF]";
- if (want.equals(have)) continue;
- System.err.println("want line: "+want);
- System.err.println("have line: "+have);
- throw new AssertionError("unexpected output: "+have);
- }
- if (iter.hasNext())
- throw new AssertionError("unexpected output: "+iter.next());
- }
- private static final String[] EXPECT_OUTPUT = {
- "Printing some argument lists, starting with a empty one:",
- "[test.java.dyn.InvokeDynamicPrintArgs, nothing, ()void][]",
- "[test.java.dyn.InvokeDynamicPrintArgs, bar, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar arg, 1]",
- "[test.java.dyn.InvokeDynamicPrintArgs, bar2, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar2 arg, 222]",
- "[test.java.dyn.InvokeDynamicPrintArgs, baz, (String,int,double)void, 1234.5][baz arg, 2, 3.14]",
- "[test.java.dyn.InvokeDynamicPrintArgs, foo, (String)void][foo arg]",
- "Done printing argument lists."
- };
-
- private static void printArgs(Object bsmInfo, Object... args) {
- System.out.println(bsmInfo+Arrays.deepToString(args));
- }
- private static MethodHandle MH_printArgs() throws ReflectiveOperationException {
- shouldNotCallThis();
- return lookup().findStatic(lookup().lookupClass(),
- "printArgs", methodType(void.class, Object.class, Object[].class));
- }
-
- private static CallSite bsm(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
- // ignore caller and name, but match the type:
- Object bsmInfo = Arrays.asList(caller, name, type);
- return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
- }
- private static MethodType MT_bsm() {
- shouldNotCallThis();
- return methodType(CallSite.class, Lookup.class, String.class, MethodType.class);
- }
- private static MethodHandle MH_bsm() throws ReflectiveOperationException {
- shouldNotCallThis();
- return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());
- }
-
- private static CallSite bsm2(Lookup caller, String name, MethodType type, Object... arg) throws ReflectiveOperationException {
- // ignore caller and name, but match the type:
- List<Object> bsmInfo = new ArrayList<>(Arrays.asList(caller, name, type));
- bsmInfo.addAll(Arrays.asList((Object[])arg));
- return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
- }
- private static MethodType MT_bsm2() {
- shouldNotCallThis();
- return methodType(CallSite.class, Lookup.class, String.class, MethodType.class, Object[].class);
- }
- private static MethodHandle MH_bsm2() throws ReflectiveOperationException {
- shouldNotCallThis();
- return lookup().findStatic(lookup().lookupClass(), "bsm2", MT_bsm2());
- }
-
- private static MethodHandle INDY_nothing() throws Throwable {
- shouldNotCallThis();
- return ((CallSite) MH_bsm().invokeGeneric(lookup(),
- "nothing", methodType(void.class)
- )).dynamicInvoker();
- }
- private static MethodHandle INDY_foo() throws Throwable {
- shouldNotCallThis();
- return ((CallSite) MH_bsm().invokeGeneric(lookup(),
- "foo", methodType(void.class, String.class)
- )).dynamicInvoker();
- }
- private static MethodHandle INDY_bar() throws Throwable {
- shouldNotCallThis();
- return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
- "bar", methodType(void.class, String.class, int.class)
- , new Object[] { Void.class, "void type!",
- 1, 234.5F, 67.5, (long)89 }
- )).dynamicInvoker();
- }
- private static MethodHandle INDY_bar2() throws Throwable {
- shouldNotCallThis();
- return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
- "bar2", methodType(void.class, String.class, int.class)
- , new Object[] { Void.class, "void type!",
- 1, 234.5F, 67.5, (long)89 }
- )).dynamicInvoker();
- }
- private static MethodHandle INDY_baz() throws Throwable {
- shouldNotCallThis();
- return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
- "baz", methodType(void.class, String.class, int.class, double.class)
- , 1234.5
- )).dynamicInvoker();
- }
-
- private static void shouldNotCallThis() {
- // if this gets called, the transformation has not taken place
- if (System.getProperty("InvokeDynamicPrintArgs.allow-untransformed") != null) return;
- throw new AssertionError("this code should be statically transformed away by Indify");
- }
-}
--- a/jdk/test/java/dyn/InvokeGenericTest.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,484 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary unit tests for java.dyn.MethodHandle.invokeGeneric
- * @compile -XDallowTransitionalJSR292=no -target 7 InvokeGenericTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.InvokeGenericTest
- */
-
-package test.java.dyn;
-
-import java.dyn.*;
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-import java.lang.reflect.*;
-import java.util.*;
-import org.junit.*;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-
-
-/**
- *
- * @author jrose
- */
-public class InvokeGenericTest {
- // How much output?
- static int verbosity = 0;
- static {
- String vstr = System.getProperty("test.java.dyn.InvokeGenericTest.verbosity");
- if (vstr != null) verbosity = Integer.parseInt(vstr);
- }
-
- @Test
- public void testFirst() throws Throwable {
- verbosity += 9; try {
- // left blank for debugging
- } finally { printCounts(); verbosity -= 9; }
- }
-
- public InvokeGenericTest() {
- }
-
- @Before
- public void checkImplementedPlatform() {
- boolean platformOK = false;
- Properties properties = System.getProperties();
- String vers = properties.getProperty("java.vm.version");
- String name = properties.getProperty("java.vm.name");
- String arch = properties.getProperty("os.arch");
- if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
- arch.equals("sparc") || arch.equals("sparcv9")) &&
- (name.contains("Client") || name.contains("Server"))
- ) {
- platformOK = true;
- } else {
- System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
- }
- assumeTrue(platformOK);
- }
-
- String testName;
- static int allPosTests, allNegTests;
- int posTests, negTests;
- @After
- public void printCounts() {
- if (verbosity >= 2 && (posTests | negTests) != 0) {
- System.out.println();
- if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run");
- if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run");
- allPosTests += posTests;
- allNegTests += negTests;
- posTests = negTests = 0;
- }
- }
- void countTest(boolean positive) {
- if (positive) ++posTests;
- else ++negTests;
- }
- void countTest() { countTest(true); }
- void startTest(String name) {
- if (testName != null) printCounts();
- if (verbosity >= 1)
- System.out.println(name);
- posTests = negTests = 0;
- testName = name;
- }
-
- @BeforeClass
- public static void setUpClass() throws Exception {
- calledLog.clear();
- calledLog.add(null);
- nextArgVal = INITIAL_ARG_VAL;
- }
-
- @AfterClass
- public static void tearDownClass() throws Exception {
- int posTests = allPosTests, negTests = allNegTests;
- if (verbosity >= 2 && (posTests | negTests) != 0) {
- System.out.println();
- if (posTests != 0) System.out.println("=== "+posTests+" total positive test cases");
- if (negTests != 0) System.out.println("=== "+negTests+" total negative test cases");
- }
- }
-
- static List<Object> calledLog = new ArrayList<Object>();
- static Object logEntry(String name, Object... args) {
- return Arrays.asList(name, Arrays.asList(args));
- }
- static Object called(String name, Object... args) {
- Object entry = logEntry(name, args);
- calledLog.add(entry);
- return entry;
- }
- static void assertCalled(String name, Object... args) {
- Object expected = logEntry(name, args);
- Object actual = calledLog.get(calledLog.size() - 1);
- if (expected.equals(actual) && verbosity < 9) return;
- System.out.println("assertCalled "+name+":");
- System.out.println("expected: "+expected);
- System.out.println("actual: "+actual);
- System.out.println("ex. types: "+getClasses(expected));
- System.out.println("act. types: "+getClasses(actual));
- assertEquals("previous method call", expected, actual);
- }
- static void printCalled(MethodHandle target, String name, Object... args) {
- if (verbosity >= 3)
- System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
- }
-
- static Object castToWrapper(Object value, Class<?> dst) {
- Object wrap = null;
- if (value instanceof Number)
- wrap = castToWrapperOrNull(((Number)value).longValue(), dst);
- if (value instanceof Character)
- wrap = castToWrapperOrNull((char)(Character)value, dst);
- if (wrap != null) return wrap;
- return dst.cast(value);
- }
-
- static Object castToWrapperOrNull(long value, Class<?> dst) {
- if (dst == int.class || dst == Integer.class)
- return (int)(value);
- if (dst == long.class || dst == Long.class)
- return (long)(value);
- if (dst == char.class || dst == Character.class)
- return (char)(value);
- if (dst == short.class || dst == Short.class)
- return (short)(value);
- if (dst == float.class || dst == Float.class)
- return (float)(value);
- if (dst == double.class || dst == Double.class)
- return (double)(value);
- if (dst == byte.class || dst == Byte.class)
- return (byte)(value);
- if (dst == boolean.class || dst == boolean.class)
- return ((value % 29) & 1) == 0;
- return null;
- }
-
- static final int ONE_MILLION = (1000*1000), // first int value
- TEN_BILLION = (10*1000*1000*1000), // scale factor to reach upper 32 bits
- INITIAL_ARG_VAL = ONE_MILLION << 1; // <<1 makes space for sign bit;
- static long nextArgVal;
- static long nextArg(boolean moreBits) {
- long val = nextArgVal++;
- long sign = -(val & 1); // alternate signs
- val >>= 1;
- if (moreBits)
- // Guarantee some bits in the high word.
- // In any case keep the decimal representation simple-looking,
- // with lots of zeroes, so as not to make the printed decimal
- // strings unnecessarily noisy.
- val += (val % ONE_MILLION) * TEN_BILLION;
- return val ^ sign;
- }
- static int nextArg() {
- // Produce a 32-bit result something like ONE_MILLION+(smallint).
- // Example: 1_000_042.
- return (int) nextArg(false);
- }
- static long nextArg(Class<?> kind) {
- if (kind == long.class || kind == Long.class ||
- kind == double.class || kind == Double.class)
- // produce a 64-bit result something like
- // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
- // Example: 10_000_420_001_000_042.
- return nextArg(true);
- return (long) nextArg();
- }
-
- static Object randomArg(Class<?> param) {
- Object wrap = castToWrapperOrNull(nextArg(param), param);
- if (wrap != null) {
- return wrap;
- }
-// import sun.dyn.util.Wrapper;
-// Wrapper wrap = Wrapper.forBasicType(dst);
-// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
-// wrap = Wrapper.forWrapperType(dst);
-// if (wrap != Wrapper.OBJECT)
-// return wrap.wrap(nextArg++);
- if (param.isInterface()) {
- for (Class<?> c : param.getClasses()) {
- if (param.isAssignableFrom(c) && !c.isInterface())
- { param = c; break; }
- }
- }
- if (param.isInterface() || param.isAssignableFrom(String.class))
- return "#"+nextArg();
- else
- try {
- return param.newInstance();
- } catch (InstantiationException ex) {
- } catch (IllegalAccessException ex) {
- }
- return null; // random class not Object, String, Integer, etc.
- }
- static Object[] randomArgs(Class<?>... params) {
- Object[] args = new Object[params.length];
- for (int i = 0; i < args.length; i++)
- args[i] = randomArg(params[i]);
- return args;
- }
- static Object[] randomArgs(int nargs, Class<?> param) {
- Object[] args = new Object[nargs];
- for (int i = 0; i < args.length; i++)
- args[i] = randomArg(param);
- return args;
- }
-
- static final Object ANON_OBJ = new Object();
- static Object zeroArg(Class<?> param) {
- Object x = castToWrapperOrNull(0L, param);
- if (x != null) return x;
- if (param.isInterface() || param.isAssignableFrom(String.class)) return "\"\"";
- if (param == Object.class) return ANON_OBJ;
- if (param.getComponentType() != null) return Array.newInstance(param.getComponentType(), 0);
- return null;
- }
- static Object[] zeroArgs(Class<?>... params) {
- Object[] args = new Object[params.length];
- for (int i = 0; i < args.length; i++)
- args[i] = zeroArg(params[i]);
- return args;
- }
- static Object[] zeroArgs(List<Class<?>> params) {
- return zeroArgs(params.toArray(new Class<?>[0]));
- }
-
- static <T, E extends T> T[] array(Class<T[]> atype, E... a) {
- return Arrays.copyOf(a, a.length, atype);
- }
- static <T> T[] cat(T[] a, T... b) {
- int alen = a.length, blen = b.length;
- if (blen == 0) return a;
- T[] c = Arrays.copyOf(a, alen + blen);
- System.arraycopy(b, 0, c, alen, blen);
- return c;
- }
- static Integer[] boxAll(int... vx) {
- Integer[] res = new Integer[vx.length];
- for (int i = 0; i < res.length; i++) {
- res[i] = vx[i];
- }
- return res;
- }
- static Object getClasses(Object x) {
- if (x == null) return x;
- if (x instanceof String) return x; // keep the name
- if (x instanceof List) {
- // recursively report classes of the list elements
- Object[] xa = ((List)x).toArray();
- for (int i = 0; i < xa.length; i++)
- xa[i] = getClasses(xa[i]);
- return Arrays.asList(xa);
- }
- return x.getClass().getSimpleName();
- }
-
- static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) {
- return changeArgTypes(target, 0, 999, argType);
- }
- static MethodHandle changeArgTypes(MethodHandle target,
- int beg, int end, Class<?> argType) {
- MethodType targetType = target.type();
- end = Math.min(end, targetType.parameterCount());
- ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList());
- Collections.fill(argTypes.subList(beg, end), argType);
- MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
- return MethodHandles.convertArguments(target, ttype2);
- }
-
- // This lookup is good for all members in and under InvokeGenericTest.
- static final Lookup LOOKUP = MethodHandles.lookup();
-
- Map<List<Class<?>>, MethodHandle> CALLABLES = new HashMap<List<Class<?>>, MethodHandle>();
- MethodHandle callable(List<Class<?>> params) {
- MethodHandle mh = CALLABLES.get(params);
- if (mh == null) {
- mh = collector_MH.asType(methodType(Object.class, params));
- CALLABLES.put(params, mh);
- }
- return mh;
- }
- MethodHandle callable(Class<?>... params) {
- return callable(Arrays.asList(params));
- }
- private static Object collector(Object... args) {
- return Arrays.asList(args);
- }
- private static final MethodHandle collector_MH;
- static {
- try {
- collector_MH
- = LOOKUP.findStatic(LOOKUP.lookupClass(),
- "collector",
- methodType(Object.class, Object[].class));
- } catch (ReflectiveOperationException ex) {
- throw new RuntimeException(ex);
- }
- }
-
- @Test
- public void testSimple() throws Throwable {
- startTest("testSimple");
- countTest();
- String[] args = { "one", "two" };
- MethodHandle mh = callable(Object.class, String.class);
- Object res; List resl;
- res = resl = (List) mh.invokeGeneric((String)args[0], (Object)args[1]);
- //System.out.println(res);
- assertEquals(Arrays.asList(args), res);
- }
-
- @Test
- public void testWrongArgumentCount() throws Throwable {
- startTest("testWrongArgumentCount");
- for (int i = 0; i <= 10; i++) {
- testWrongArgumentCount(Collections.<Class<?>>nCopies(i, Integer.class));
- if (i <= 4) {
- testWrongArgumentCount(Collections.<Class<?>>nCopies(i, int.class));
- testWrongArgumentCount(Collections.<Class<?>>nCopies(i, long.class));
- }
- }
- }
- public void testWrongArgumentCount(List<Class<?>> params) throws Throwable {
- int max = params.size();
- for (int i = 0; i < max; i++) {
- List<Class<?>> params2 = params.subList(0, i);
- for (int k = 0; k <= 2; k++) {
- if (k == 1) params = methodType(Object.class, params).generic().parameterList();
- if (k == 2) params2 = methodType(Object.class, params2).generic().parameterList();
- testWrongArgumentCount(params, params2);
- testWrongArgumentCount(params2, params);
- }
- }
- }
- public void testWrongArgumentCount(List<Class<?>> expect, List<Class<?>> observe) throws Throwable {
- countTest(false);
- if (expect.equals(observe))
- assert(false);
- MethodHandle target = callable(expect);
- Object[] args = zeroArgs(observe);
- Object junk;
- try {
- switch (args.length) {
- case 0:
- junk = target.invokeGeneric(); break;
- case 1:
- junk = target.invokeGeneric(args[0]); break;
- case 2:
- junk = target.invokeGeneric(args[0], args[1]); break;
- case 3:
- junk = target.invokeGeneric(args[0], args[1], args[2]); break;
- case 4:
- junk = target.invokeGeneric(args[0], args[1], args[2], args[3]); break;
- default:
- junk = target.invokeWithArguments(args); break;
- }
- } catch (WrongMethodTypeException ex) {
- return;
- } catch (Exception ex) {
- throw new RuntimeException("wrong exception calling "+target+target.type()+" on "+Arrays.asList(args)+" : "+ex);
- }
- throw new RuntimeException("bad success calling "+target+target.type()+" on "+Arrays.asList(args));
- }
-
- /** Make a list of all combinations of the given types, with the given arities.
- * A void return type is possible iff the first type is void.class.
- */
- static List<MethodType> allMethodTypes(int minargc, int maxargc, Class<?>... types) {
- ArrayList<MethodType> result = new ArrayList<MethodType>();
- if (types.length > 0) {
- ArrayList<MethodType> argcTypes = new ArrayList<MethodType>();
- // build arity-zero types first
- for (Class<?> rtype : types) {
- argcTypes.add(MethodType.methodType(rtype));
- }
- if (types[0] == void.class)
- // void is not an argument type
- types = Arrays.copyOfRange(types, 1, types.length);
- for (int argc = 0; argc <= maxargc; argc++) {
- if (argc >= minargc)
- result.addAll(argcTypes);
- if (argc >= maxargc)
- break;
- ArrayList<MethodType> prevTypes = argcTypes;
- argcTypes = new ArrayList<MethodType>();
- for (MethodType prevType : prevTypes) {
- for (Class<?> ptype : types) {
- argcTypes.add(prevType.insertParameterTypes(argc, ptype));
- }
- }
- }
- }
- return Collections.unmodifiableList(result);
- }
- static List<MethodType> allMethodTypes(int argc, Class<?>... types) {
- return allMethodTypes(argc, argc, types);
- }
-
- interface RandomInterface { }
-
- MethodHandle toString_MH;
-
- @Test
- public void testReferenceConversions() throws Throwable {
- startTest("testReferenceConversions");
- toString_MH = LOOKUP.
- findVirtual(Object.class, "toString", MethodType.methodType(String.class));
- String[] args = { "one", "two" };
- for (MethodType type : allMethodTypes(2, Object.class, String.class, RandomInterface.class)) {
- testReferenceConversions(type, args);
- }
- }
- public void testReferenceConversions(MethodType type, Object... args) throws Throwable {
- countTest();
- if (verbosity > 3) System.out.println("target type: "+type);
- MethodHandle mh = callable(type.parameterList());
- MethodHandle tsdrop = MethodHandles.dropArguments(toString_MH, 1, type.parameterList());
- mh = MethodHandles.foldArguments(tsdrop, mh);
- mh = mh.asType(type);
- Object res = mh.invokeGeneric((String)args[0], (Object)args[1]);
- //System.out.println(res);
- assertEquals(Arrays.asList(args).toString(), res);
- }
-
-
- @Test @Ignore("known failure pending 6939861")
- public void testBoxConversions() throws Throwable {
- startTest("testBoxConversions");
- countTest();
- Integer[] args = { 1, 2 };
- MethodHandle mh = callable(Object.class, int.class);
- Object res; List resl;
- res = resl = (List) mh.invokeGeneric((int)args[0], (Object)args[1]);
- //System.out.println(res);
- assertEquals(Arrays.asList(args), res);
- }
-
-}
--- a/jdk/test/java/dyn/JavaDocExamplesTest.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary example code used in javadoc for java.dyn API
- * @compile -XDallowTransitionalJSR292=no JavaDocExamplesTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamplesTest
- */
-
-/*
----- To run outside jtreg:
-$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
- $DAVINCI/sources/jdk/test/java/dyn/JavaDocExamplesTest.java
-$ $JAVA7X_HOME/bin/java -cp $JUNIT4_JAR:/tmp/Classes \
- -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
- -Dtest.java.dyn.JavaDocExamplesTest.verbosity=1 \
- test.java.dyn.JavaDocExamplesTest
-----
-*/
-
-package test.java.dyn;
-
-import java.dyn.*;
-import static java.dyn.MethodHandles.*;
-import static java.dyn.MethodType.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.junit.*;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-
-
-/**
- * @author jrose
- */
-public class JavaDocExamplesTest {
- /** Wrapper for running the JUnit tests in this module.
- * Put JUnit on the classpath!
- */
- public static void main(String... ignore) {
- org.junit.runner.JUnitCore.runClasses(JavaDocExamplesTest.class);
- }
- // How much output?
- static int verbosity = Integer.getInteger("test.java.dyn.JavaDocExamplesTest.verbosity", 0);
-
-{}
-static final private Lookup LOOKUP = lookup();
-// static final private MethodHandle CONCAT_1 = LOOKUP.findVirtual(String.class,
-// "concat", methodType(String.class, String.class));
-// static final private MethodHandle HASHCODE_1 = LOOKUP.findVirtual(Object.class,
-// "hashCode", methodType(int.class));
-
-// form required if ReflectiveOperationException is intercepted:
-static final private MethodHandle CONCAT_2, HASHCODE_2;
-static {
- try {
- CONCAT_2 = LOOKUP.findVirtual(String.class,
- "concat", methodType(String.class, String.class));
- HASHCODE_2 = LOOKUP.findVirtual(Object.class,
- "hashCode", methodType(int.class));
- } catch (ReflectiveOperationException ex) {
- throw new RuntimeException(ex);
- }
-}
-{}
-
- @Test public void testFindVirtual() throws Throwable {
-{}
-MethodHandle CONCAT_3 = LOOKUP.findVirtual(String.class,
- "concat", methodType(String.class, String.class));
-MethodHandle HASHCODE_3 = LOOKUP.findVirtual(Object.class,
- "hashCode", methodType(int.class));
-//assertEquals("xy", (String) CONCAT_1.invokeExact("x", "y"));
-assertEquals("xy", (String) CONCAT_2.invokeExact("x", "y"));
-assertEquals("xy", (String) CONCAT_3.invokeExact("x", "y"));
-//assertEquals("xy".hashCode(), (int) HASHCODE_1.invokeExact((Object)"xy"));
-assertEquals("xy".hashCode(), (int) HASHCODE_2.invokeExact((Object)"xy"));
-assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy"));
-{}
- }
- @Test public void testDropArguments() throws Throwable {
- {{
-{} /// JAVADOC
-MethodHandle cat = lookup().findVirtual(String.class,
- "concat", methodType(String.class, String.class));
-assertEquals("xy", (String) cat.invokeExact("x", "y"));
-MethodHandle d0 = dropArguments(cat, 0, String.class);
-assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
-MethodHandle d1 = dropArguments(cat, 1, String.class);
-assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
-MethodHandle d2 = dropArguments(cat, 2, String.class);
-assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
-MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
-assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
- }}
- }
-
- @Test public void testFilterArguments() throws Throwable {
- {{
-{} /// JAVADOC
-MethodHandle cat = lookup().findVirtual(String.class,
- "concat", methodType(String.class, String.class));
-MethodHandle upcase = lookup().findVirtual(String.class,
- "toUpperCase", methodType(String.class));
-assertEquals("xy", (String) cat.invokeExact("x", "y"));
-MethodHandle f0 = filterArguments(cat, 0, upcase);
-assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
-MethodHandle f1 = filterArguments(cat, 1, upcase);
-assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
-MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
-assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
- }}
- }
-
- static void assertEquals(Object exp, Object act) {
- if (verbosity > 0)
- System.out.println("result: "+act);
- Assert.assertEquals(exp, act);
- }
-
- @Test public void testMethodHandlesSummary() throws Throwable {
- {{
-{} /// JAVADOC
-Object x, y; String s; int i;
-MethodType mt; MethodHandle mh;
-MethodHandles.Lookup lookup = MethodHandles.lookup();
-// mt is (char,char)String
-mt = MethodType.methodType(String.class, char.class, char.class);
-mh = lookup.findVirtual(String.class, "replace", mt);
-s = (String) mh.invokeExact("daddy",'d','n');
-// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
-assert(s.equals("nanny"));
-// weakly typed invocation (using MHs.invoke)
-s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
-assert(s.equals("savvy"));
-// mt is (Object[])List
-mt = MethodType.methodType(java.util.List.class, Object[].class);
-mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
-assert(mh.isVarargsCollector());
-x = mh.invokeGeneric("one", "two");
-// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
-assert(x.equals(java.util.Arrays.asList("one","two")));
-// mt is (Object,Object,Object)Object
-mt = MethodType.genericMethodType(3);
-mh = mh.asType(mt);
-x = mh.invokeExact((Object)1, (Object)2, (Object)3);
-// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
-assert(x.equals(java.util.Arrays.asList(1,2,3)));
-// mt is { => int}
-mt = MethodType.methodType(int.class);
-mh = lookup.findVirtual(java.util.List.class, "size", mt);
-i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
-// invokeExact(Ljava/util/List;)I
-assert(i == 3);
-mt = MethodType.methodType(void.class, String.class);
-mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
-mh.invokeExact(System.out, "Hello, world.");
-// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
-{}
- }}
- }
-
- @Test public void testAsVarargsCollector() throws Throwable {
- {{
-{} /// JAVADOC
-MethodHandle asList = publicLookup()
- .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
- .asVarargsCollector(Object[].class);
-assertEquals("[]", asList.invokeGeneric().toString());
-assertEquals("[1]", asList.invokeGeneric(1).toString());
-assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString());
-Object[] argv = { "three", "thee", "tee" };
-assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString());
-List ls = (List) asList.invokeGeneric((Object)argv);
-assertEquals(1, ls.size());
-assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
- }}
- }
-
- @Test public void testVarargsCollectorSuppression() throws Throwable {
- {{
-{} /// JAVADOC
-MethodHandle vamh = publicLookup()
- .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
- .asVarargsCollector(Object[].class);
-MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
-assert(vamh.type().equals(mh.type()));
-assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString());
-boolean failed = false;
-try { mh.invokeGeneric(1,2,3); }
-catch (WrongMethodTypeException ex) { failed = true; }
-assert(failed);
-{}
- }}
- }
-}
--- a/jdk/test/java/dyn/MethodHandlesTest.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2400 +0,0 @@
-/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/* @test
- * @summary unit tests for java.dyn.MethodHandles
- * @compile -source 7 -target 7 -XDallowTransitionalJSR292=no MethodHandlesTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.MethodHandlesTest
- */
-
-package test.java.dyn;
-
-import java.dyn.*;
-import java.dyn.MethodHandles.Lookup;
-import java.lang.reflect.*;
-import java.util.*;
-import org.junit.*;
-import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-
-
-/**
- *
- * @author jrose
- */
-public class MethodHandlesTest {
- // How much output?
- static int verbosity = 0;
- static {
- String vstr = System.getProperty("test.java.dyn.MethodHandlesTest.verbosity");
- if (vstr != null) verbosity = Integer.parseInt(vstr);
- }
-
- // Set this true during development if you want to fast-forward to
- // a particular new, non-working test. Tests which are known to
- // work (or have recently worked) test this flag and return on true.
- static boolean CAN_SKIP_WORKING = false;
- //static { CAN_SKIP_WORKING = true; }
-
- // Set true to test more calls. If false, some tests are just
- // lookups, without exercising the actual method handle.
- static boolean DO_MORE_CALLS = true;
-
- @Test
- public void testFirst() throws Throwable {
- verbosity += 9; try {
- // left blank for debugging
- } finally { printCounts(); verbosity -= 9; }
- }
-
- // current failures
- @Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
- public void testFail_1() throws Throwable {
- // AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters
- testSpreadArguments(int.class, 0, 6);
- }
- @Test @Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args")
- public void testFail_2() throws Throwable {
- // if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes:
- testSpreadArguments(Object.class, 0, 2);
- }
- @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
- public void testFail_3() throws Throwable {
- // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
- testSpreadArguments(int.class, 1, 2);
- }
- @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
- public void testFail_4() throws Throwable {
- // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
- testCollectArguments(int.class, 1, 2);
- }
- @Test @Ignore("cannot collect leading primitive types")
- public void testFail_5() throws Throwable {
- // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
- testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class));
- }
- @Test @Ignore("should not insert arguments beyond MethodHandlePushLimit")
- public void testFail_6() throws Throwable {
- // ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13
- testInsertArguments(0, 0, MAX_ARG_INCREASE+10);
- }
- static final int MAX_ARG_INCREASE = 3;
-
- public MethodHandlesTest() {
- }
-
- @Before
- public void checkImplementedPlatform() {
- boolean platformOK = false;
- Properties properties = System.getProperties();
- String vers = properties.getProperty("java.vm.version");
- String name = properties.getProperty("java.vm.name");
- String arch = properties.getProperty("os.arch");
- if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
- arch.equals("sparc") || arch.equals("sparcv9")) &&
- (name.contains("Client") || name.contains("Server"))
- ) {
- platformOK = true;
- } else {
- System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
- }
- assumeTrue(platformOK);
- }
-
- String testName;
- static int allPosTests, allNegTests;
- int posTests, negTests;
- @After
- public void printCounts() {
- if (verbosity >= 2 && (posTests | negTests) != 0) {
- System.out.println();
- if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run");
- if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run");
- allPosTests += posTests;
- allNegTests += negTests;
- posTests = negTests = 0;
- }
- }
- void countTest(boolean positive) {
- if (positive) ++posTests;
- else ++negTests;
- }
- void countTest() { countTest(true); }
- void startTest(String name) {
- if (testName != null) printCounts();
- if (verbosity >= 1)
- System.out.println(name);
- posTests = negTests = 0;
- testName = name;
- }
-
- @BeforeClass
- public static void setUpClass() throws Exception {
- calledLog.clear();
- calledLog.add(null);
- nextArgVal = INITIAL_ARG_VAL;
- }
-
- @AfterClass
- public static void tearDownClass() throws Exception {
- int posTests = allPosTests, negTests = allNegTests;
- if (verbosity >= 2 && (posTests | negTests) != 0) {
- System.out.println();
- if (posTests != 0) System.out.println("=== "+posTests+" total positive test cases");
- if (negTests != 0) System.out.println("=== "+negTests+" total negative test cases");
- }
- }
-
- static List<Object> calledLog = new ArrayList<Object>();
- static Object logEntry(String name, Object... args) {
- return Arrays.asList(name, Arrays.asList(args));
- }
- static Object called(String name, Object... args) {
- Object entry = logEntry(name, args);
- calledLog.add(entry);
- return entry;
- }
- static void assertCalled(String name, Object... args) {
- Object expected = logEntry(name, args);
- Object actual = calledLog.get(calledLog.size() - 1);
- if (expected.equals(actual) && verbosity < 9) return;
- System.out.println("assertCalled "+name+":");
- System.out.println("expected: "+expected);
- System.out.println("actual: "+actual);
- System.out.println("ex. types: "+getClasses(expected));
- System.out.println("act. types: "+getClasses(actual));
- assertEquals("previous method call", expected, actual);
- }
- static void printCalled(MethodHandle target, String name, Object... args) {
- if (verbosity >= 3)
- System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
- }
-
- static Object castToWrapper(Object value, Class<?> dst) {
- Object wrap = null;
- if (value instanceof Number)
- wrap = castToWrapperOrNull(((Number)value).longValue(), dst);
- if (value instanceof Character)
- wrap = castToWrapperOrNull((char)(Character)value, dst);
- if (wrap != null) return wrap;
- return dst.cast(value);
- }
-
- static Object castToWrapperOrNull(long value, Class<?> dst) {
- if (dst == int.class || dst == Integer.class)
- return (int)(value);
- if (dst == long.class || dst == Long.class)
- return (long)(value);
- if (dst == char.class || dst == Character.class)
- return (char)(value);
- if (dst == short.class || dst == Short.class)
- return (short)(value);
- if (dst == float.class || dst == Float.class)
- return (float)(value);
- if (dst == double.class || dst == Double.class)
- return (double)(value);
- if (dst == byte.class || dst == Byte.class)
- return (byte)(value);
- if (dst == boolean.class || dst == boolean.class)
- return ((value % 29) & 1) == 0;
- return null;
- }
-
- static final int ONE_MILLION = (1000*1000), // first int value
- TEN_BILLION = (10*1000*1000*1000), // scale factor to reach upper 32 bits
- INITIAL_ARG_VAL = ONE_MILLION << 1; // <<1 makes space for sign bit;
- static long nextArgVal;
- static long nextArg(boolean moreBits) {
- long val = nextArgVal++;
- long sign = -(val & 1); // alternate signs
- val >>= 1;
- if (moreBits)
- // Guarantee some bits in the high word.
- // In any case keep the decimal representation simple-looking,
- // with lots of zeroes, so as not to make the printed decimal
- // strings unnecessarily noisy.
- val += (val % ONE_MILLION) * TEN_BILLION;
- return val ^ sign;
- }
- static int nextArg() {
- // Produce a 32-bit result something like ONE_MILLION+(smallint).
- // Example: 1_000_042.
- return (int) nextArg(false);
- }
- static long nextArg(Class<?> kind) {
- if (kind == long.class || kind == Long.class ||
- kind == double.class || kind == Double.class)
- // produce a 64-bit result something like
- // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
- // Example: 10_000_420_001_000_042.
- return nextArg(true);
- return (long) nextArg();
- }
-
- static Object randomArg(Class<?> param) {
- Object wrap = castToWrapperOrNull(nextArg(param), param);
- if (wrap != null) {
- return wrap;
- }
-// import sun.dyn.util.Wrapper;
-// Wrapper wrap = Wrapper.forBasicType(dst);
-// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
-// wrap = Wrapper.forWrapperType(dst);
-// if (wrap != Wrapper.OBJECT)
-// return wrap.wrap(nextArg++);
- if (param.isInterface()) {
- for (Class<?> c : param.getClasses()) {
- if (param.isAssignableFrom(c) && !c.isInterface())
- { param = c; break; }
- }
- }
- if (param.isInterface() || param.isAssignableFrom(String.class))
- return "#"+nextArg();
- else
- try {
- return param.newInstance();
- } catch (InstantiationException ex) {
- } catch (IllegalAccessException ex) {
- }
- return null; // random class not Object, String, Integer, etc.
- }
- static Object[] randomArgs(Class<?>... params) {
- Object[] args = new Object[params.length];
- for (int i = 0; i < args.length; i++)
- args[i] = randomArg(params[i]);
- return args;
- }
- static Object[] randomArgs(int nargs, Class<?> param) {
- Object[] args = new Object[nargs];
- for (int i = 0; i < args.length; i++)
- args[i] = randomArg(param);
- return args;
- }
-
- static <T, E extends T> T[] array(Class<T[]> atype, E... a) {
- return Arrays.copyOf(a, a.length, atype);
- }
- static <T> T[] cat(T[] a, T... b) {
- int alen = a.length, blen = b.length;
- if (blen == 0) return a;
- T[] c = Arrays.copyOf(a, alen + blen);
- System.arraycopy(b, 0, c, alen, blen);
- return c;
- }
- static Integer[] boxAll(int... vx) {
- Integer[] res = new Integer[vx.length];
- for (int i = 0; i < res.length; i++) {
- res[i] = vx[i];
- }
- return res;
- }
- static Object getClasses(Object x) {
- if (x == null) return x;
- if (x instanceof String) return x; // keep the name
- if (x instanceof List) {
- // recursively report classes of the list elements
- Object[] xa = ((List)x).toArray();
- for (int i = 0; i < xa.length; i++)
- xa[i] = getClasses(xa[i]);
- return Arrays.asList(xa);
- }
- return x.getClass().getSimpleName();
- }
-
- /** Return lambda(arg...[arity]) { new Object[]{ arg... } } */
- static MethodHandle varargsList(int arity) {
- return ValueConversions.varargsList(arity);
- }
- /** Return lambda(arg...[arity]) { Arrays.asList(arg...) } */
- static MethodHandle varargsArray(int arity) {
- return ValueConversions.varargsArray(arity);
- }
- /** Variation of varargsList, but with the given rtype. */
- static MethodHandle varargsList(int arity, Class<?> rtype) {
- MethodHandle list = varargsList(arity);
- MethodType listType = list.type().changeReturnType(rtype);
- if (List.class.isAssignableFrom(rtype) || rtype == void.class || rtype == Object.class) {
- // OK
- } else if (rtype.isAssignableFrom(String.class)) {
- if (LIST_TO_STRING == null)
- try {
- LIST_TO_STRING = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToString",
- MethodType.methodType(String.class, List.class));
- } catch (Exception ex) { throw new RuntimeException(ex); }
- list = MethodHandles.filterReturnValue(list, LIST_TO_STRING);
- } else if (rtype.isPrimitive()) {
- if (LIST_TO_INT == null)
- try {
- LIST_TO_INT = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToInt",
- MethodType.methodType(int.class, List.class));
- } catch (Exception ex) { throw new RuntimeException(ex); }
- list = MethodHandles.filterReturnValue(list, LIST_TO_INT);
- list = MethodHandles.explicitCastArguments(list, listType);
- } else {
- throw new RuntimeException("varargsList: "+rtype);
- }
- return list.asType(listType);
- }
- private static MethodHandle LIST_TO_STRING, LIST_TO_INT;
- private static String listToString(List x) { return x.toString(); }
- private static int listToInt(List x) { return x.toString().hashCode(); }
-
- static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) {
- return changeArgTypes(target, 0, 999, argType);
- }
- static MethodHandle changeArgTypes(MethodHandle target,
- int beg, int end, Class<?> argType) {
- MethodType targetType = target.type();
- end = Math.min(end, targetType.parameterCount());
- ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList());
- Collections.fill(argTypes.subList(beg, end), argType);
- MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
- return MethodHandles.convertArguments(target, ttype2);
- }
-
- // This lookup is good for all members in and under MethodHandlesTest.
- static final Lookup PRIVATE = MethodHandles.lookup();
- // This lookup is good for package-private members but not private ones.
- static final Lookup PACKAGE = PackageSibling.lookup();
- // This lookup is good only for public members.
- static final Lookup PUBLIC = MethodHandles.publicLookup();
-
- // Subject methods...
- static class Example implements IntExample {
- final String name;
- public Example() { name = "Example#"+nextArg(); }
- protected Example(String name) { this.name = name; }
- protected Example(int x) { this(); called("protected <init>", this, x); }
- @Override public String toString() { return name; }
-
- public void v0() { called("v0", this); }
- void pkg_v0() { called("pkg_v0", this); }
- private void pri_v0() { called("pri_v0", this); }
- public static void s0() { called("s0"); }
- static void pkg_s0() { called("pkg_s0"); }
- private static void pri_s0() { called("pri_s0"); }
-
- public Object v1(Object x) { return called("v1", this, x); }
- public Object v2(Object x, Object y) { return called("v2", this, x, y); }
- public Object v2(Object x, int y) { return called("v2", this, x, y); }
- public Object v2(int x, Object y) { return called("v2", this, x, y); }
- public Object v2(int x, int y) { return called("v2", this, x, y); }
- public static Object s1(Object x) { return called("s1", x); }
- public static Object s2(int x) { return called("s2", x); }
- public static Object s3(long x) { return called("s3", x); }
- public static Object s4(int x, int y) { return called("s4", x, y); }
- public static Object s5(long x, int y) { return called("s5", x, y); }
- public static Object s6(int x, long y) { return called("s6", x, y); }
- public static Object s7(float x, double y) { return called("s7", x, y); }
-
- static final Lookup EXAMPLE = MethodHandles.lookup(); // for testing findSpecial
- }
- static final Lookup EXAMPLE = Example.EXAMPLE;
- public static class PubExample extends Example {
- public PubExample() { super("PubExample#"+nextArg()); }
- }
- static class SubExample extends Example {
- @Override public void v0() { called("Sub/v0", this); }
- @Override void pkg_v0() { called("Sub/pkg_v0", this); }
- private SubExample(int x) { called("<init>", this, x); }
- public SubExample() { super("SubExample#"+nextArg()); }
- }
- public static interface IntExample {
- public void v0();
- public static class Impl implements IntExample {
- public void v0() { called("Int/v0", this); }
- final String name;
- public Impl() { name = "Impl#"+nextArg(); }
- @Override public String toString() { return name; }
- }
- }
-
- static final Object[][][] ACCESS_CASES = {
- { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false
- { { false, PUBLIC }, { false, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[1]: only PRIVATE
- { { false, PUBLIC }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[2]: PUBLIC false
- { { true, PUBLIC }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[3]: all true
- };
-
- static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) {
- Object[][] cases;
- if (name.contains("pri_") || isSpecial) {
- cases = ACCESS_CASES[1]; // PRIVATE only
- } else if (name.contains("pkg_") || !Modifier.isPublic(defc.getModifiers())) {
- cases = ACCESS_CASES[2]; // not PUBLIC
- } else {
- assertTrue(name.indexOf('_') < 0);
- boolean pubc = Modifier.isPublic(defc.getModifiers());
- if (pubc)
- cases = ACCESS_CASES[3]; // all access levels
- else
- cases = ACCESS_CASES[2]; // PACKAGE but not PUBLIC
- }
- if (defc != Example.class && cases[cases.length-1][1] == EXAMPLE)
- cases = Arrays.copyOfRange(cases, 0, cases.length-1);
- return cases;
- }
- static Object[][] accessCases(Class<?> defc, String name) {
- return accessCases(defc, name, false);
- }
-
- @Test
- public void testFindStatic() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("findStatic");
- testFindStatic(PubExample.class, void.class, "s0");
- testFindStatic(Example.class, void.class, "s0");
- testFindStatic(Example.class, void.class, "pkg_s0");
- testFindStatic(Example.class, void.class, "pri_s0");
-
- testFindStatic(Example.class, Object.class, "s1", Object.class);
- testFindStatic(Example.class, Object.class, "s2", int.class);
- testFindStatic(Example.class, Object.class, "s3", long.class);
- testFindStatic(Example.class, Object.class, "s4", int.class, int.class);
- testFindStatic(Example.class, Object.class, "s5", long.class, int.class);
- testFindStatic(Example.class, Object.class, "s6", int.class, long.class);
- testFindStatic(Example.class, Object.class, "s7", float.class, double.class);
-
- testFindStatic(false, PRIVATE, Example.class, void.class, "bogus");
- }
-
- void testFindStatic(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- for (Object[] ac : accessCases(defc, name)) {
- testFindStatic((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params);
- }
- }
- void testFindStatic(Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- testFindStatic(true, lookup, defc, ret, name, params);
- }
- void testFindStatic(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- countTest(positive);
- MethodType type = MethodType.methodType(ret, params);
- MethodHandle target = null;
- Exception noAccess = null;
- try {
- if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
- target = lookup.in(defc).findStatic(defc, name, type);
- } catch (ReflectiveOperationException ex) {
- noAccess = ex;
- if (name.contains("bogus"))
- assertTrue(noAccess instanceof NoSuchMethodException);
- else
- assertTrue(noAccess instanceof IllegalAccessException);
- }
- if (verbosity >= 3)
- System.out.println("findStatic "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target
- +(noAccess == null ? "" : " !! "+noAccess));
- if (positive && noAccess != null) throw noAccess;
- assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
- if (!positive) return; // negative test failed as expected
- assertEquals(type, target.type());
- assertNameStringContains(target, name);
- if (!DO_MORE_CALLS && lookup != PRIVATE) return;
- Object[] args = randomArgs(params);
- printCalled(target, name, args);
- target.invokeWithArguments(args);
- assertCalled(name, args);
- if (verbosity >= 1)
- System.out.print(':');
- }
-
- // rough check of name string
- static void assertNameStringContains(Object x, String s) {
- if (x.toString().contains(s)) return;
- assertEquals(s, x);
- }
-
- @Test
- public void testFindVirtual() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("findVirtual");
- testFindVirtual(Example.class, void.class, "v0");
- testFindVirtual(Example.class, void.class, "pkg_v0");
- testFindVirtual(Example.class, void.class, "pri_v0");
- testFindVirtual(Example.class, Object.class, "v1", Object.class);
- testFindVirtual(Example.class, Object.class, "v2", Object.class, Object.class);
- testFindVirtual(Example.class, Object.class, "v2", Object.class, int.class);
- testFindVirtual(Example.class, Object.class, "v2", int.class, Object.class);
- testFindVirtual(Example.class, Object.class, "v2", int.class, int.class);
- testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "bogus");
- // test dispatch
- testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/v0");
- testFindVirtual(SubExample.class, Example.class, void.class, "Sub/v0");
- testFindVirtual(SubExample.class, IntExample.class, void.class, "Sub/v0");
- testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/pkg_v0");
- testFindVirtual(SubExample.class, Example.class, void.class, "Sub/pkg_v0");
- testFindVirtual(Example.class, IntExample.class, void.class, "v0");
- testFindVirtual(IntExample.Impl.class, IntExample.class, void.class, "Int/v0");
- }
-
- void testFindVirtual(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- Class<?> rcvc = defc;
- testFindVirtual(rcvc, defc, ret, name, params);
- }
- void testFindVirtual(Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- for (Object[] ac : accessCases(defc, name)) {
- testFindVirtual((Boolean)ac[0], (Lookup)ac[1], rcvc, defc, ret, name, params);
- }
- }
- void testFindVirtual(Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- testFindVirtual(true, lookup, rcvc, defc, ret, name, params);
- }
- void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- countTest(positive);
- String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo
- MethodType type = MethodType.methodType(ret, params);
- MethodHandle target = null;
- Exception noAccess = null;
- try {
- if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
- target = lookup.in(defc).findVirtual(defc, methodName, type);
- } catch (ReflectiveOperationException ex) {
- noAccess = ex;
- if (name.contains("bogus"))
- assertTrue(noAccess instanceof NoSuchMethodException);
- else
- assertTrue(noAccess instanceof IllegalAccessException);
- }
- if (verbosity >= 3)
- System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target
- +(noAccess == null ? "" : " !! "+noAccess));
- if (positive && noAccess != null) throw noAccess;
- assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
- if (!positive) return; // negative test failed as expected
- Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
- MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
- assertEquals(typeWithSelf, target.type());
- assertNameStringContains(target, methodName);
- if (!DO_MORE_CALLS && lookup != PRIVATE) return;
- Object[] argsWithSelf = randomArgs(paramsWithSelf);
- if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc);
- printCalled(target, name, argsWithSelf);
- target.invokeWithArguments(argsWithSelf);
- assertCalled(name, argsWithSelf);
- if (verbosity >= 1)
- System.out.print(':');
- }
-
- @Test
- public void testFindSpecial() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("findSpecial");
- testFindSpecial(SubExample.class, Example.class, void.class, "v0");
- testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0");
- // Do some negative testing:
- testFindSpecial(false, EXAMPLE, SubExample.class, Example.class, void.class, "bogus");
- testFindSpecial(false, PRIVATE, SubExample.class, Example.class, void.class, "bogus");
- for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) {
- testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0");
- testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class);
- testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0");
- }
- }
-
- void testFindSpecial(Class<?> specialCaller,
- Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- testFindSpecial(true, EXAMPLE, specialCaller, defc, ret, name, params);
- testFindSpecial(true, PRIVATE, specialCaller, defc, ret, name, params);
- testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params);
- testFindSpecial(false, PUBLIC, specialCaller, defc, ret, name, params);
- }
- void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller,
- Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- countTest(positive);
- MethodType type = MethodType.methodType(ret, params);
- MethodHandle target = null;
- Exception noAccess = null;
- try {
- if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
- if (verbosity >= 5) System.out.println(" lookup => "+lookup.in(specialCaller));
- target = lookup.in(specialCaller).findSpecial(defc, name, type, specialCaller);
- } catch (ReflectiveOperationException ex) {
- noAccess = ex;
- if (name.contains("bogus"))
- assertTrue(noAccess instanceof NoSuchMethodException);
- else
- assertTrue(noAccess instanceof IllegalAccessException);
- }
- if (verbosity >= 3)
- System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target
- +(target == null ? "" : target.type())
- +(noAccess == null ? "" : " !! "+noAccess));
- if (positive && noAccess != null) throw noAccess;
- assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
- if (!positive) return; // negative test failed as expected
- assertEquals(specialCaller, target.type().parameterType(0));
- assertEquals(type, target.type().dropParameterTypes(0,1));
- Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params);
- MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
- assertNameStringContains(target, name);
- if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE) return;
- Object[] args = randomArgs(paramsWithSelf);
- printCalled(target, name, args);
- target.invokeWithArguments(args);
- assertCalled(name, args);
- }
-
- @Test
- public void testBind() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("bind");
- testBind(Example.class, void.class, "v0");
- testBind(Example.class, void.class, "pkg_v0");
- testBind(Example.class, void.class, "pri_v0");
- testBind(Example.class, Object.class, "v1", Object.class);
- testBind(Example.class, Object.class, "v2", Object.class, Object.class);
- testBind(Example.class, Object.class, "v2", Object.class, int.class);
- testBind(Example.class, Object.class, "v2", int.class, Object.class);
- testBind(Example.class, Object.class, "v2", int.class, int.class);
- testBind(false, PRIVATE, Example.class, void.class, "bogus");
- testBind(SubExample.class, void.class, "Sub/v0");
- testBind(SubExample.class, void.class, "Sub/pkg_v0");
- testBind(IntExample.Impl.class, void.class, "Int/v0");
- }
-
- void testBind(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- for (Object[] ac : accessCases(defc, name)) {
- testBind((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params);
- }
- }
-
- void testBind(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- countTest(positive);
- String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo
- MethodType type = MethodType.methodType(ret, params);
- Object receiver = randomArg(defc);
- MethodHandle target = null;
- Exception noAccess = null;
- try {
- if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
- target = lookup.in(defc).bind(receiver, methodName, type);
- } catch (ReflectiveOperationException ex) {
- noAccess = ex;
- if (name.contains("bogus"))
- assertTrue(noAccess instanceof NoSuchMethodException);
- else
- assertTrue(noAccess instanceof IllegalAccessException);
- }
- if (verbosity >= 3)
- System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target
- +(noAccess == null ? "" : " !! "+noAccess));
- if (positive && noAccess != null) throw noAccess;
- assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
- if (!positive) return; // negative test failed as expected
- assertEquals(type, target.type());
- Object[] args = randomArgs(params);
- printCalled(target, name, args);
- target.invokeWithArguments(args);
- Object[] argsWithReceiver = cat(array(Object[].class, receiver), args);
- assertCalled(name, argsWithReceiver);
- if (verbosity >= 1)
- System.out.print(':');
- }
-
- @Test
- public void testUnreflect() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("unreflect");
- testUnreflect(Example.class, true, void.class, "s0");
- testUnreflect(Example.class, true, void.class, "pkg_s0");
- testUnreflect(Example.class, true, void.class, "pri_s0");
-
- testUnreflect(Example.class, true, Object.class, "s1", Object.class);
- testUnreflect(Example.class, true, Object.class, "s2", int.class);
- testUnreflect(Example.class, true, Object.class, "s3", long.class);
- testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class);
- testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class);
- testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class);
-
- testUnreflect(Example.class, false, void.class, "v0");
- testUnreflect(Example.class, false, void.class, "pkg_v0");
- testUnreflect(Example.class, false, void.class, "pri_v0");
- testUnreflect(Example.class, false, Object.class, "v1", Object.class);
- testUnreflect(Example.class, false, Object.class, "v2", Object.class, Object.class);
- testUnreflect(Example.class, false, Object.class, "v2", Object.class, int.class);
- testUnreflect(Example.class, false, Object.class, "v2", int.class, Object.class);
- testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class);
- }
-
- void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable {
- for (Object[] ac : accessCases(defc, name)) {
- testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params);
- }
- }
- void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- for (Object[] ac : accessCases(defc, name)) {
- testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
- }
- }
- void testUnreflectMaybeSpecial(Class<?> specialCaller,
- boolean positive, Lookup lookup,
- Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- countTest(positive);
- MethodType type = MethodType.methodType(ret, params);
- Method rmethod = defc.getDeclaredMethod(name, params);
- MethodHandle target = null;
- Exception noAccess = null;
- boolean isStatic = (rcvc == null);
- boolean isSpecial = (specialCaller != null);
- try {
- if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
- if (isSpecial)
- target = lookup.in(specialCaller).unreflectSpecial(rmethod, specialCaller);
- else
- target = lookup.in(defc).unreflect(rmethod);
- } catch (ReflectiveOperationException ex) {
- noAccess = ex;
- if (name.contains("bogus"))
- assertTrue(noAccess instanceof NoSuchMethodException);
- else
- assertTrue(noAccess instanceof IllegalAccessException);
- }
- if (verbosity >= 3)
- System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type
- +(!isSpecial ? "" : " specialCaller="+specialCaller)
- +( isStatic ? "" : " receiver="+rcvc)
- +" => "+target
- +(noAccess == null ? "" : " !! "+noAccess));
- if (positive && noAccess != null) throw noAccess;
- assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
- if (!positive) return; // negative test failed as expected
- assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers()));
- Class<?>[] paramsMaybeWithSelf = params;
- if (!isStatic) {
- paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params);
- }
- MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf);
- if (isStatic) {
- assertEquals(typeMaybeWithSelf, target.type());
- } else {
- if (isSpecial)
- assertEquals(specialCaller, target.type().parameterType(0));
- else
- assertEquals(defc, target.type().parameterType(0));
- assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc));
- }
- Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf);
- printCalled(target, name, argsMaybeWithSelf);
- target.invokeWithArguments(argsMaybeWithSelf);
- assertCalled(name, argsMaybeWithSelf);
- if (verbosity >= 1)
- System.out.print(':');
- }
-
- void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
- for (Object[] ac : accessCases(defc, name, true)) {
- Class<?> specialCaller = rcvc;
- testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
- }
- }
-
- @Test
- public void testUnreflectSpecial() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("unreflectSpecial");
- testUnreflectSpecial(Example.class, Example.class, void.class, "v0");
- testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0");
- testUnreflectSpecial(Example.class, Example.class, void.class, "pkg_v0");
- testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0");
- testUnreflectSpecial(Example.class, Example.class, Object.class, "v2", int.class, int.class);
- testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class);
- testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0");
- }
-
- public static class HasFields {
- boolean fZ = false;
- byte fB = (byte)'B';
- short fS = (short)'S';
- char fC = 'C';
- int fI = 'I';
- long fJ = 'J';
- float fF = 'F';
- double fD = 'D';
- static boolean sZ = true;
- static byte sB = 1+(byte)'B';
- static short sS = 1+(short)'S';
- static char sC = 1+'C';
- static int sI = 1+'I';
- static long sJ = 1+'J';
- static float sF = 1+'F';
- static double sD = 1+'D';
-
- Object fL = 'L';
- String fR = "R";
- static Object sL = 'M';
- static String sR = "S";
-
- static final Object[][] CASES;
- static {
- ArrayList<Object[]> cases = new ArrayList<Object[]>();
- Object types[][] = {
- {'L',Object.class}, {'R',String.class},
- {'I',int.class}, {'J',long.class},
- {'F',float.class}, {'D',double.class},
- {'Z',boolean.class}, {'B',byte.class},
- {'S',short.class}, {'C',char.class},
- };
- HasFields fields = new HasFields();
- for (Object[] t : types) {
- for (int kind = 0; kind <= 1; kind++) {
- boolean isStatic = (kind != 0);
- char btc = (Character)t[0];
- String name = (isStatic ? "s" : "f") + btc;
- Class<?> type = (Class<?>) t[1];
- Object value;
- Field field;
- try {
- field = HasFields.class.getDeclaredField(name);
- } catch (Exception ex) {
- throw new InternalError("no field HasFields."+name);
- }
- try {
- value = field.get(fields);
- } catch (Exception ex) {
- throw new InternalError("cannot fetch field HasFields."+name);
- }
- if (type == float.class) {
- float v = 'F';
- if (isStatic) v++;
- assertTrue(value.equals(v));
- }
- assertTrue(name.equals(field.getName()));
- assertTrue(type.equals(field.getType()));
- assertTrue(isStatic == (Modifier.isStatic(field.getModifiers())));
- cases.add(new Object[]{ field, value });
- }
- }
- cases.add(new Object[]{ new Object[]{ false, HasFields.class, "bogus_fD", double.class }, Error.class });
- cases.add(new Object[]{ new Object[]{ true, HasFields.class, "bogus_sL", Object.class }, Error.class });
- CASES = cases.toArray(new Object[0][]);
- }
- }
-
- static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC = 3, TEST_SETTER = 0x10;
- static boolean testModeMatches(int testMode, boolean isStatic) {
- switch (testMode) {
- case TEST_FIND_STATIC: return isStatic;
- case TEST_FIND_FIELD: return !isStatic;
- case TEST_UNREFLECT: return true; // unreflect matches both
- }
- throw new InternalError("testMode="+testMode);
- }
-
- @Test
- public void testUnreflectGetter() throws Throwable {
- startTest("unreflectGetter");
- testGetter(TEST_UNREFLECT);
- }
- @Test
- public void testFindGetter() throws Throwable {
- startTest("findGetter");
- testGetter(TEST_FIND_FIELD);
- }
- @Test
- public void testFindStaticGetter() throws Throwable {
- startTest("findStaticGetter");
- testGetter(TEST_FIND_STATIC);
- }
- public void testGetter(int testMode) throws Throwable {
- Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
- for (Object[] c : HasFields.CASES) {
- boolean positive = (c[1] != Error.class);
- testGetter(positive, lookup, c[0], c[1], testMode);
- }
- testGetter(true, lookup,
- new Object[]{ true, System.class, "out", java.io.PrintStream.class },
- System.out, testMode);
- for (int isStaticN = 0; isStaticN <= 1; isStaticN++) {
- testGetter(false, lookup,
- new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
- null, testMode);
- }
- }
- public void testGetter(boolean positive, MethodHandles.Lookup lookup,
- Object fieldRef, Object value, int testMode) throws Throwable {
- testAccessor(positive, lookup, fieldRef, value, testMode);
- }
-
- public void testAccessor(boolean positive, MethodHandles.Lookup lookup,
- Object fieldRef, Object value, int testMode0) throws Throwable {
- boolean isGetter = ((testMode0 & TEST_SETTER) == 0);
- int testMode = testMode0 & ~TEST_SETTER;
- boolean isStatic;
- Class<?> fclass;
- String fname;
- Class<?> ftype;
- Field f = (fieldRef instanceof Field ? (Field)fieldRef : null);
- if (f != null) {
- isStatic = Modifier.isStatic(f.getModifiers());
- fclass = f.getDeclaringClass();
- fname = f.getName();
- ftype = f.getType();
- } else {
- Object[] scnt = (Object[]) fieldRef;
- isStatic = (Boolean) scnt[0];
- fclass = (Class<?>) scnt[1];
- fname = (String) scnt[2];
- ftype = (Class<?>) scnt[3];
- try {
- f = fclass.getDeclaredField(fname);
- } catch (ReflectiveOperationException ex) {
- f = null;
- }
- }
- if (!testModeMatches(testMode, isStatic)) return;
- if (f == null && testMode == TEST_UNREFLECT) return;
- countTest(positive);
- MethodType expType;
- if (isGetter)
- expType = MethodType.methodType(ftype, HasFields.class);
- else
- expType = MethodType.methodType(void.class, HasFields.class, ftype);
- if (isStatic) expType = expType.dropParameterTypes(0, 1);
- Exception noAccess = null;
- MethodHandle mh;
- try {
- switch (testMode0) {
- case TEST_UNREFLECT: mh = lookup.unreflectGetter(f); break;
- case TEST_FIND_FIELD: mh = lookup.findGetter(fclass, fname, ftype); break;
- case TEST_FIND_STATIC: mh = lookup.findStaticGetter(fclass, fname, ftype); break;
- case TEST_SETTER|
- TEST_UNREFLECT: mh = lookup.unreflectSetter(f); break;
- case TEST_SETTER|
- TEST_FIND_FIELD: mh = lookup.findSetter(fclass, fname, ftype); break;
- case TEST_SETTER|
- TEST_FIND_STATIC: mh = lookup.findStaticSetter(fclass, fname, ftype); break;
- default:
- throw new InternalError("testMode="+testMode);
- }
- } catch (ReflectiveOperationException ex) {
- mh = null;
- noAccess = ex;
- if (fname.contains("bogus"))
- assertTrue(noAccess instanceof NoSuchFieldException);
- else
- assertTrue(noAccess instanceof IllegalAccessException);
- }
- if (verbosity >= 3)
- System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype
- +" => "+mh
- +(noAccess == null ? "" : " !! "+noAccess));
- if (positive && noAccess != null) throw new RuntimeException(noAccess);
- assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, mh != null);
- if (!positive) return; // negative test failed as expected
- assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount());
-
-
- assertSame(mh.type(), expType);
- assertNameStringContains(mh, fname);
- HasFields fields = new HasFields();
- Object sawValue;
- Class<?> vtype = ftype;
- if (ftype != int.class) vtype = Object.class;
- if (isGetter) {
- mh = MethodHandles.convertArguments(mh, mh.type().generic()
- .changeReturnType(vtype));
- } else {
- int last = mh.type().parameterCount() - 1;
- mh = MethodHandles.convertArguments(mh, mh.type().generic()
- .changeReturnType(void.class)
- .changeParameterType(last, vtype));
- }
- if (f != null && f.getDeclaringClass() == HasFields.class) {
- assertEquals(f.get(fields), value); // clean to start with
- }
- if (isGetter) {
- Object expValue = value;
- for (int i = 0; i <= 1; i++) {
- if (isStatic) {
- if (ftype == int.class)
- sawValue = (int) mh.invokeExact(); // do these exactly
- else
- sawValue = mh.invokeExact();
- } else {
- if (ftype == int.class)
- sawValue = (int) mh.invokeExact((Object) fields);
- else
- sawValue = mh.invokeExact((Object) fields);
- }
- assertEquals(sawValue, expValue);
- if (f != null && f.getDeclaringClass() == HasFields.class
- && !Modifier.isFinal(f.getModifiers())) {
- Object random = randomArg(ftype);
- f.set(fields, random);
- expValue = random;
- } else {
- break;
- }
- }
- } else {
- for (int i = 0; i <= 1; i++) {
- Object putValue = randomArg(ftype);
- if (isStatic) {
- if (ftype == int.class)
- mh.invokeExact((int)putValue); // do these exactly
- else
- mh.invokeExact(putValue);
- } else {
- if (ftype == int.class)
- mh.invokeExact((Object) fields, (int)putValue);
- else
- mh.invokeExact((Object) fields, putValue);
- }
- if (f != null && f.getDeclaringClass() == HasFields.class) {
- assertEquals(f.get(fields), putValue);
- }
- }
- }
- if (f != null && f.getDeclaringClass() == HasFields.class) {
- f.set(fields, value); // put it back
- }
- }
-
-
- @Test
- public void testUnreflectSetter() throws Throwable {
- startTest("unreflectSetter");
- testSetter(TEST_UNREFLECT);
- }
- @Test
- public void testFindSetter() throws Throwable {
- startTest("findSetter");
- testSetter(TEST_FIND_FIELD);
- }
- @Test
- public void testFindStaticSetter() throws Throwable {
- startTest("findStaticSetter");
- testSetter(TEST_FIND_STATIC);
- }
- public void testSetter(int testMode) throws Throwable {
- Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
- startTest("unreflectSetter");
- for (Object[] c : HasFields.CASES) {
- boolean positive = (c[1] != Error.class);
- testSetter(positive, lookup, c[0], c[1], testMode);
- }
- for (int isStaticN = 0; isStaticN <= 1; isStaticN++) {
- testSetter(false, lookup,
- new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
- null, testMode);
- }
- }
- public void testSetter(boolean positive, MethodHandles.Lookup lookup,
- Object fieldRef, Object value, int testMode) throws Throwable {
- testAccessor(positive, lookup, fieldRef, value, testMode | TEST_SETTER);
- }
-
- @Test
- public void testArrayElementGetter() throws Throwable {
- startTest("arrayElementGetter");
- testArrayElementGetterSetter(false);
- }
-
- @Test
- public void testArrayElementSetter() throws Throwable {
- startTest("arrayElementSetter");
- testArrayElementGetterSetter(true);
- }
-
- public void testArrayElementGetterSetter(boolean testSetter) throws Throwable {
- testArrayElementGetterSetter(new Object[10], testSetter);
- testArrayElementGetterSetter(new String[10], testSetter);
- testArrayElementGetterSetter(new boolean[10], testSetter);
- testArrayElementGetterSetter(new byte[10], testSetter);
- testArrayElementGetterSetter(new char[10], testSetter);
- testArrayElementGetterSetter(new short[10], testSetter);
- testArrayElementGetterSetter(new int[10], testSetter);
- testArrayElementGetterSetter(new float[10], testSetter);
- testArrayElementGetterSetter(new long[10], testSetter);
- testArrayElementGetterSetter(new double[10], testSetter);
- }
-
- public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable {
- countTest(true);
- if (verbosity >= 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]");
- Class<?> arrayType = array.getClass();
- Class<?> elemType = arrayType.getComponentType();
- MethodType expType = !testSetter
- ? MethodType.methodType(elemType, arrayType, int.class)
- : MethodType.methodType(void.class, arrayType, int.class, elemType);
- MethodHandle mh = !testSetter
- ? MethodHandles.arrayElementGetter(arrayType)
- : MethodHandles.arrayElementSetter(arrayType);
- assertSame(mh.type(), expType);
- if (elemType != int.class && elemType != boolean.class) {
- MethodType gtype;
- if (true) { // FIXME: remove this path (and remove <void> below in the mh.invokes)
- gtype = mh.type().changeParameterType(0, Object.class);
- if (testSetter)
- gtype = gtype.changeParameterType(2, Object.class);
- else
- gtype = gtype.changeReturnType(Object.class);
- } else
- // FIXME: This simpler path hits a bug in convertArguments => ToGeneric
- gtype = mh.type().generic().changeParameterType(1, int.class);
- mh = MethodHandles.convertArguments(mh, gtype);
- }
- Object sawValue, expValue;
- List<Object> model = array2list(array);
- int length = Array.getLength(array);
- for (int i = 0; i < length; i++) {
- // update array element
- Object random = randomArg(elemType);
- model.set(i, random);
- if (testSetter) {
- if (elemType == int.class)
- mh.invokeExact((int[]) array, i, (int)random);
- else if (elemType == boolean.class)
- mh.invokeExact((boolean[]) array, i, (boolean)random);
- else
- mh.invokeExact(array, i, random);
- assertEquals(model, array2list(array));
- } else {
- Array.set(array, i, random);
- }
- if (verbosity >= 5) {
- List<Object> array2list = array2list(array);
- System.out.println("a["+i+"]="+random+" => "+array2list);
- if (!array2list.equals(model))
- System.out.println("*** != "+model);
- }
- // observe array element
- sawValue = Array.get(array, i);
- if (!testSetter) {
- expValue = sawValue;
- if (elemType == int.class)
- sawValue = (int) mh.invokeExact((int[]) array, i);
- else if (elemType == boolean.class)
- sawValue = (boolean) mh.invokeExact((boolean[]) array, i);
- else
- sawValue = mh.invokeExact(array, i);
- assertEquals(sawValue, expValue);
- assertEquals(model, array2list(array));
- }
- }
- }
-
- List<Object> array2list(Object array) {
- int length = Array.getLength(array);
- ArrayList<Object> model = new ArrayList<Object>(length);
- for (int i = 0; i < length; i++)
- model.add(Array.get(array, i));
- return model;
- }
-
- static class Callee {
- static Object id() { return called("id"); }
- static Object id(Object x) { return called("id", x); }
- static Object id(Object x, Object y) { return called("id", x, y); }
- static Object id(Object x, Object y, Object z) { return called("id", x, y, z); }
- static Object id(Object... vx) { return called("id", vx); }
- static MethodHandle ofType(int n) {
- return ofType(Object.class, n);
- }
- static MethodHandle ofType(Class<?> rtype, int n) {
- if (n == -1)
- return ofType(MethodType.methodType(rtype, Object[].class));
- return ofType(MethodType.genericMethodType(n).changeReturnType(rtype));
- }
- static MethodHandle ofType(Class<?> rtype, Class<?>... ptypes) {
- return ofType(MethodType.methodType(rtype, ptypes));
- }
- static MethodHandle ofType(MethodType type) {
- Class<?> rtype = type.returnType();
- String pfx = "";
- if (rtype != Object.class)
- pfx = rtype.getSimpleName().substring(0, 1).toLowerCase();
- String name = pfx+"id";
- try {
- return PRIVATE.findStatic(Callee.class, name, type);
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
- }
-
- @Test
- public void testConvertArguments() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("convertArguments");
- testConvert(Callee.ofType(1), null, "id", int.class);
- testConvert(Callee.ofType(1), null, "id", String.class);
- testConvert(Callee.ofType(1), null, "id", Integer.class);
- testConvert(Callee.ofType(1), null, "id", short.class);
- testConvert(Callee.ofType(1), null, "id", char.class);
- testConvert(Callee.ofType(1), null, "id", byte.class);
- }
-
- void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
- testConvert(true, false, id, rtype, name, params);
- testConvert(true, true, id, rtype, name, params);
- }
-
- void testConvert(boolean positive, boolean useAsType,
- MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
- countTest(positive);
- MethodType idType = id.type();
- if (rtype == null) rtype = idType.returnType();
- for (int i = 0; i < params.length; i++) {
- if (params[i] == null) params[i] = idType.parameterType(i);
- }
- // simulate the pairwise conversion
- MethodType newType = MethodType.methodType(rtype, params);
- Object[] args = randomArgs(newType.parameterArray());
- Object[] convArgs = args.clone();
- for (int i = 0; i < args.length; i++) {
- Class<?> src = newType.parameterType(i);
- Class<?> dst = idType.parameterType(i);
- if (src != dst)
- convArgs[i] = castToWrapper(convArgs[i], dst);
- }
- Object convResult = id.invokeWithArguments(convArgs);
- {
- Class<?> dst = newType.returnType();
- Class<?> src = idType.returnType();
- if (src != dst)
- convResult = castToWrapper(convResult, dst);
- }
- MethodHandle target = null;
- RuntimeException error = null;
- try {
- if (useAsType)
- target = id.asType(newType);
- else
- target = MethodHandles.convertArguments(id, newType);
- } catch (RuntimeException ex) {
- error = ex;
- }
- if (verbosity >= 3)
- System.out.println("convert "+id+ " to "+newType+" => "+target
- +(error == null ? "" : " !! "+error));
- if (positive && error != null) throw error;
- assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
- if (!positive) return; // negative test failed as expected
- assertEquals(newType, target.type());
- printCalled(target, id.toString(), args);
- Object result = target.invokeWithArguments(args);
- assertCalled(name, convArgs);
- assertEquals(convResult, result);
- if (verbosity >= 1)
- System.out.print(':');
- }
-
- @Test
- public void testVarargsCollector() throws Throwable {
- MethodHandle vac0 = PRIVATE.findStatic(MethodHandlesTest.class, "called",
- MethodType.methodType(Object.class, String.class, Object[].class));
- vac0 = vac0.bindTo("vac");
- MethodHandle vac = vac0.asVarargsCollector(Object[].class);
- testConvert(true, true, vac.asType(MethodType.genericMethodType(0)), null, "vac");
- testConvert(true, true, vac.asType(MethodType.genericMethodType(0)), null, "vac");
- for (Class<?> at : new Class[] { Object.class, String.class, Integer.class }) {
- testConvert(true, true, vac.asType(MethodType.genericMethodType(1)), null, "vac", at);
- testConvert(true, true, vac.asType(MethodType.genericMethodType(2)), null, "vac", at, at);
- }
- }
-
- @Test
- public void testPermuteArguments() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("permuteArguments");
- testPermuteArguments(4, Integer.class, 2, String.class, 0);
- //testPermuteArguments(6, Integer.class, 0, null, 30);
- //testPermuteArguments(4, Integer.class, 1, int.class, 6);
- }
- public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
- if (verbosity >= 2)
- System.out.println("permuteArguments "+max+"*"+type1.getName()
- +(t2c==0?"":"/"+t2c+"*"+type2.getName())
- +(dilution > 0 ? " with dilution "+dilution : ""));
- int t2pos = t2c == 0 ? 0 : 1;
- for (int inargs = t2pos+1; inargs <= max; inargs++) {
- Class<?>[] types = new Class<?>[inargs];
- Arrays.fill(types, type1);
- if (t2c != 0) {
- // Fill in a middle range with type2:
- Arrays.fill(types, t2pos, Math.min(t2pos+t2c, inargs), type2);
- }
- Object[] args = randomArgs(types);
- int numcases = 1;
- for (int outargs = 0; outargs <= max; outargs++) {
- if (outargs - inargs >= MAX_ARG_INCREASE) continue;
- int[] reorder = new int[outargs];
- int casStep = dilution + 1;
- // Avoid some common factors:
- while ((casStep > 2 && casStep % 2 == 0 && inargs % 2 == 0) ||
- (casStep > 3 && casStep % 3 == 0 && inargs % 3 == 0))
- casStep++;
- for (int cas = 0; cas < numcases; cas += casStep) {
- for (int i = 0, c = cas; i < outargs; i++) {
- reorder[i] = c % inargs;
- c /= inargs;
- }
- testPermuteArguments(args, types, reorder);
- }
- numcases *= inargs;
- if (dilution > 10 && outargs >= 4) {
- // Do some special patterns, which we probably missed.
- // Replication of a single argument or argument pair.
- for (int i = 0; i < inargs; i++) {
- Arrays.fill(reorder, i);
- testPermuteArguments(args, types, reorder);
- for (int d = 1; d <= 2; d++) {
- if (i + d >= inargs) continue;
- for (int j = 1; j < outargs; j += 2)
- reorder[j] += 1;
- testPermuteArguments(args, types, reorder);
- testPermuteArguments(args, types, reverse(reorder));
- }
- }
- // Repetition of a sequence of 3 or more arguments.
- for (int i = 1; i < inargs; i++) {
- for (int len = 3; len <= inargs; len++) {
- for (int j = 0; j < outargs; j++)
- reorder[j] = (i + (j % len)) % inargs;
- testPermuteArguments(args, types, reorder);
- testPermuteArguments(args, types, reverse(reorder));
- }
- }
- }
- }
- }
- }
-
- static int[] reverse(int[] reorder) {
- reorder = reorder.clone();
- for (int i = 0, imax = reorder.length / 2; i < imax; i++) {
- int j = reorder.length - 1 - i;
- int tem = reorder[i];
- reorder[i] = reorder[j];
- reorder[j] = tem;
- }
- return reorder;
- }
-
- void testPermuteArguments(Object[] args, Class<?>[] types, int[] reorder) throws Throwable {
- countTest();
- if (args == null && types == null) {
- int max = 0;
- for (int j : reorder) {
- if (max < j) max = j;
- }
- args = randomArgs(max+1, Integer.class);
- }
- if (args == null) {
- args = randomArgs(types);
- }
- if (types == null) {
- types = new Class<?>[args.length];
- for (int i = 0; i < args.length; i++)
- types[i] = args[i].getClass();
- }
- int inargs = args.length, outargs = reorder.length;
- assertTrue(inargs == types.length);
- if (verbosity >= 3)
- System.out.println("permuteArguments "+Arrays.toString(reorder));
- Object[] permArgs = new Object[outargs];
- Class<?>[] permTypes = new Class<?>[outargs];
- for (int i = 0; i < outargs; i++) {
- permArgs[i] = args[reorder[i]];
- permTypes[i] = types[reorder[i]];
- }
- if (verbosity >= 4) {
- System.out.println("in args: "+Arrays.asList(args));
- System.out.println("out args: "+Arrays.asList(permArgs));
- System.out.println("in types: "+Arrays.asList(types));
- System.out.println("out types: "+Arrays.asList(permTypes));
- }
- MethodType inType = MethodType.methodType(Object.class, types);
- MethodType outType = MethodType.methodType(Object.class, permTypes);
- MethodHandle target = MethodHandles.convertArguments(varargsList(outargs), outType);
- MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder);
- Object result = newTarget.invokeWithArguments(args);
- Object expected = Arrays.asList(permArgs);
- assertEquals(expected, result);
- }
-
-
- @Test
- public void testSpreadArguments() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("spreadArguments");
- for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
- if (verbosity >= 3)
- System.out.println("spreadArguments "+argType);
- // FIXME: enable _adapter_spread_args and fix Fail_2
- for (int nargs = 0; nargs < 10; nargs++) {
- if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1
- for (int pos = 0; pos < nargs; pos++) {
- if (argType == int.class && pos > 0) continue; // FIXME Fail_3
- testSpreadArguments(argType, pos, nargs);
- }
- }
- }
- }
- public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable {
- countTest();
- MethodHandle target = varargsArray(nargs);
- MethodHandle target2 = changeArgTypes(target, argType);
- if (verbosity >= 3)
- System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]");
- Object[] args = randomArgs(target2.type().parameterArray());
- // make sure the target does what we think it does:
- if (pos == 0 && nargs < 5) {
- Object[] check = (Object[]) target.invokeWithArguments(args);
- assertArrayEquals(args, check);
- switch (nargs) {
- case 0:
- check = (Object[]) target.invokeExact();
- assertArrayEquals(args, check);
- break;
- case 1:
- check = (Object[]) target.invokeExact(args[0]);
- assertArrayEquals(args, check);
- break;
- case 2:
- check = (Object[]) target.invokeExact(args[0], args[1]);
- assertArrayEquals(args, check);
- break;
- }
- }
- List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList());
- { // modify newParams in place
- List<Class<?>> spreadParams = newParams.subList(pos, nargs);
- spreadParams.clear(); spreadParams.add(Object[].class);
- }
- MethodType newType = MethodType.methodType(Object.class, newParams);
- MethodHandle result = target2.asSpreader(Object[].class, nargs-pos).asType(newType);
- Object[] returnValue;
- if (pos == 0) {
- // In the following line, the first cast implies
- // normal Object return value for the MH call (Object[])->Object,
- // while the second cast dynamically converts to an Object array.
- // Such a double cast is typical of MH.invokeExact.
- returnValue = (Object[]) (Object) result.invokeExact(args);
- } else {
- Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
- args1[pos] = Arrays.copyOfRange(args, pos, args.length);
- returnValue = (Object[]) result.invokeWithArguments(args1);
- }
- assertArrayEquals(args, returnValue);
- }
-
- @Test
- public void testCollectArguments() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("collectArguments");
- for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
- if (verbosity >= 3)
- System.out.println("collectArguments "+argType);
- for (int nargs = 0; nargs < 10; nargs++) {
- for (int pos = 0; pos < nargs; pos++) {
- if (argType == int.class) continue; // FIXME Fail_4
- testCollectArguments(argType, pos, nargs);
- }
- }
- }
- }
- public void testCollectArguments(Class<?> argType, int pos, int nargs) throws Throwable {
- countTest();
- // fake up a MH with the same type as the desired adapter:
- MethodHandle fake = varargsArray(nargs);
- fake = changeArgTypes(fake, argType);
- MethodType newType = fake.type();
- Object[] args = randomArgs(newType.parameterArray());
- // here is what should happen:
- Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1);
- collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length);
- // here is the MH which will witness the collected argument tail:
- MethodHandle target = varargsArray(pos+1);
- target = changeArgTypes(target, 0, pos, argType);
- target = changeArgTypes(target, pos, pos+1, Object[].class);
- if (verbosity >= 3)
- System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
- MethodHandle result = target.asCollector(Object[].class, nargs-pos).asType(newType);
- Object[] returnValue = (Object[]) result.invokeWithArguments(args);
-// assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
-// returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
-// collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]);
- assertArrayEquals(collectedArgs, returnValue);
- }
-
- @Test
- public void testInsertArguments() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("insertArguments");
- for (int nargs = 0; nargs <= 4; nargs++) {
- for (int ins = 0; ins <= 4; ins++) {
- if (ins > MAX_ARG_INCREASE) continue; // FIXME Fail_6
- for (int pos = 0; pos <= nargs; pos++) {
- testInsertArguments(nargs, pos, ins);
- }
- }
- }
- }
-
- void testInsertArguments(int nargs, int pos, int ins) throws Throwable {
- countTest();
- MethodHandle target = varargsArray(nargs + ins);
- Object[] args = randomArgs(target.type().parameterArray());
- List<Object> resList = Arrays.asList(args);
- List<Object> argsToPass = new ArrayList<Object>(resList);
- List<Object> argsToInsert = argsToPass.subList(pos, pos + ins);
- if (verbosity >= 3)
- System.out.println("insert: "+argsToInsert+" into "+target);
- MethodHandle target2 = MethodHandles.insertArguments(target, pos,
- (Object[]) argsToInsert.toArray());
- argsToInsert.clear(); // remove from argsToInsert
- Object res2 = target2.invokeWithArguments(argsToPass);
- Object res2List = Arrays.asList((Object[])res2);
- if (verbosity >= 3)
- System.out.println("result: "+res2List);
- //if (!resList.equals(res2List))
- // System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List);
- assertEquals(resList, res2List);
- }
-
- @Test
- public void testFilterReturnValue() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("filterReturnValue");
- Class<?> classOfVCList = varargsList(1).invokeWithArguments(0).getClass();
- assertTrue(List.class.isAssignableFrom(classOfVCList));
- for (int nargs = 0; nargs <= 3; nargs++) {
- for (Class<?> rtype : new Class[] { Object.class,
- List.class,
- int.class,
- //byte.class, //FIXME: add this
- //long.class, //FIXME: add this
- CharSequence.class,
- String.class }) {
- testFilterReturnValue(nargs, rtype);
- }
- }
- }
-
- void testFilterReturnValue(int nargs, Class<?> rtype) throws Throwable {
- countTest();
- MethodHandle target = varargsList(nargs, rtype);
- MethodHandle filter;
- if (List.class.isAssignableFrom(rtype) || rtype.isAssignableFrom(List.class))
- filter = varargsList(1); // add another layer of list-ness
- else
- filter = MethodHandles.identity(rtype);
- filter = filter.asType(MethodType.methodType(target.type().returnType(), rtype));
- Object[] argsToPass = randomArgs(nargs, Object.class);
- if (verbosity >= 3)
- System.out.println("filter "+target+" to "+rtype.getSimpleName()+" with "+filter);
- MethodHandle target2 = MethodHandles.filterReturnValue(target, filter);
- if (verbosity >= 4)
- System.out.println("filtered target: "+target2);
- // Simulate expected effect of filter on return value:
- Object unfiltered = target.invokeWithArguments(argsToPass);
- Object expected = filter.invokeWithArguments(unfiltered);
- if (verbosity >= 4)
- System.out.println("unfiltered: "+unfiltered+" : "+unfiltered.getClass().getSimpleName());
- if (verbosity >= 4)
- System.out.println("expected: "+expected+" : "+expected.getClass().getSimpleName());
- Object result = target2.invokeWithArguments(argsToPass);
- if (verbosity >= 3)
- System.out.println("result: "+result+" : "+result.getClass().getSimpleName());
- if (!expected.equals(result))
- System.out.println("*** fail at n/rt = "+nargs+"/"+rtype.getSimpleName()+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
- assertEquals(expected, result);
- }
-
- @Test
- public void testFilterArguments() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("filterArguments");
- for (int nargs = 1; nargs <= 6; nargs++) {
- for (int pos = 0; pos < nargs; pos++) {
- testFilterArguments(nargs, pos);
- }
- }
- }
-
- void testFilterArguments(int nargs, int pos) throws Throwable {
- countTest();
- MethodHandle target = varargsList(nargs);
- MethodHandle filter = varargsList(1);
- filter = MethodHandles.convertArguments(filter, filter.type().generic());
- Object[] argsToPass = randomArgs(nargs, Object.class);
- if (verbosity >= 3)
- System.out.println("filter "+target+" at "+pos+" with "+filter);
- MethodHandle target2 = MethodHandles.filterArguments(target, pos, filter);
- // Simulate expected effect of filter on arglist:
- Object[] filteredArgs = argsToPass.clone();
- filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]);
- List<Object> expected = Arrays.asList(filteredArgs);
- Object result = target2.invokeWithArguments(argsToPass);
- if (verbosity >= 3)
- System.out.println("result: "+result);
- if (!expected.equals(result))
- System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
- assertEquals(expected, result);
- }
-
- @Test
- public void testFoldArguments() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("foldArguments");
- for (int nargs = 0; nargs <= 4; nargs++) {
- for (int fold = 0; fold <= nargs; fold++) {
- for (int pos = 0; pos <= nargs; pos++) {
- testFoldArguments(nargs, pos, fold);
- }
- }
- }
- }
-
- void testFoldArguments(int nargs, int pos, int fold) throws Throwable {
- if (pos != 0) return; // can fold only at pos=0 for now
- countTest();
- MethodHandle target = varargsList(1 + nargs);
- MethodHandle combine = varargsList(fold).asType(MethodType.genericMethodType(fold));
- List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class));
- if (verbosity >= 3)
- System.out.println("fold "+target+" with "+combine);
- MethodHandle target2 = MethodHandles.foldArguments(target, combine);
- // Simulate expected effect of combiner on arglist:
- List<Object> expected = new ArrayList<Object>(argsToPass);
- List<Object> argsToFold = expected.subList(pos, pos + fold);
- if (verbosity >= 3)
- System.out.println("fold: "+argsToFold+" into "+target2);
- Object foldedArgs = combine.invokeWithArguments(argsToFold);
- argsToFold.add(0, foldedArgs);
- Object result = target2.invokeWithArguments(argsToPass);
- if (verbosity >= 3)
- System.out.println("result: "+result);
- if (!expected.equals(result))
- System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result+" != "+expected);
- assertEquals(expected, result);
- }
-
- @Test
- public void testDropArguments() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("dropArguments");
- for (int nargs = 0; nargs <= 4; nargs++) {
- for (int drop = 1; drop <= 4; drop++) {
- for (int pos = 0; pos <= nargs; pos++) {
- testDropArguments(nargs, pos, drop);
- }
- }
- }
- }
-
- void testDropArguments(int nargs, int pos, int drop) throws Throwable {
- countTest();
- MethodHandle target = varargsArray(nargs);
- Object[] args = randomArgs(target.type().parameterArray());
- MethodHandle target2 = MethodHandles.dropArguments(target, pos,
- Collections.nCopies(drop, Object.class).toArray(new Class[0]));
- List<Object> resList = Arrays.asList(args);
- List<Object> argsToDrop = new ArrayList<Object>(resList);
- for (int i = drop; i > 0; i--) {
- argsToDrop.add(pos, "blort#"+i);
- }
- Object res2 = target2.invokeWithArguments(argsToDrop);
- Object res2List = Arrays.asList((Object[])res2);
- //if (!resList.equals(res2List))
- // System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
- assertEquals(resList, res2List);
- }
-
- @Test
- public void testInvokers() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker");
- // exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker
- Set<MethodType> done = new HashSet<MethodType>();
- for (int i = 0; i <= 6; i++) {
- MethodType gtype = MethodType.genericMethodType(i);
- for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
- for (int j = -1; j < i; j++) {
- MethodType type = gtype;
- if (j < 0)
- type = type.changeReturnType(argType);
- else if (argType == void.class)
- continue;
- else
- type = type.changeParameterType(j, argType);
- if (argType.isPrimitive() && j != i-1) continue; // FIXME Fail_5
- if (done.add(type))
- testInvokers(type);
- MethodType vtype = type.changeReturnType(void.class);
- if (done.add(vtype))
- testInvokers(vtype);
- }
- }
- }
- }
-
- public void testInvokers(MethodType type) throws Throwable {
- if (verbosity >= 3)
- System.out.println("test invokers for "+type);
- int nargs = type.parameterCount();
- boolean testRetCode = type.returnType() != void.class;
- MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee",
- MethodType.genericMethodType(0, true));
- assertTrue(target.isVarargsCollector());
- target = target.asType(type);
- Object[] args = randomArgs(type.parameterArray());
- List<Object> targetPlusArgs = new ArrayList<Object>(Arrays.asList(args));
- targetPlusArgs.add(0, target);
- int code = (Integer) invokee(args);
- Object log = logEntry("invokee", args);
- assertEquals(log.hashCode(), code);
- assertCalled("invokee", args);
- MethodHandle inv;
- Object result;
- // exact invoker
- countTest();
- calledLog.clear();
- inv = MethodHandles.exactInvoker(type);
- result = inv.invokeWithArguments(targetPlusArgs);
- if (testRetCode) assertEquals(code, result);
- assertCalled("invokee", args);
- // generic invoker
- countTest();
- inv = MethodHandles.genericInvoker(type);
- if (nargs <= 3) {
- calledLog.clear();
- switch (nargs) {
- case 0:
- result = inv.invokeExact(target);
- break;
- case 1:
- result = inv.invokeExact(target, args[0]);
- break;
- case 2:
- result = inv.invokeExact(target, args[0], args[1]);
- break;
- case 3:
- result = inv.invokeExact(target, args[0], args[1], args[2]);
- break;
- }
- if (testRetCode) assertEquals(code, result);
- assertCalled("invokee", args);
- }
- calledLog.clear();
- result = inv.invokeWithArguments(targetPlusArgs);
- if (testRetCode) assertEquals(code, result);
- assertCalled("invokee", args);
- // varargs invoker #0
- calledLog.clear();
- inv = MethodHandles.spreadInvoker(type, 0);
- result = inv.invokeExact(target, args);
- if (testRetCode) assertEquals(code, result);
- assertCalled("invokee", args);
- if (nargs >= 1) {
- // varargs invoker #1
- calledLog.clear();
- inv = MethodHandles.spreadInvoker(type, 1);
- result = inv.invokeExact(target, args[0], Arrays.copyOfRange(args, 1, nargs));
- if (testRetCode) assertEquals(code, result);
- assertCalled("invokee", args);
- }
- if (nargs >= 2) {
- // varargs invoker #2
- calledLog.clear();
- inv = MethodHandles.spreadInvoker(type, 2);
- result = inv.invokeExact(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs));
- if (testRetCode) assertEquals(code, result);
- assertCalled("invokee", args);
- }
- if (nargs >= 3) {
- // varargs invoker #3
- calledLog.clear();
- inv = MethodHandles.spreadInvoker(type, 3);
- result = inv.invokeExact(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs));
- if (testRetCode) assertEquals(code, result);
- assertCalled("invokee", args);
- }
- for (int k = 0; k <= nargs; k++) {
- // varargs invoker #0..N
- countTest();
- calledLog.clear();
- inv = MethodHandles.spreadInvoker(type, k);
- List<Object> targetPlusVarArgs = new ArrayList<Object>(targetPlusArgs);
- List<Object> tailList = targetPlusVarArgs.subList(1+k, 1+nargs);
- Object[] tail = tailList.toArray();
- tailList.clear(); tailList.add(tail);
- result = inv.invokeWithArguments(targetPlusVarArgs);
- if (testRetCode) assertEquals(code, result);
- assertCalled("invokee", args);
- }
-
- // dynamic invoker
- countTest();
- CallSite site = new MutableCallSite(type);
- inv = site.dynamicInvoker();
-
- // see if we get the result of the original target:
- try {
- result = inv.invokeWithArguments(args);
- assertTrue("should not reach here", false);
- } catch (IllegalStateException ex) {
- String msg = ex.getMessage();
- assertTrue(msg, msg.contains("site"));
- }
-
- // set new target after invoker is created, to make sure we track target
- site.setTarget(target);
- calledLog.clear();
- result = inv.invokeWithArguments(args);
- if (testRetCode) assertEquals(code, result);
- assertCalled("invokee", args);
- }
-
- static Object invokee(Object... args) {
- return called("invokee", args).hashCode();
- }
-
- private static final String MISSING_ARG = "missingArg";
- static Object targetIfEquals() {
- return called("targetIfEquals");
- }
- static Object fallbackIfNotEquals() {
- return called("fallbackIfNotEquals");
- }
- static Object targetIfEquals(Object x) {
- assertEquals(x, MISSING_ARG);
- return called("targetIfEquals", x);
- }
- static Object fallbackIfNotEquals(Object x) {
- assertFalse(x.toString(), x.equals(MISSING_ARG));
- return called("fallbackIfNotEquals", x);
- }
- static Object targetIfEquals(Object x, Object y) {
- assertEquals(x, y);
- return called("targetIfEquals", x, y);
- }
- static Object fallbackIfNotEquals(Object x, Object y) {
- assertFalse(x.toString(), x.equals(y));
- return called("fallbackIfNotEquals", x, y);
- }
- static Object targetIfEquals(Object x, Object y, Object z) {
- assertEquals(x, y);
- return called("targetIfEquals", x, y, z);
- }
- static Object fallbackIfNotEquals(Object x, Object y, Object z) {
- assertFalse(x.toString(), x.equals(y));
- return called("fallbackIfNotEquals", x, y, z);
- }
-
- @Test
- public void testGuardWithTest() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("guardWithTest");
- for (int nargs = 0; nargs <= 3; nargs++) {
- if (nargs != 2) continue; // FIXME: test more later
- testGuardWithTest(nargs, Object.class);
- testGuardWithTest(nargs, String.class);
- }
- }
- void testGuardWithTest(int nargs, Class<?> argClass) throws Throwable {
- countTest();
- MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class));
- MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs));
- MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs));
- while (test.type().parameterCount() < nargs)
- test = MethodHandles.dropArguments(test, test.type().parameterCount()-1, Object.class);
- while (test.type().parameterCount() > nargs)
- test = MethodHandles.insertArguments(test, 0, MISSING_ARG);
- if (argClass != Object.class) {
- test = changeArgTypes(test, argClass);
- target = changeArgTypes(target, argClass);
- fallback = changeArgTypes(fallback, argClass);
- }
- MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback);
- assertEquals(target.type(), mh.type());
- Object[][] argLists = {
- { },
- { "foo" }, { MISSING_ARG },
- { "foo", "foo" }, { "foo", "bar" },
- { "foo", "foo", "baz" }, { "foo", "bar", "baz" }
- };
- for (Object[] argList : argLists) {
- if (argList.length != nargs) continue;
- boolean equals;
- switch (nargs) {
- case 0: equals = true; break;
- case 1: equals = MISSING_ARG.equals(argList[0]); break;
- default: equals = argList[0].equals(argList[1]); break;
- }
- String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
- if (verbosity >= 3)
- System.out.println(logEntry(willCall, argList));
- Object result = mh.invokeWithArguments(argList);
- assertCalled(willCall, argList);
- }
- }
-
- @Test
- public void testCatchException() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("catchException");
- for (int nargs = 2; nargs <= 6; nargs++) {
- for (int ti = 0; ti <= 1; ti++) {
- boolean throwIt = (ti != 0);
- testCatchException(int.class, new ClassCastException("testing"), throwIt, nargs);
- testCatchException(void.class, new java.io.IOException("testing"), throwIt, nargs);
- testCatchException(String.class, new LinkageError("testing"), throwIt, nargs);
- }
- }
- }
-
- private static <T extends Throwable>
- Object throwOrReturn(Object normal, T exception) throws T {
- if (exception != null) throw exception;
- return normal;
- }
-
- void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable {
- countTest();
- if (verbosity >= 3)
- System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs);
- Class<? extends Throwable> exType = thrown.getClass();
- MethodHandle throwOrReturn
- = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
- MethodType.methodType(Object.class, Object.class, Throwable.class));
- MethodHandle thrower = throwOrReturn.asType(MethodType.genericMethodType(2));
- while (thrower.type().parameterCount() < nargs)
- thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class);
- MethodHandle catcher = varargsList(1+nargs).asType(MethodType.genericMethodType(1+nargs));
- MethodHandle target = MethodHandles.catchException(thrower,
- thrown.getClass(), catcher);
- assertEquals(thrower.type(), target.type());
- //System.out.println("catching with "+target+" : "+throwOrReturn);
- Object[] args = randomArgs(nargs, Object.class);
- args[1] = (throwIt ? thrown : null);
- Object returned = target.invokeWithArguments(args);
- //System.out.println("return from "+target+" : "+returned);
- if (!throwIt) {
- assertSame(args[0], returned);
- } else {
- List<Object> catchArgs = new ArrayList<Object>(Arrays.asList(args));
- catchArgs.add(0, thrown);
- assertEquals(catchArgs, returned);
- }
- }
-
- @Test
- public void testThrowException() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("throwException");
- testThrowException(int.class, new ClassCastException("testing"));
- testThrowException(void.class, new java.io.IOException("testing"));
- testThrowException(String.class, new LinkageError("testing"));
- }
-
- void testThrowException(Class<?> returnType, Throwable thrown) throws Throwable {
- countTest();
- Class<? extends Throwable> exType = thrown.getClass();
- MethodHandle target = MethodHandles.throwException(returnType, exType);
- //System.out.println("throwing with "+target+" : "+thrown);
- MethodType expectedType = MethodType.methodType(returnType, exType);
- assertEquals(expectedType, target.type());
- target = MethodHandles.convertArguments(target, target.type().generic());
- Throwable caught = null;
- try {
- Object res = target.invokeExact((Object) thrown);
- fail("got "+res+" instead of throwing "+thrown);
- } catch (Throwable ex) {
- if (ex != thrown) {
- if (ex instanceof Error) throw (Error)ex;
- if (ex instanceof RuntimeException) throw (RuntimeException)ex;
- }
- caught = ex;
- }
- assertSame(thrown, caught);
- }
-
- @Test
- public void testCastFailure() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("testCastFailure");
- testCastFailure("cast/argument", 11000);
- testCastFailure("unbox/argument", 11000);
- testCastFailure("cast/return", 11000);
- testCastFailure("unbox/return", 11000);
- }
-
- static class Surprise {
- public MethodHandle asMethodHandle() {
- return VALUE.bindTo(this);
- }
- Object value(Object x) {
- trace("value", x);
- if (boo != null) return boo;
- return x;
- }
- Object boo;
- void boo(Object x) { boo = x; }
-
- static void trace(String x, Object y) {
- if (verbosity > 8) System.out.println(x+"="+y);
- }
- static Object refIdentity(Object x) { trace("ref.x", x); return x; }
- static Integer boxIdentity(Integer x) { trace("box.x", x); return x; }
- static int intIdentity(int x) { trace("int.x", x); return x; }
- static MethodHandle VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY;
- static {
- try {
- VALUE = PRIVATE.findVirtual(
- Surprise.class, "value",
- MethodType.methodType(Object.class, Object.class));
- REF_IDENTITY = PRIVATE.findStatic(
- Surprise.class, "refIdentity",
- MethodType.methodType(Object.class, Object.class));
- BOX_IDENTITY = PRIVATE.findStatic(
- Surprise.class, "boxIdentity",
- MethodType.methodType(Integer.class, Integer.class));
- INT_IDENTITY = PRIVATE.findStatic(
- Surprise.class, "intIdentity",
- MethodType.methodType(int.class, int.class));
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
- }
-
- void testCastFailure(String mode, int okCount) throws Throwable {
- countTest(false);
- if (verbosity > 2) System.out.println("mode="+mode);
- Surprise boo = new Surprise();
- MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0;
- if (mode.endsWith("/return")) {
- if (mode.equals("unbox/return")) {
- // fail on return to ((Integer)surprise).intValue
- surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(int.class, Object.class));
- identity = MethodHandles.convertArguments(identity, MethodType.methodType(int.class, Object.class));
- } else if (mode.equals("cast/return")) {
- // fail on return to (Integer)surprise
- surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(Integer.class, Object.class));
- identity = MethodHandles.convertArguments(identity, MethodType.methodType(Integer.class, Object.class));
- }
- } else if (mode.endsWith("/argument")) {
- MethodHandle callee = null;
- if (mode.equals("unbox/argument")) {
- // fail on handing surprise to int argument
- callee = Surprise.INT_IDENTITY;
- } else if (mode.equals("cast/argument")) {
- // fail on handing surprise to Integer argument
- callee = Surprise.BOX_IDENTITY;
- }
- if (callee != null) {
- callee = MethodHandles.convertArguments(callee, MethodType.genericMethodType(1));
- surprise = MethodHandles.filterArguments(callee, 0, surprise);
- identity = MethodHandles.filterArguments(callee, 0, identity);
- }
- }
- assertNotSame(mode, surprise, surprise0);
- identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1));
- surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1));
- Object x = 42;
- for (int i = 0; i < okCount; i++) {
- Object y = identity.invokeExact(x);
- assertEquals(x, y);
- Object z = surprise.invokeExact(x);
- assertEquals(x, z);
- }
- boo.boo("Boo!");
- Object y = identity.invokeExact(x);
- assertEquals(x, y);
- try {
- Object z = surprise.invokeExact(x);
- System.out.println("Failed to throw; got z="+z);
- assertTrue(false);
- } catch (Exception ex) {
- if (verbosity > 2)
- System.out.println("caught "+ex);
- if (verbosity > 3)
- ex.printStackTrace();
- assertTrue(ex instanceof ClassCastException
- // FIXME: accept only one of the two for any given unit test
- || ex instanceof WrongMethodTypeException
- );
- }
- }
-
- static Example userMethod(Object o, String s, int i) {
- called("userMethod", o, s, i);
- return null;
- }
-
- @Test
- public void testUserClassInSignature() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- startTest("testUserClassInSignature");
- Lookup lookup = MethodHandles.lookup();
- String name; MethodType mt; MethodHandle mh;
- Object[] args;
-
- // Try a static method.
- name = "userMethod";
- mt = MethodType.methodType(Example.class, Object.class, String.class, int.class);
- mh = lookup.findStatic(lookup.lookupClass(), name, mt);
- assertEquals(mt, mh.type());
- assertEquals(Example.class, mh.type().returnType());
- args = randomArgs(mh.type().parameterArray());
- mh.invokeWithArguments(args);
- assertCalled(name, args);
-
- // Try a virtual method.
- name = "v2";
- mt = MethodType.methodType(Object.class, Object.class, int.class);
- mh = lookup.findVirtual(Example.class, name, mt);
- assertEquals(mt, mh.type().dropParameterTypes(0,1));
- assertTrue(mh.type().parameterList().contains(Example.class));
- args = randomArgs(mh.type().parameterArray());
- mh.invokeWithArguments(args);
- assertCalled(name, args);
- }
-
- static void runForRunnable() {
- called("runForRunnable");
- }
- private interface Fooable {
- Object foo(Fooable x, Object y);
- // this is for randomArg:
- public class Impl implements Fooable {
- public Object foo(Fooable x, Object y) {
- throw new RuntimeException("do not call");
- }
- final String name;
- public Impl() { name = "Fooable#"+nextArg(); }
- @Override public String toString() { return name; }
- }
- }
- static Object fooForFooable(Fooable x, Object y) {
- return called("fooForFooable", x, y);
- }
- private static class MyCheckedException extends Exception {
- }
- private interface WillThrow {
- void willThrow() throws MyCheckedException;
- }
-
- @Test
- public void testAsInstance() throws Throwable {
- if (CAN_SKIP_WORKING) return;
- Lookup lookup = MethodHandles.lookup();
- {
- MethodType mt = MethodType.methodType(void.class);
- MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt);
- Runnable proxy = MethodHandles.asInstance(mh, Runnable.class);
- proxy.run();
- assertCalled("runForRunnable");
- }
- {
- MethodType mt = MethodType.methodType(Object.class, Fooable.class, Object.class);
- MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable", mt);
- Fooable proxy = MethodHandles.asInstance(mh, Fooable.class);
- Object[] args = randomArgs(mt.parameterArray());
- Object result = proxy.foo((Fooable) args[0], args[1]);
- assertCalled("fooForFooable", args);
- assertEquals(result, logEntry("fooForFooable", args));
- }
- for (Throwable ex : new Throwable[] { new NullPointerException("ok"),
- new InternalError("ok"),
- new Throwable("fail"),
- new Exception("fail"),
- new MyCheckedException()
- }) {
- MethodHandle mh = MethodHandles.throwException(void.class, Throwable.class);
- mh = MethodHandles.insertArguments(mh, 0, ex);
- WillThrow proxy = MethodHandles.asInstance(mh, WillThrow.class);
- try {
- proxy.willThrow();
- System.out.println("Failed to throw: "+ex);
- assertTrue(false);
- } catch (Throwable ex1) {
- if (verbosity > 2) {
- System.out.println("throw "+ex);
- System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1));
- }
- if (ex instanceof RuntimeException ||
- ex instanceof Error) {
- assertSame("must pass unchecked exception out without wrapping", ex, ex1);
- } else if (ex instanceof MyCheckedException) {
- assertSame("must pass declared exception out without wrapping", ex, ex1);
- } else {
- assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1);
- UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1;
- assertSame(ex, utex.getCause());
- }
- }
- }
- // Test error checking:
- for (Class<?> nonSAM : new Class[] { Object.class,
- String.class,
- CharSequence.class,
- Example.class }) {
- try {
- MethodHandles.asInstance(varargsArray(0), nonSAM);
- System.out.println("Failed to throw");
- assertTrue(false);
- } catch (IllegalArgumentException ex) {
- }
- }
- }
-}
-// Local abbreviated copy of sun.dyn.util.ValueConversions
-class ValueConversions {
- private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
- private static final Object[] NO_ARGS_ARRAY = {};
- private static Object[] makeArray(Object... args) { return args; }
- private static Object[] array() { return NO_ARGS_ARRAY; }
- private static Object[] array(Object a0)
- { return makeArray(a0); }
- private static Object[] array(Object a0, Object a1)
- { return makeArray(a0, a1); }
- private static Object[] array(Object a0, Object a1, Object a2)
- { return makeArray(a0, a1, a2); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3)
- { return makeArray(a0, a1, a2, a3); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4)
- { return makeArray(a0, a1, a2, a3, a4); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5)
- { return makeArray(a0, a1, a2, a3, a4, a5); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- private static Object[] array(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9)
- { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- static MethodHandle[] makeArrays() {
- ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
- MethodHandles.Lookup lookup = IMPL_LOOKUP;
- for (;;) {
- int nargs = arrays.size();
- MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class);
- String name = "array";
- MethodHandle array = null;
- try {
- array = lookup.findStatic(ValueConversions.class, name, type);
- } catch (ReflectiveOperationException ex) {
- // break from loop!
- }
- if (array == null) break;
- arrays.add(array);
- }
- assertTrue(arrays.size() == 11); // current number of methods
- return arrays.toArray(new MethodHandle[0]);
- }
- static final MethodHandle[] ARRAYS = makeArrays();
-
- /** Return a method handle that takes the indicated number of Object
- * arguments and returns an Object array of them, as if for varargs.
- */
- public static MethodHandle varargsArray(int nargs) {
- if (nargs < ARRAYS.length)
- return ARRAYS[nargs];
- // else need to spin bytecode or do something else fancy
- throw new UnsupportedOperationException("NYI: cannot form a varargs array of length "+nargs);
- }
-
- private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
- private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
- private static List<Object> list() { return NO_ARGS_LIST; }
- private static List<Object> list(Object a0)
- { return makeList(a0); }
- private static List<Object> list(Object a0, Object a1)
- { return makeList(a0, a1); }
- private static List<Object> list(Object a0, Object a1, Object a2)
- { return makeList(a0, a1, a2); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
- { return makeList(a0, a1, a2, a3); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4)
- { return makeList(a0, a1, a2, a3, a4); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5)
- { return makeList(a0, a1, a2, a3, a4, a5); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6)
- { return makeList(a0, a1, a2, a3, a4, a5, a6); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7)
- { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8)
- { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
- private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
- Object a4, Object a5, Object a6, Object a7,
- Object a8, Object a9)
- { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
- static MethodHandle[] makeLists() {
- ArrayList<MethodHandle> lists = new ArrayList<MethodHandle>();
- MethodHandles.Lookup lookup = IMPL_LOOKUP;
- for (;;) {
- int nargs = lists.size();
- MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
- String name = "list";
- MethodHandle list = null;
- try {
- list = lookup.findStatic(ValueConversions.class, name, type);
- } catch (ReflectiveOperationException ex) {
- // break from loop!
- }
- if (list == null) break;
- lists.add(list);
- }
- assertTrue(lists.size() == 11); // current number of methods
- return lists.toArray(new MethodHandle[0]);
- }
- static final MethodHandle[] LISTS = makeLists();
-
- /** Return a method handle that takes the indicated number of Object
- * arguments and returns List.
- */
- public static MethodHandle varargsList(int nargs) {
- if (nargs < LISTS.length)
- return LISTS[nargs];
- // else need to spin bytecode or do something else fancy
- throw new UnsupportedOperationException("NYI");
- }
-}
-// This guy tests access from outside the same package member, but inside
-// the package itself.
-class PackageSibling {
- static Lookup lookup() {
- return MethodHandles.lookup();
- }
-}
--- a/jdk/test/java/dyn/MethodTypeTest.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,529 +0,0 @@
-/*
- * Copyright 2008, 2011 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/* @test
- * @summary unit tests for java.dyn.MethodType
- * @compile MethodTypeTest.java
- * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.MethodTypeTest
- */
-
-package test.java.dyn;
-
-import java.dyn.MethodType;
-import java.lang.reflect.Method;
-
-import java.util.*;
-import org.junit.*;
-import static org.junit.Assert.*;
-
-/**
- *
- * @author jrose
- */
-public class MethodTypeTest {
-
- private Class<?> rtype;
- private Class<?>[] ptypes;
- private MethodType mt_viS, mt_OO, mt_OO2, mt_vv, mt_Vv, mt_Ov;
- private MethodType mt_iSI, mt_ISi, mt_ISI, mt_iSi;
- private MethodType mt_viO, mt_iO2, mt_OOi, mt_iOi;
- private MethodType mt_VIO, mt_IO2, mt_OOI, mt_IOI, mt_VIS;
- private MethodType mt_vOiSzA, mt_OO99;
- private MethodType[] GALLERY;
- private Method compareTo;
-
- @Before
- public void setUp() throws Exception {
- rtype = void.class;
- ptypes = new Class<?>[] { int.class, String.class };
-
- mt_viS = MethodType.methodType(void.class, int.class, String.class);
- mt_OO = MethodType.methodType(Object.class, Object.class);
- mt_OO2 = MethodType.methodType(Object.class, Object.class, Object.class);
- mt_vv = MethodType.methodType(void.class);
- mt_Vv = MethodType.methodType(Void.class);
- mt_Ov = MethodType.methodType(Object.class);
- mt_iSI = MethodType.methodType(int.class, String.class, Integer.class);
- mt_ISi = MethodType.methodType(Integer.class, String.class, int.class);
- mt_ISI = MethodType.methodType(Integer.class, String.class, Integer.class);
- mt_iSi = MethodType.methodType(int.class, String.class, int.class);
-
- compareTo = String.class.getDeclaredMethod("compareTo", String.class);
-
- mt_viO = MethodType.methodType(void.class, int.class, Object.class);
- mt_iO2 = MethodType.methodType(int.class, Object.class, Object.class);
- mt_OOi = MethodType.methodType(Object.class, Object.class, int.class);
- mt_iOi = MethodType.methodType(int.class, Object.class, int.class);
-
- mt_VIO = MethodType.methodType(Void.class, Integer.class, Object.class);
- mt_IO2 = MethodType.methodType(Integer.class, Object.class, Object.class);
- mt_OOI = MethodType.methodType(Object.class, Object.class, Integer.class);
- mt_IOI = MethodType.methodType(Integer.class, Object.class, Integer.class);
- mt_VIS = MethodType.methodType(Void.class, Integer.class, String.class);
-
- mt_vOiSzA = MethodType.methodType(void.class, Object.class, int.class, String.class, boolean.class, Object[].class);
- mt_OO99 = MethodType.genericMethodType(99);
-
- GALLERY = new MethodType[] {
- mt_viS, mt_OO, mt_OO2, mt_vv, mt_Vv, mt_Ov,
- mt_iSI, mt_ISi, mt_ISI, mt_iSi,
- mt_viO, mt_iO2, mt_OOi, mt_iOi,
- mt_VIO, mt_IO2, mt_OOI, mt_IOI,
- mt_VIS, mt_vOiSzA, mt_OO99
- };
- }
-
- @After
- public void tearDown() throws Exception {
- }
-
- /** Make sure the method types are all distinct. */
- @Test
- public void testDistinct() {
- List<MethodType> gallery2 = new ArrayList<>();
- for (MethodType mt : GALLERY) {
- assertFalse(mt.toString(), gallery2.contains(mt));
- gallery2.add(mt);
- }
- // check self-equality also:
- assertEquals(Arrays.asList(GALLERY), gallery2);
- }
-
- /**
- * Test of make method, of class MethodType.
- */
- @Test
- public void testMake_Class_ClassArr() {
- System.out.println("make (from type array)");
- MethodType result = MethodType.methodType(rtype, ptypes);
- assertSame(mt_viS, result);
- }
-
- /**
- * Test of make method, of class MethodType.
- */
- @Test
- public void testMake_Class_List() {
- System.out.println("make (from type list)");
- MethodType result = MethodType.methodType(rtype, Arrays.asList(ptypes));
- assertSame(mt_viS, result);
- }
-
- /**
- * Test of make method, of class MethodType.
- */
- @Test
- public void testMake_3args() {
- System.out.println("make (from type with varargs)");
- MethodType result = MethodType.methodType(rtype, ptypes[0], ptypes[1]);
- assertSame(mt_viS, result);
- }
-
- /**
- * Test of make method, of class MethodType.
- */
- @Test
- public void testMake_Class() {
- System.out.println("make (from single type)");
- Class<?> rt = Integer.class;
- MethodType expResult = MethodType.methodType(rt, new Class<?>[0]);
- MethodType result = MethodType.methodType(rt);
- assertSame(expResult, result);
- }
-
- @Test
- public void testMakeGeneric() {
- System.out.println("makeGeneric");
- int objectArgCount = 2;
- MethodType expResult = mt_OO2;
- MethodType result = MethodType.genericMethodType(objectArgCount);
- assertSame(expResult, result);
- }
-
- /**
- * Test of make method, of class MethodType.
- */
- @Test
- public void testMake_MethodType() {
- System.out.println("make (from rtype, MethodType)");
- MethodType expResult = mt_iO2;
- MethodType result = MethodType.methodType(int.class, mt_IO2);
- assertSame(expResult, result);
- }
-
- /**
- * Test of make method, of class MethodType.
- */
- @Test
- public void testMake_String_ClassLoader() {
- System.out.println("make (from bytecode signature)");
- ClassLoader loader = null;
- MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
- String obj = "Ljava/lang/Object;";
- assertEquals(obj, concat(Object.class));
- String[] expResults = {
- "(ILjava/lang/String;)V",
- concat("(", obj, 2, ")", Object.class),
- "()V", "()"+obj,
- concat("(", String.class, Integer.class, ")I"),
- concat("(", String.class, "I)", Integer.class),
- concat("(", String.class, Integer.class, ")", Integer.class),
- concat("(", String.class, "I)I")
- };
- for (int i = 0; i < instances.length; i++) {
- MethodType instance = instances[i];
- String result = instance.toMethodDescriptorString();
- assertEquals("#"+i, expResults[i], result);
- MethodType parsed = MethodType.fromMethodDescriptorString(result, loader);
- assertSame("--#"+i, instance, parsed);
- }
- }
- private static String concat(Object... parts) {
- StringBuilder sb = new StringBuilder();
- Object prevPart = "";
- for (Object part : parts) {
- if (part instanceof Class) {
- part = "L"+((Class)part).getName()+";";
- }
- if (part instanceof Integer) {
- for (int n = (Integer) part; n > 1; n--)
- sb.append(prevPart);
- part = "";
- }
- sb.append(part);
- prevPart = part;
- }
- return sb.toString().replace('.', '/');
- }
-
- @Test
- public void testHasPrimitives() {
- System.out.println("hasPrimitives");
- MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
- boolean[] expResults = {true, false, true, false, true, true, false, true};
- for (int i = 0; i < instances.length; i++) {
- boolean result = instances[i].hasPrimitives();
- assertEquals("#"+i, expResults[i], result);
- }
- }
-
- @Test
- public void testHasWrappers() {
- System.out.println("hasWrappers");
- MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
- boolean[] expResults = {false, false, false, false, true, true, true, false};
- for (int i = 0; i < instances.length; i++) {
- System.out.println(" hasWrappers "+instances[i]);
- boolean result = instances[i].hasWrappers();
- assertEquals("#"+i, expResults[i], result);
- }
- }
-
- @Test
- public void testErase() {
- System.out.println("erase");
- MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
- MethodType[] expResults = {mt_viO, mt_OO2, mt_vv, mt_Ov, mt_iO2, mt_OOi, mt_OO2, mt_iOi};
- for (int i = 0; i < instances.length; i++) {
- MethodType result = instances[i].erase();
- assertSame("#"+i, expResults[i], result);
- }
- }
-
- @Test
- public void testGeneric() {
- System.out.println("generic");
- MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
- MethodType[] expResults = {mt_OO2, mt_OO2, mt_Ov, mt_Ov, mt_OO2, mt_OO2, mt_OO2, mt_OO2};
- for (int i = 0; i < instances.length; i++) {
- MethodType result = instances[i].generic();
- assertSame("#"+i, expResults[i], result);
- }
- }
-
- @Test
- public void testWrap() {
- System.out.println("wrap");
- MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
- MethodType[] expResults = {mt_VIS, mt_OO2, mt_Vv, mt_Ov, mt_ISI, mt_ISI, mt_ISI, mt_ISI};
- for (int i = 0; i < instances.length; i++) {
- MethodType result = instances[i].wrap();
- assertSame("#"+i, expResults[i], result);
- }
- }
-
- @Test
- public void testUnwrap() {
- System.out.println("unwrap");
- MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
- MethodType[] expResults = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSi, mt_iSi, mt_iSi, mt_iSi};
- for (int i = 0; i < instances.length; i++) {
- MethodType result = instances[i].unwrap();
- assertSame("#"+i, expResults[i], result);
- }
- }
-
- /**
- * Test of parameterType method, of class MethodType.
- */
- @Test
- public void testParameterType() {
- System.out.println("parameterType");
- for (int num = 0; num < ptypes.length; num++) {
- MethodType instance = mt_viS;
- Class<?> expResult = ptypes[num];
- Class<?> result = instance.parameterType(num);
- assertSame(expResult, result);
- }
- }
-
- /**
- * Test of parameterCount method, of class MethodType.
- */
- @Test
- public void testParameterCount() {
- System.out.println("parameterCount");
- MethodType instance = mt_viS;
- int expResult = 2;
- int result = instance.parameterCount();
- assertEquals(expResult, result);
- }
-
- /**
- * Test of returnType method, of class MethodType.
- */
- @Test
- public void testReturnType() {
- System.out.println("returnType");
- MethodType instance = mt_viS;
- Class<?> expResult = void.class;
- Class<?> result = instance.returnType();
- assertSame(expResult, result);
- }
-
- /**
- * Test of parameterList method, of class MethodType.
- */
- @Test
- public void testParameterList() {
- System.out.println("parameterList");
- MethodType instance = mt_viS;
- List<Class<?>> expResult = Arrays.asList(ptypes);
- List<Class<?>> result = instance.parameterList();
- assertEquals(expResult, result);
- }
-
- /**
- * Test of parameterArray method, of class MethodType.
- */
- @Test
- public void testParameterArray() {
- System.out.println("parameterArray");
- MethodType instance = mt_viS;
- Class<?>[] expResult = ptypes;
- Class<?>[] result = instance.parameterArray();
- assertEquals(Arrays.asList(expResult), Arrays.asList(result));
- }
-
- /**
- * Test of equals method, of class MethodType.
- */
- @Test
- public void testEquals_Object() {
- System.out.println("equals");
- Object x = null;
- MethodType instance = mt_viS;
- boolean expResult = false;
- boolean result = instance.equals(x);
- assertEquals(expResult, result);
- }
-
- /**
- * Test of equals method, of class MethodType.
- */
- @Test
- public void testEquals_MethodType() {
- System.out.println("equals");
- MethodType that = mt_viS;
- MethodType instance = mt_viS;
- boolean expResult = true;
- boolean result = instance.equals(that);
- assertEquals(expResult, result);
- }
-
- /**
- * Test of hashCode method, of class MethodType.
- */
- @Test
- public void testHashCode() {
- System.out.println("hashCode");
- MethodType instance = mt_viS;
- ArrayList<Class<?>> types = new ArrayList<Class<?>>();
- types.add(instance.returnType());
- types.addAll(instance.parameterList());
- int expResult = types.hashCode();
- int result = instance.hashCode();
- assertEquals(expResult, result);
- }
-
- /**
- * Test of toString method, of class MethodType.
- */
- @Test
- public void testToString() {
- System.out.println("toString");
- MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
- //String expResult = "void[int, class java.lang.String]";
- String[] expResults = {
- "(int,String)void",
- "(Object,Object)Object",
- "()void",
- "()Object",
- "(String,Integer)int",
- "(String,int)Integer",
- "(String,Integer)Integer",
- "(String,int)int"
- };
- for (int i = 0; i < instances.length; i++) {
- MethodType instance = instances[i];
- String result = instance.toString();
- System.out.println("#"+i+":"+result);
- assertEquals("#"+i, expResults[i], result);
- }
- }
-
- private static byte[] writeSerial(Object x) throws java.io.IOException {
- try (java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
- java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(bout)
- ) {
- out.writeObject(x);
- out.flush();
- return bout.toByteArray();
- }
- }
- private static Object readSerial(byte[] wire) throws java.io.IOException, ClassNotFoundException {
- try (java.io.ByteArrayInputStream bin = new java.io.ByteArrayInputStream(wire);
- java.io.ObjectInputStream in = new java.io.ObjectInputStream(bin)) {
- return in.readObject();
- }
- }
- private static void testSerializedEquality(Object x) throws java.io.IOException, ClassNotFoundException {
- if (x instanceof Object[])
- x = Arrays.asList((Object[]) x); // has proper equals method
- byte[] wire = writeSerial(x);
- Object y = readSerial(wire);
- assertEquals(x, y);
- }
-
- /** Test (de-)serialization. */
- @Test
- public void testSerialization() throws Throwable {
- System.out.println("serialization");
- for (MethodType mt : GALLERY) {
- testSerializedEquality(mt);
- }
- testSerializedEquality(GALLERY);
-
- // Make a list of mixed objects:
- List<Object> stuff = new ArrayList<>();
- Collections.addAll(stuff, GALLERY); // copy #1
- Object[] triples = Arrays.copyOfRange(GALLERY, 0, GALLERY.length/2);
- Collections.addAll(stuff, triples); // copy #3 (partial)
- for (MethodType mt : GALLERY) {
- Collections.addAll(stuff, mt.parameterArray());
- }
- Collections.shuffle(stuff, new Random(292));
- Collections.addAll(stuff, GALLERY); // copy #2
- testSerializedEquality(stuff);
- }
-
- /** Test serialization formats. */
- @Test
- public void testPortableSerialFormat() throws Throwable {
- System.out.println("portable serial format");
- Object[][] cases = {
- { mt_vv, new byte[] { // ()void
- (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13,
- (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x64, (byte)0x79, (byte)0x6e,
- (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
- (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
- (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
- (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x6f, (byte)0x69, (byte)0x64,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00,
- (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e,
- (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61,
- (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab, (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb,
- (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
- } },
- { mt_OO, new byte[] { // (Object)Object
- (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13,
- (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x64, (byte)0x79, (byte)0x6e,
- (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
- (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
- (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
- (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61,
- (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62,
- (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
- (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00, (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a,
- (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67,
- (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61, (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab,
- (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb, (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02,
- (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01,
- (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x03, (byte)0x78,
- } },
- };
- boolean generateData = false;
- //generateData = true;
- for (Object[] c : cases) {
- MethodType mt = (MethodType) c[0];
- System.out.println("deserialize "+mt);
- byte[] wire = (byte[]) c[1];
- if (generateData) {
- wire = writeSerial(mt);
- final String INDENT = " ";
- System.out.print("{ // "+mt);
- for (int i = 0; i < wire.length; i++) {
- if (i % 8 == 0) { System.out.println(); System.out.print(INDENT+" "); }
- String hex = Integer.toHexString(wire[i] & 0xFF);
- if (hex.length() == 1) hex = "0"+hex;
- System.out.print(" (byte)0x"+hex+",");
- }
- System.out.println();
- System.out.println(INDENT+"}");
- System.out.flush();
- }
- Object decode;
- try {
- decode = readSerial(wire);
- } catch (Exception ex) {
- decode = ex; // oops!
- }
- assertEquals(mt, decode);
- }
- }
-}
--- a/jdk/test/java/dyn/indify/Indify.java Fri Mar 18 00:03:24 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1890 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package indify;
-
-import java.util.*;
-import java.io.*;
-import java.lang.reflect.Modifier;
-import java.util.regex.*;
-
-/**
- * Transform one or more class files to incorporate JSR 292 features,
- * such as {@code invokedynamic}.
- * <p>
- * This is a standalone program in a single source file.
- * In this form, it may be useful for test harnesses, small experiments, and javadoc examples.
- * Copies of this file may show up in multiple locations for standalone usage.
- * The primary maintained location of this file is as follows:
- * <a href="http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java">
- * http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java</a>
- * <p>
- * Static private methods named MH_x and MT_x (where x is arbitrary)
- * must be stereotyped generators of MethodHandle and MethodType
- * constants. All calls to them are transformed to {@code CONSTANT_MethodHandle}
- * and {@code CONSTANT_MethodType} "ldc" instructions.
- * The stereotyped code must create method types by calls to {@code methodType} or
- * {@code fromMethodDescriptorString}. The "lookup" argument must be created
- * by calls to {@code java.dyn.MethodHandles#lookup MethodHandles.lookup}.
- * The class and string arguments must be constant.
- * The following methods of {@code java.dyn.MethodHandle.Lookup Lookup} are
- * allowed for method handle creation: {@code findStatic}, {@code findVirtual},
- * {@code findConstructor}, {@code findSpecial},
- * {@code findGetter}, {@code findSetter},
- * {@code findStaticGetter}, or {@code findStaticSetter}.
- * The call to one of these methods must be followed immediately
- * by an {@code areturn} instruction.
- * The net result of the call to the MH_x or MT_x method must be
- * the creation of a constant method handle. Thus, replacing calls
- * to MH_x or MT_x methods by {@code ldc} instructions should leave
- * the meaning of the program unchanged.
- * <p>
- * Static private methods named INDY_x must be stereotyped generators
- * of {@code invokedynamic} call sites.
- * All calls to them must be immediately followed by
- * {@code invokeExact} calls.
- * All such pairs of calls are transformed to {@code invokedynamic}
- * instructions. Each INDY_x method must begin with a call to a
- * MH_x method, which is taken to be its bootstrap method.
- * The method must be immediately invoked (via {@code invokeGeneric}
- * on constant lookup, name, and type arguments. An object array of
- * constants may also be appended to the {@code invokeGeneric call}.
- * This call must be cast to {@code CallSite}, and the result must be
- * immediately followed by a call to {@code dynamicInvoker}, with the
- * resulting method handle returned.
- * <p>
- * The net result of all of these actions is equivalent to the JVM's
- * execution of an {@code invokedynamic} instruction in the unlinked state.
- * Running this code once should produce the same results as running
- * the corresponding {@code invokedynamic} instruction.
- * In order to model the caching behavior, the code of an INDY_x
- * method is allowed to begin with getstatic, aaload, and if_acmpne
- * instructions which load a static method handle value and return it
- * if the value is non-null.
- * <p>
- * Example usage:
- * <blockquote><pre>
-$ JAVA_HOME=(some recent OpenJDK 7 build)
-$ ant
-$ $JAVA_HOME/bin/java -cp build/classes indify.Indify --overwrite --dest build/testout build/classes/indify/Example.class
-$ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp build/classes indify.Example
-MT = (java.lang.Object)java.lang.Object
-MH = adder(int,int)java.lang.Integer
-adder(1,2) = 3
-calling indy: 42
-$ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp build/testout indify.Example
-(same output as above)
- * </pre></blockquote>
- * <p>
- * Before OpenJDK build b123, the format of {@code CONSTANT_InvokeDynamic} is in transition,
- * and the switch {@code --transitionalJSR292=yes} is recommended.
- * It is turned <em>off</em> by default, but users of earlier builds may need to turn it on.
- * <p>
- * A version of this transformation built on top of <a href="http://asm.ow2.org/">http://asm.ow2.org/</a> would be welcome.
- * @author John Rose
- */
-public class Indify {
- public static void main(String... av) throws IOException {
- new Indify().run(av);
- }
-
- public File dest;
- public String[] classpath = {"."};
- public boolean keepgoing = false;
- public boolean expandProperties = false;
- public boolean overwrite = false;
- public boolean quiet = false;
- public boolean verbose = false;
- public boolean transitionalJSR292 = false; // final version is distributed
- public boolean all = false;
- public int verifySpecifierCount = -1;
-
- public void run(String... av) throws IOException {
- List<String> avl = new ArrayList<>(Arrays.asList(av));
- parseOptions(avl);
- if (avl.isEmpty())
- throw new IllegalArgumentException("Usage: indify [--dest dir] [option...] file...");
- if ("--java".equals(avl.get(0))) {
- avl.remove(0);
- try {
- runApplication(avl.toArray(new String[0]));
- } catch (Exception ex) {
- if (ex instanceof RuntimeException) throw (RuntimeException) ex;
- throw new RuntimeException(ex);
- }
- return;
- }
- Exception err = null;
- for (String a : avl) {
- try {
- indify(a);
- } catch (Exception ex) {
- if (err == null) err = ex;
- System.err.println("failure on "+a);
- if (!keepgoing) break;
- }
- }
- if (err != null) {
- if (err instanceof IOException) throw (IOException) err;
- throw (RuntimeException) err;
- }
- }
-
- /** Execute the given application under a class loader which indifies all application classes. */
- public void runApplication(String... av) throws Exception {
- List<String> avl = new ArrayList<>(Arrays.asList(av));
- String mainClassName = avl.remove(0);
- av = avl.toArray(new String[0]);
- Class<?> mainClass = Class.forName(mainClassName, true, makeClassLoader());
- java.lang.reflect.Method main = mainClass.getMethod("main", String[].class);
- try { main.setAccessible(true); } catch (SecurityException ex) { }
- main.invoke(null, (Object) av);
- }
-
- public void parseOptions(List<String> av) throws IOException {
- for (; !av.isEmpty(); av.remove(0)) {
- String a = av.get(0);
- if (a.startsWith("-")) {
- String a2 = null;
- int eq = a.indexOf('=');
- if (eq > 0) {
- a2 = maybeExpandProperties(a.substring(eq+1));
- a = a.substring(0, eq+1);
- }
- switch (a) {
- case "--java":
- return; // keep this argument
- case "-d": case "--dest": case "-d=": case "--dest=":
- dest = new File(a2 != null ? a2 : maybeExpandProperties(av.remove(1)));
- break;
- case "-cp": case "--classpath":
- classpath = maybeExpandProperties(av.remove(1)).split("["+File.pathSeparatorChar+"]");
- break;
- case "-k": case "--keepgoing": case "--keepgoing=":
- keepgoing = booleanOption(a2); // print errors but keep going
- break;
- case "--expand-properties": case "--expand-properties=":
- expandProperties = booleanOption(a2); // expand property references in subsequent arguments
- break;
- case "--verify-specifier-count": case "--verify-specifier-count=":
- verifySpecifierCount = Integer.valueOf(a2);
- break;
- case "--overwrite": case "--overwrite=":
- overwrite = booleanOption(a2); // overwrite output files
- break;
- case "--all": case "--all=":
- all = booleanOption(a2); // copy all classes, even if no patterns
- break;
- case "-q": case "--quiet": case "--quiet=":
- quiet = booleanOption(a2); // less output
- break;
- case "-v": case "--verbose": case "--verbose=":
- verbose = booleanOption(a2); // more output
- break;
- case "--transitionalJSR292": case "--transitionalJSR292=":
- transitionalJSR292 = booleanOption(a2); // use older invokedynamic format
- break;
- default:
- throw new IllegalArgumentException("unrecognized flag: "+a);
- }
- continue;
- } else {
- break;
- }
- }
- if (dest == null && !overwrite)
- throw new RuntimeException("no output specified; need --dest d or --overwrite");
- if (expandProperties) {
- for (int i = 0; i < av.size(); i++)
- av.set(i, maybeExpandProperties(av.get(i)));
- }
- }
-
- private boolean booleanOption(String s) {
- if (s == null) return true;
- switch (s) {
- case "true": case "yes": case "on": case "1": return true;
- case "false": case "no": case "off": case "0": return false;
- }
- throw new IllegalArgumentException("unrecognized boolean flag="+s);
- }
-
- private String maybeExpandProperties(String s) {
- if (!expandProperties) return s;
- Set<String> propsDone = new HashSet<>();
- while (s.contains("${")) {
- int lbrk = s.indexOf("${");
- int rbrk = s.indexOf('}', lbrk);
- if (rbrk < 0) break;
- String prop = s.substring(lbrk+2, rbrk);
- if (!propsDone.add(prop)) break;
- String value = System.getProperty(prop);
- if (verbose) System.err.println("expanding ${"+prop+"} => "+value);
- if (value == null) break;
- s = s.substring(0, lbrk) + value + s.substring(rbrk+1);
- }
- return s;
- }
-
- public void indify(String a) throws IOException {
- File f = new File(a);
- String fn = f.getName();
- if (fn.endsWith(".class") && f.isFile())
- indifyFile(f, dest);
- else if (fn.endsWith(".jar") && f.isFile())
- indifyJar(f, dest);
- else if (f.isDirectory())
- indifyTree(f, dest);
- else if (!keepgoing)
- throw new RuntimeException("unrecognized file: "+a);
- }
-
- private void ensureDirectory(File dir) {
- if (dir.mkdirs() && !quiet)
- System.err.println("created "+dir);
- }
-
- public void indifyFile(File f, File dest) throws IOException {
- if (verbose) System.err.println("reading "+f);
- ClassFile cf = new ClassFile(f);
- Logic logic = new Logic(cf);
- boolean changed = logic.transform();
- logic.reportPatternMethods(quiet, keepgoing);
- if (changed || all) {
- File outfile;
- if (dest != null) {
- ensureDirectory(dest);
- outfile = classPathFile(dest, cf.nameString());
- } else {
- outfile = f; // overwrite input file, no matter where it is
- }
- cf.writeTo(outfile);
- if (!quiet) System.err.println("wrote "+outfile);
- }
- }
-
- File classPathFile(File pathDir, String className) {
- String qualname = className.replace('.','/')+".class";
- qualname = qualname.replace('/', File.separatorChar);
- return new File(pathDir, qualname);
- }
-
- public void indifyJar(File f, Object dest) throws IOException {
- throw new UnsupportedOperationException("Not yet implemented");
- }
-
- public void indifyTree(File f, File dest) throws IOException {
- if (verbose) System.err.println("reading directory: "+f);
- for (File f2 : f.listFiles(new FilenameFilter() {
- public boolean accept(File dir, String name) {
- if (name.endsWith(".class")) return true;
- if (name.contains(".")) return false;
- // return true if it might be a package name:
- return Character.isJavaIdentifierStart(name.charAt(0));
- }})) {
- if (f2.getName().endsWith(".class"))
- indifyFile(f2, dest);
- else if (f2.isDirectory())
- indifyTree(f2, dest);
- }
- }
-
- public ClassLoader makeClassLoader() {
- return new Loader();
- }
- private class Loader extends ClassLoader {
- Loader() {
- this(Indify.class.getClassLoader());
- }
- Loader(ClassLoader parent) {
- super(parent);
- }
- public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
- File f = findClassInPath(name);
- if (f != null) {
- try {
- Class<?> c = transformAndLoadClass(f);
- if (c != null) {
- if (resolve) resolveClass(c);
- return c;
- }
- } catch (Exception ex) {
- if (ex instanceof IllegalArgumentException)
- // pass error from reportPatternMethods
- throw (IllegalArgumentException) ex;
- }
- }
- return super.loadClass(name, resolve);
- }
- private File findClassInPath(String name) {
- for (String s : classpath) {
- File f = classPathFile(new File(s), name);
- //System.out.println("Checking for "+f);
- if (f.exists() && f.canRead()) {
- return f;
- }
- }
- return null;
- }
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- try {
- return transformAndLoadClass(findClassInPath(name));
- } catch (IOException ex) {
- throw new ClassNotFoundException("IO error", ex);
- }
- }
- private Class<?> transformAndLoadClass(File f) throws ClassNotFoundException, IOException {
- if (verbose) System.err.println("Loading class from "+f);
- ClassFile cf = new ClassFile(f);
- Logic logic = new Logic(cf);
- boolean changed = logic.transform();
- if (verbose && !changed) System.err.println("(no change)");
- logic.reportPatternMethods(!verbose, keepgoing);
- byte[] bytes = cf.toByteArray();
- return defineClass(null, bytes, 0, bytes.length);
- }
- }
-
- private class Logic {
- // Indify logic, per se.
- ClassFile cf;
- final char[] poolMarks;
- final Map<Method,Constant> constants = new HashMap<>();
- final Map<Method,String> indySignatures = new HashMap<>();
- Logic(ClassFile cf) {
- this.cf = cf;
- poolMarks = new char[cf.pool.size()];
- }
- boolean transform() {
- if (!initializeMarks()) return false;
- if (!findPatternMethods()) return false;
- Pool pool = cf.pool;
- //for (Constant c : cp) System.out.println(" # "+c);
- for (Method m : cf.methods) {
- if (constants.containsKey(m)) continue; // don't bother
- // Transform references.
- int blab = 0;
- for (Instruction i = m.instructions(); i != null; i = i.next()) {
- if (i.bc != opc_invokestatic) continue;
- int methi = i.u2At(1);
- if (poolMarks[methi] == 0) continue;
- Short[] ref = pool.getMemberRef((short)methi);
- Method conm = findMember(cf.methods, ref[1], ref[2]);
- if (conm == null) continue;
- Constant con = constants.get(conm);
- if (con == null) continue;
- if (blab++ == 0 && !quiet)
- System.err.println("patching "+cf.nameString()+"."+m);
- //if (blab == 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println(" |"+j); }
- if (con.tag == CONSTANT_InvokeDynamic ||
- con.tag == CONSTANT_InvokeDynamic_17) {
- // need to patch the following instruction too,
- // but there are usually intervening argument pushes too
- Instruction i2 = findPop(i);
- Short[] ref2 = null;
- short ref2i = 0;
- if (i2 != null && i2.bc == opc_invokevirtual &&
- poolMarks[(char)(ref2i = (short) i2.u2At(1))] == 'D')
- ref2 = pool.getMemberRef(ref2i);
- if (ref2 == null || !"invokeExact".equals(pool.getString(ref2[1]))) {
- System.err.println(m+": failed to create invokedynamic at "+i.pc);
- continue;
- }
- String invType = pool.getString(ref2[2]);
- String bsmType = indySignatures.get(conm);
- if (!invType.equals(bsmType)) {
- System.err.println(m+": warning: "+conm+" call type and local invoke type differ: "
- +bsmType+", "+invType);
- }
- assert(i.len == 3 || i2.len == 3);
- if (!quiet) System.err.println(i+" "+conm+";...; "+i2+" => invokedynamic "+con);
- int start = i.pc + 3, end = i2.pc;
- System.arraycopy(i.codeBase, start, i.codeBase, i.pc, end-start);
- i.forceNext(0); // force revisit of new instruction
- i2.u1AtPut(-3, opc_invokedynamic);
- i2.u2AtPut(-2, con.index);
- i2.u2AtPut(0, (short)0);
- i2.u1AtPut(2, opc_nop);
- //System.out.println(new Instruction(i.codeBase, i2.pc-3));
- } else {
- if (!quiet) System.err.println(i+" "+conm+" => ldc "+con);
- assert(i.len == 3);
- i.u1AtPut(0, opc_ldc_w);
- i.u2AtPut(1, con.index);
- }
- }
- //if (blab >= 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println(" |"+j); }
- }
- cf.methods.removeAll(constants.keySet());
- return true;
- }
-
- // Scan forward from the instruction to find where the stack p
- // below the current sp at the instruction.
- Instruction findPop(Instruction i) {
- //System.out.println("findPop from "+i);
- Pool pool = cf.pool;
- JVMState jvm = new JVMState();
- decode:
- for (i = i.clone().next(); i != null; i = i.next()) {
- String pops = INSTRUCTION_POPS[i.bc];
- //System.out.println(" "+i+" "+jvm.stack+" : "+pops.replace("$", " => "));
- if (pops == null) break;
- if (jvm.stackMotion(i.bc)) continue decode;
- if (pops.indexOf('Q') >= 0) {
- Short[] ref = pool.getMemberRef((short) i.u2At(1));
- String type = simplifyType(pool.getString(CONSTANT_Utf8, ref[2]));
- switch (i.bc) {
- case opc_getstatic:
- case opc_getfield:
- case opc_putstatic:
- case opc_putfield:
- pops = pops.replace("Q", type);
- break;
- default:
- if (!type.startsWith("("))
- throw new InternalError(i.toString());
- pops = pops.replace("Q$Q", type.substring(1).replace(")","$"));
- break;
- }
- //System.out.println("special type: "+type+" => "+pops);
- }
- int npops = pops.indexOf('$');
- if (npops < 0) throw new InternalError();
- if (npops > jvm.sp()) return i;
- List<Object> args = jvm.args(npops);
- int k = 0;
- for (Object x : args) {
- char have = (Character) x;
- char want = pops.charAt(k++);
- if (have == 'X' || want == 'X') continue;
- if (have != want) break decode;
- }
- if (pops.charAt(k++) != '$') break decode;
- args.clear();
- while (k < pops.length())
- args.add(pops.charAt(k++));
- }
- System.err.println("*** bailout on jvm: "+jvm.stack+" "+i);
- return null;
- }
-
- boolean findPatternMethods() {
- boolean found = false;
- for (char mark : "THI".toCharArray()) {
- for (Method m : cf.methods) {
- if (!Modifier.isPrivate(m.access)) continue;
- if (!Modifier.isStatic(m.access)) continue;
- if (nameAndTypeMark(m.name, m.type) == mark) {
- Constant con = scanPattern(m, mark);
- if (con == null) continue;
- constants.put(m, con);
- found = true;
- }
- }
- }
- return found;
- }
-
- void reportPatternMethods(boolean quietly, boolean allowMatchFailure) {
- if (!quietly && !constants.keySet().isEmpty())
- System.err.println("pattern methods removed: "+constants.keySet());
- for (Method m : cf.methods) {
- if (nameMark(cf.pool.getString(m.name)) != 0 &&
- constants.get(m) == null) {
- String failure = "method has special name but fails to match pattern: "+m;
- if (!allowMatchFailure)
- throw new IllegalArgumentException(failure);
- else if (!quietly)
- System.err.println("warning: "+failure);
- }
- }
- if (verifySpecifierCount >= 0) {
- List<Object[]> specs = bootstrapMethodSpecifiers(false);
- int specsLen = (specs == null ? 0 : specs.size());
- if (specsLen != verifySpecifierCount) {
- throw new IllegalArgumentException("BootstrapMethods length is "+specsLen+" but should be "+verifySpecifierCount);
- }
- }
- if (!quiet) System.err.flush();
- }
-
- // mark constant pool entries according to participation in patterns
- boolean initializeMarks() {
- boolean changed = false;
- for (;;) {
- boolean changed1 = false;
- int cpindex = -1;
- for (Constant e : cf.pool) {
- ++cpindex;
- if (e == null) continue;
- char mark = poolMarks[cpindex];
- if (mark != 0) continue;
- switch (e.tag) {
- case CONSTANT_Utf8:
- mark = nameMark(e.itemString()); break;
- case CONSTANT_NameAndType:
- mark = nameAndTypeMark(e.itemIndexes()); break;
- case CONSTANT_Class: {
- int n1 = e.itemIndex();
- char nmark = poolMarks[(char)n1];
- if ("DJ".indexOf(nmark) >= 0)
- mark = nmark;
- break;
- }
- case CONSTANT_Field:
- case CONSTANT_Method: {
- Short[] n12 = e.itemIndexes();
- short cl = n12[0];
- short nt = n12[1];
- char cmark = poolMarks[(char)cl];
- if (cmark != 0) {
- mark = cmark; // it is a java.dyn.* or java.lang.* method
- break;
- }
- String cls = cf.pool.getString(CONSTANT_Class, cl);
- if (cls.equals(cf.nameString())) {
- switch (poolMarks[(char)nt]) {
- // it is a private MH/MT/INDY method
- case 'T': case 'H': case 'I':
- mark = poolMarks[(char)nt];
- break;
- }
- }
- break;
- }
- default: break;
- }
- if (mark != 0) {
- poolMarks[cpindex] = mark;
- changed1 = true;
- }
- }
- if (!changed1)
- break;
- changed = true;
- }
- return changed;
- }
- char nameMark(String s) {
- if (s.startsWith("MT_")) return 'T';
- else if (s.startsWith("MH_")) return 'H';
- else if (s.startsWith("INDY_")) return 'I';
- else if (s.startsWith("java/dyn/")) return 'D';
- else if (s.startsWith("java/lang/")) return 'J';
- return 0;
- }
- char nameAndTypeMark(Short[] n12) {
- return nameAndTypeMark(n12[0], n12[1]);
- }
- char nameAndTypeMark(short n1, short n2) {
- char mark = poolMarks[(char)n1];
- if (mark == 0) return 0;
- String descr = cf.pool.getString(CONSTANT_Utf8, n2);
- String requiredType;
- switch (poolMarks[(char)n1]) {
- case 'H': requiredType = "()Ljava/dyn/MethodHandle;"; break;
- case 'T': requiredType = "()Ljava/dyn/MethodType;"; break;
- case 'I': requiredType = "()Ljava/dyn/MethodHandle;"; break;
- default: return 0;
- }
- if (descr.equals(requiredType)) return mark;
- return 0;
- }
-
- private class JVMState {
- final List<Object> stack = new ArrayList<>();
- int sp() { return stack.size(); }
- void push(Object x) { stack.add(x); }
- void push2(Object x) { stack.add(EMPTY_SLOT); stack.add(x); }
- void pushAt(int pos, Object x) { stack.add(stack.size()+pos, x); }
- Object pop() { return stack.remove(sp()-1); }
- Object top() { return stack.get(sp()-1); }
- List<Object> args(boolean hasRecv, String type) {
- return args(argsize(type) + (hasRecv ? 1 : 0));
- }
- List<Object> args(int argsize) {
- return stack.subList(sp()-argsize, sp());
- }
- boolean stackMotion(int bc) {
- switch (bc) {
- case opc_pop: pop(); break;
- case opc_pop2: pop(); pop(); break;
- case opc_swap: pushAt(-1, pop()); break;
- case opc_dup: push(top()); break;
- case opc_dup_x1: pushAt(-2, top()); break;
- case opc_dup_x2: pushAt(-3, top()); break;
- // ? also: dup2{,_x1,_x2}
- default: return false;
- }
- return true;
- }
- }
- private final String EMPTY_SLOT = "_";
- private void removeEmptyJVMSlots(List<Object> args) {
- for (;;) {
- int i = args.indexOf(EMPTY_SLOT);
- if (i >= 0 && i+1 < args.size()
- && (isConstant(args.get(i+1), CONSTANT_Long) ||
- isConstant(args.get(i+1), CONSTANT_Double)))
- args.remove(i);
- else break;
- }
- }
-
- private Constant scanPattern(Method m, char patternMark) {
- if (verbose) System.err.println("scan "+m+" for pattern="+patternMark);
- int wantTag;
- switch (patternMark) {
- case 'T': wantTag = CONSTANT_MethodType; break;
- case 'H': wantTag = CONSTANT_MethodHandle; break;
- case 'I': wantTag = CONSTANT_InvokeDynamic; break;
- default: throw new InternalError();
- }
- Instruction i = m.instructions();
- JVMState jvm = new JVMState();
- Pool pool = cf.pool;
- int branchCount = 0;
- Object arg;
- List<Object> args;
- List<Object> bsmArgs = null; // args to invokeGeneric
- decode:
- for (; i != null; i = i.next()) {
- //System.out.println(jvm.stack+" "+i);
- int bc = i.bc;
- switch (bc) {
- case opc_ldc: jvm.push(pool.get(i.u1At(1))); break;
- case opc_ldc_w: jvm.push(pool.get(i.u2At(1))); break;
- case opc_ldc2_w: jvm.push2(pool.get(i.u2At(1))); break;
- case opc_aconst_null: jvm.push(null); break;
- case opc_bipush: jvm.push((int)(byte) i.u1At(1)); break;
- case opc_sipush: jvm.push((int)(short)i.u2At(1)); break;
-
- // these support creation of a restarg array
- case opc_anewarray:
- arg = jvm.pop();
- if (!(arg instanceof Integer)) break decode;
- arg = Arrays.asList(new Object[(Integer)arg]);
- jvm.push(arg);
- break;
- case opc_dup:
- jvm.push(jvm.top()); break;
- case opc_aastore:
- args = jvm.args(3); // array, index, value
- if (args.get(0) instanceof List &&
- args.get(1) instanceof Integer) {
- ((List<Object>)args.get(0)).set( (Integer)args.get(1), args.get(2) );
- }
- args.clear();
- break;
-
- case opc_new:
- {
- String type = pool.getString(CONSTANT_Class, (short)i.u2At(1));
- //System.out.println("new "+type);
- switch (type) {
- case "java/lang/StringBuilder":
- jvm.push("StringBuilder");
- continue decode; // go to next instruction
- }
- break decode; // bail out
- }
-
- case opc_getstatic:
- {
- // int.class compiles to getstatic Integer.TYPE
- int fieldi = i.u2At(1);
- char mark = poolMarks[fieldi];
- //System.err.println("getstatic "+fieldi+Arrays.asList(pool.getStrings(pool.getMemberRef((short)fieldi)))+mark);
- if (mark == 'J') {
- Short[] ref = pool.getMemberRef((short) fieldi);
- String name = pool.getString(CONSTANT_Utf8, ref[1]);
- if ("TYPE".equals(name)) {
- String wrapperName = pool.getString(CONSTANT_Class, ref[0]).replace('/', '.');
- // a primitive type descriptor
- Class<?> primClass;
- try {
- primClass = (Class<?>) Class.forName(wrapperName).getField(name).get(null);
- } catch (Exception ex) {
- throw new InternalError("cannot load "+wrapperName+"."+name);
- }
- jvm.push(primClass);
- break;
- }
- }
- // unknown field; keep going...
- jvm.push(UNKNOWN_CON);
- break;
- }
- case opc_putstatic:
- {
- if (patternMark != 'I') break decode;
- jvm.pop();
- // unknown field; keep going...
- break;
- }
-
- case opc_invokestatic:
- case opc_invokevirtual:
- case opc_invokespecial:
- {
- boolean hasRecv = (bc != opc_invokestatic);
- int methi = i.u2At(1);
- char mark = poolMarks[methi];
- Short[] ref = pool.getMemberRef((short)methi);
- String type = pool.getString(CONSTANT_Utf8, ref[2]);
- //System.out.println("invoke "+pool.getString(CONSTANT_Utf8, ref[1])+" "+Arrays.asList(ref)+" : "+type);
- args = jvm.args(hasRecv, type);
- String intrinsic = null;
- Constant con;
- if (mark == 'D' || mark == 'J') {
- intrinsic = pool.getString(CONSTANT_Utf8, ref[1]);
- if (mark == 'J') {
- String cls = pool.getString(CONSTANT_Class, ref[0]);
- cls = cls.substring(1+cls.lastIndexOf('/'));
- intrinsic = cls+"."+intrinsic;
- }
- //System.out.println("recognized intrinsic "+intrinsic);
- byte refKind = -1;
- switch (intrinsic) {
- case "findGetter": refKind = REF_getField; break;
- case "findStaticGetter": refKind = REF_getStatic; break;
- case "findSetter": refKind = REF_putField; break;
- case "findStaticSetter": refKind = REF_putStatic; break;
- case "findVirtual": refKind = REF_invokeVirtual; break;
- case "findStatic": refKind = REF_invokeStatic; break;
- case "findSpecial": refKind = REF_invokeSpecial; break;
- case "findConstructor": refKind = REF_newInvokeSpecial; break;
- }
- if (refKind >= 0 && (con = parseMemberLookup(refKind, args)) != null) {
- args.clear(); args.add(con);
- continue;
- }
- }
- Method ownMethod = null;
- if (mark == 'T' || mark == 'H' || mark == 'I') {
- ownMethod = findMember(cf.methods, ref[1], ref[2]);
- }
- //if (intrinsic != null) System.out.println("intrinsic = "+intrinsic);
- switch (intrinsic == null ? "" : intrinsic) {
- case "fromMethodDescriptorString":
- con = makeMethodTypeCon(args.get(0));
- args.clear(); args.add(con);
- continue;
- case "methodType": {
- flattenVarargs(args); // there are several overloadings, some with varargs
- StringBuilder buf = new StringBuilder();
- String rtype = null;
- for (Object typeArg : args) {
- if (typeArg instanceof Class) {
- Class<?> argClass = (Class<?>) typeArg;
- if (argClass.isPrimitive()) {
- char tchar;
- switch (argClass.getName()) {
- case "void": tchar = 'V'; break;
- case "boolean": tchar = 'Z'; break;
- case "byte": tchar = 'B'; break;
- case "char": tchar = 'C'; break;
- case "short": tchar = 'S'; break;
- case "int": tchar = 'I'; break;
- case "long": tchar = 'J'; break;
- case "float": tchar = 'F'; break;
- case "double": tchar = 'D'; break;
- default: throw new InternalError(argClass.toString());
- }
- buf.append(tchar);
- } else {
- // should not happen, but...
- buf.append('L').append(argClass.getName().replace('.','/')).append(';');
- }
- } else if (typeArg instanceof Constant) {
- Constant argCon = (Constant) typeArg;
- if (argCon.tag == CONSTANT_Class) {
- String cn = pool.get(argCon.itemIndex()).itemString();
- if (cn.endsWith(";"))
- buf.append(cn);
- else
- buf.append('L').append(cn).append(';');
- } else {
- break decode;
- }
- } else {
- break decode;
- }
- if (rtype == null) {
- // first arg is treated differently
- rtype = buf.toString();
- buf.setLength(0);
- buf.append('(');
- }
- }
- buf.append(')').append(rtype);
- con = con = makeMethodTypeCon(buf.toString());
- args.clear(); args.add(con);
- continue;
- }
- case "lookup":
- case "dynamicInvoker":
- args.clear(); args.add(intrinsic);
- continue;
- case "lookupClass":
- if (args.equals(Arrays.asList("lookup"))) {
- // fold lookup().lookupClass() to the enclosing class
- args.clear(); args.add(pool.get(cf.thisc));
- continue;
- }
- break;
- case "invokeGeneric":
- case "invokeWithArguments":
- if (patternMark != 'I') break decode;
- if ("invokeWithArguments".equals(intrinsic))
- flattenVarargs(args);
- bsmArgs = new ArrayList(args);
- args.clear(); args.add("invokeGeneric");
- continue;
- case "Integer.valueOf":
- case "Float.valueOf":
- case "Long.valueOf":
- case "Double.valueOf":
- removeEmptyJVMSlots(args);
- if (args.size() == 1) {
- arg = args.remove(0);
- assert(3456 == (CONSTANT_Integer*1000 + CONSTANT_Float*100 + CONSTANT_Long*10 + CONSTANT_Double));
- if (isConstant(arg, CONSTANT_Integer + "IFLD".indexOf(intrinsic.charAt(0)))
- || arg instanceof Number) {
- args.add(arg); continue;
- }
- }
- break decode;
- case "StringBuilder.append":
- // allow calls like ("value = "+x)
- removeEmptyJVMSlots(args);
- args.subList(1, args.size()).clear();
- continue;
- case "StringBuilder.toString":
- args.clear();
- args.add(intrinsic);
- continue;
- }
- if (!hasRecv && ownMethod != null && patternMark != 0) {
- con = constants.get(ownMethod);
- if (con == null) break decode;
- args.clear(); args.add(con);
- continue;
- } else if (type.endsWith(")V")) {
- // allow calls like println("reached the pattern method")
- args.clear();
- continue;
- }
- break decode; // bail out for most calls
- }
- case opc_areturn:
- {
- ++branchCount;
- if (bsmArgs != null) {
- // parse bsmArgs as (MH, lookup, String, MT, [extra])
- Constant indyCon = makeInvokeDynamicCon(bsmArgs);
- if (indyCon != null) {
- Constant typeCon = (Constant) bsmArgs.get(3);
- indySignatures.put(m, pool.getString(typeCon.itemIndex()));
- return indyCon;
- }
- System.err.println(m+": inscrutable bsm arguments: "+bsmArgs);
- break decode; // bail out
- }
- arg = jvm.pop();
- if (branchCount == 2 && UNKNOWN_CON.equals(arg))
- break; // merge to next path
- if (isConstant(arg, wantTag))
- return (Constant) arg;
- break decode; // bail out
- }
- default:
- if (jvm.stackMotion(i.bc)) break;
- if (bc >= opc_nconst_MIN && bc <= opc_nconst_MAX)
- { jvm.push(INSTRUCTION_CONSTANTS[bc - opc_nconst_MIN]); break; }
- if (patternMark == 'I') {
- // these support caching paths in INDY_x methods
- if (bc == opc_aload || bc >= opc_aload_0 && bc <= opc_aload_MAX)
- { jvm.push(UNKNOWN_CON); break; }
- if (bc == opc_astore || bc >= opc_astore_0 && bc <= opc_astore_MAX)
- { jvm.pop(); break; }
- switch (bc) {
- case opc_getfield:
- case opc_aaload:
- jvm.push(UNKNOWN_CON); break;
- case opc_ifnull:
- case opc_ifnonnull:
- // ignore branch target
- if (++branchCount != 1) break decode;
- jvm.pop();
- break;
- case opc_checkcast:
- arg = jvm.top();
- if ("invokeWithArguments".equals(arg) ||
- "invokeGeneric".equals(arg))
- break; // assume it is a helpful cast
- break decode;
- default:
- break decode; // bail out
- }
- continue decode; // go to next instruction
- }
- break decode; // bail out
- } //end switch
- }
- System.err.println(m+": bailout on "+i+" jvm stack: "+jvm.stack);
- return null;
- }
- private final String UNKNOWN_CON = "<unknown>";
-
- private void flattenVarargs(List<Object> args) {
- int size = args.size();
- if (size > 0 && args.get(size-1) instanceof List)
- args.addAll((List<Object>) args.remove(size-1));
- }
-
- private boolean isConstant(Object x, int tag) {
- return x instanceof Constant && ((Constant)x).tag == tag;
- }
- private Constant makeMethodTypeCon(Object x) {
- short utfIndex;
- if (x instanceof String)
- utfIndex = (short) cf.pool.addConstant(CONSTANT_Utf8, x).index;
- else if (isConstant(x, CONSTANT_String))
- utfIndex = ((Constant)x).itemIndex();
- else return null;
- return cf.pool.addConstant(CONSTANT_MethodType, utfIndex);
- }
- private Constant parseMemberLookup(byte refKind, List<Object> args) {
- // E.g.: lookup().findStatic(Foo.class, "name", MethodType)
- if (args.size() != 4) return null;
- int argi = 0;
- if (!"lookup".equals(args.get(argi++))) return null;
- short refindex, cindex, ntindex, nindex, tindex;
- Object con;
- if (!isConstant(con = args.get(argi++), CONSTANT_Class)) return null;
- cindex = (short)((Constant)con).index;
- if (!isConstant(con = args.get(argi++), CONSTANT_String)) return null;
- nindex = ((Constant)con).itemIndex();
- if (isConstant(con = args.get(argi++), CONSTANT_MethodType) ||
- isConstant(con, CONSTANT_Class)) {
- tindex = ((Constant)con).itemIndex();
- } else return null;
- ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
- new Short[]{ nindex, tindex }).index;
- byte reftag = CONSTANT_Method;
- if (refKind <= REF_putStatic)
- reftag = CONSTANT_Field;
- else if (refKind == REF_invokeInterface)
- reftag = CONSTANT_InterfaceMethod;
- Constant ref = cf.pool.addConstant(reftag, new Short[]{ cindex, ntindex });
- return cf.pool.addConstant(CONSTANT_MethodHandle, new Object[]{ refKind, (short)ref.index });
- }
- private Constant makeInvokeDynamicCon(List<Object> args) {
- // E.g.: MH_bsm.invokeGeneric(lookup(), "name", MethodType, "extraArg")
- removeEmptyJVMSlots(args);
- if (args.size() != 4 && args.size() != 5) return null;
- int argi = 0;
- short nindex, tindex, ntindex, bsmindex;
- Object con;
- if (!isConstant(con = args.get(argi++), CONSTANT_MethodHandle)) return null;
- bsmindex = (short) ((Constant)con).index;
- if (!"lookup".equals(args.get(argi++))) return null;
- if (!isConstant(con = args.get(argi++), CONSTANT_String)) return null;
- nindex = ((Constant)con).itemIndex();
- if (!isConstant(con = args.get(argi++), CONSTANT_MethodType)) return null;
- tindex = ((Constant)con).itemIndex();
- ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
- new Short[]{ nindex, tindex }).index;
- if (transitionalJSR292) {
- if (argi != args.size()) {
- System.err.println("BSM specifier has extra arguments but transitionalJSR292=1");
- return null;
- }
- return cf.pool.addConstant(CONSTANT_InvokeDynamic_17,
- new Short[]{ bsmindex, ntindex });
- }
- List<Object> extraArgs = Collections.emptyList();
- if (argi < args.size()) {
- Object arg = args.get(argi);
- if (arg instanceof List)
- extraArgs = (List<Object>) arg;
- else
- extraArgs = Arrays.asList(arg);
- removeEmptyJVMSlots(args);
- }
- List<Short> extraArgIndexes = new CountedList<>(Short.class);
- for (Object x : extraArgs) {
- if (x instanceof Number) {
- Object num = null; byte numTag = 0;
- if (x instanceof Integer) { num = x; numTag = CONSTANT_Integer; }
- if (x instanceof Float) { num = Float.floatToRawIntBits((Float)x); numTag = CONSTANT_Float; }
- if (x instanceof Long) { num = x; numTag = CONSTANT_Long; }
- if (x instanceof Double) { num = Double.doubleToRawLongBits((Double)x); numTag = CONSTANT_Double; }
- if (num != null) x = cf.pool.addConstant(numTag, x);
- }
- if (!(x instanceof Constant)) return null;
- extraArgIndexes.add((short) ((Constant)x).index);
- }
- List<Object[]> specs = bootstrapMethodSpecifiers(true);
- int specindex = -1;
- Object[] spec = new Object[]{ bsmindex, extraArgIndexes };
- for (Object[] spec1 : specs) {
- if (Arrays.equals(spec1, spec)) {
- specindex = specs.indexOf(spec1);
- if (verbose) System.err.println("reusing BSM specifier: "+spec1[0]+spec1[1]);
- break;
- }
- }
- if (specindex == -1) {
- specindex = (short) specs.size();
- specs.add(spec);
- if (verbose) System.err.println("adding BSM specifier: "+spec[0]+spec[1]);
- }
- return cf.pool.addConstant(CONSTANT_InvokeDynamic,
- new Short[]{ (short)specindex, ntindex });
- }
-
- List<Object[]> bootstrapMethodSpecifiers(boolean createIfNotFound) {
- Attr bsms = cf.findAttr("BootstrapMethods");
- if (bsms == null) {
- if (!createIfNotFound) return null;
- bsms = new Attr(cf, "BootstrapMethods", new byte[]{0,0});
- assert(bsms == cf.findAttr("BootstrapMethods"));
- }
- if (bsms.item instanceof byte[]) {
- // unflatten
- List<Object[]> specs = new CountedList<>(Object[].class);
- DataInputStream in = new DataInputStream(new ByteArrayInputStream((byte[]) bsms.item));
- try {
- int len = (char) in.readShort();
- for (int i = 0; i < len; i++) {
- short bsm = in.readShort();
- int argc = (char) in.readShort();
- List<Short> argv = new CountedList<>(Short.class);
- for (int j = 0; j < argc; j++)
- argv.add(in.readShort());
- specs.add(new Object[]{ bsm, argv });
- }
- } catch (IOException ex) { throw new InternalError(); }
- bsms.item = specs;
- }
- return (List<Object[]>) bsms.item;
- }
- }
-
- private DataInputStream openInput(File f) throws IOException {
- return new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
- }
-
- private DataOutputStream openOutput(File f) throws IOException {
- if (!overwrite && f.exists())
- throw new IOException("file already exists: "+f);
- ensureDirectory(f.getParentFile());
- return new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
- }
-
- static byte[] readRawBytes(DataInputStream in, int size) throws IOException {
- byte[] bytes = new byte[size];
- int nr = in.read(bytes);
- if (nr != size)
- throw new InternalError("wrong size: "+nr);
- return bytes;
- }
-
- private interface Chunk {
- void readFrom(DataInputStream in) throws IOException;
- void writeTo(DataOutputStream out) throws IOException;
- }
-
- private static class CountedList<T> extends ArrayList<T> implements Chunk {
- final Class<? extends T> itemClass;
- final int rowlen;
- CountedList(Class<? extends T> itemClass, int rowlen) {
- this.itemClass = itemClass;
- this.rowlen = rowlen;
- }
- CountedList(Class<? extends T> itemClass) { this(itemClass, -1); }
- public void readFrom(DataInputStream in) throws IOException {
- int count = in.readUnsignedShort();
- while (size() < count) {
- if (rowlen < 0) {
- add(readInput(in, itemClass));
- } else {
- Class<?> elemClass = itemClass.getComponentType();
- Object[] row = (Object[]) java.lang.reflect.Array.newInstance(elemClass, rowlen);
- for (int i = 0; i < rowlen; i++)
- row[i] = readInput(in, elemClass);
- add(itemClass.cast(row));
- }
- }
- }
- public void writeTo(DataOutputStream out) throws IOException {
- out.writeShort((short)size());
- for (T item : this) {
- writeOutput(out, item);
- }
- }
- }
-
- private static <T> T readInput(DataInputStream in, Class<T> dataClass) throws IOException {
- Object data;
- if (dataClass == Integer.class) {
- data = in.readInt();
- } else if (dataClass == Short.class) {
- data = in.readShort();
- } else if (dataClass == Byte.class) {
- data = in.readByte();
- } else if (dataClass == String.class) {
- data = in.readUTF();
- } else if (Chunk.class.isAssignableFrom(dataClass)) {
- T obj;
- try { obj = dataClass.newInstance(); }
- catch (Exception ex) { throw new RuntimeException(ex); }
- ((Chunk)obj).readFrom(in);
- data = obj;
- } else {
- throw new InternalError("bad input datum: "+dataClass);
- }
- return dataClass.cast(data);
- }
- private static <T> T readInput(byte[] bytes, Class<T> dataClass) {
- try {
- return readInput(new DataInputStream(new ByteArrayInputStream(bytes)), dataClass);
- } catch (IOException ex) {
- throw new InternalError();
- }
- }
- private static void readInputs(DataInputStream in, Object... data) throws IOException {
- for (Object x : data) ((Chunk)x).readFrom(in);
- }
-
- private static void writeOutput(DataOutputStream out, Object data) throws IOException {
- if (data == null) {
- return;
- } if (data instanceof Integer) {
- out.writeInt((Integer)data);
- } else if (data instanceof Long) {
- out.writeLong((Long)data);
- } else if (data instanceof Short) {
- out.writeShort((Short)data);
- } else if (data instanceof Byte) {
- out.writeByte((Byte)data);
- } else if (data instanceof String) {
- out.writeUTF((String)data);
- } else if (data instanceof byte[]) {
- out.write((byte[])data);
- } else if (data instanceof Object[]) {
- for (Object x : (Object[]) data)
- writeOutput(out, x);
- } else if (data instanceof Chunk) {
- Chunk x = (Chunk) data;
- x.writeTo(out);
- } else if (data instanceof List) {
- for (Object x : (List<?>) data)
- writeOutput(out, x);
- } else {
- throw new InternalError("bad output datum: "+data+" : "+data.getClass().getName());
- }
- }
- private static void writeOutputs(DataOutputStream out, Object... data) throws IOException {
- for (Object x : data) writeOutput(out, x);
- }
-
- public static abstract class Outer {
- public abstract List<? extends Inner> inners();
- protected void linkInners() {
- for (Inner i : inners()) {
- i.linkOuter(this);
- if (i instanceof Outer)
- ((Outer)i).linkInners();
- }
- }
- public <T extends Outer> T outer(Class<T> c) {
- for (Outer walk = this;; walk = ((Inner)walk).outer()) {
- if (c.isInstance(walk))
- return c.cast(walk);
- //if (!(walk instanceof Inner)) return null;
- }
- }
-
- public abstract List<Attr> attrs();
- public Attr findAttr(String name) {
- return findAttr(outer(ClassFile.class).pool.stringIndex(name, false));
- }
- public Attr findAttr(int name) {
- if (name == 0) return null;
- for (Attr a : attrs()) {
- if (a.name == name) return a;
- }
- return null;
- }
- }
- public interface Inner { Outer outer(); void linkOuter(Outer o); }
- public static abstract class InnerOuter extends Outer implements Inner {
- public Outer outer;
- public Outer outer() { return outer; }
- public void linkOuter(Outer o) { assert(outer == null); outer = o; }
- }
- public static class Constant<T> implements Chunk {
- public final byte tag;
- public final T item;
- public final int index;
- public Constant(int index, byte tag, T item) {
- this.index = index;
- this.tag = tag;
- this.item = item;
- }
- public Constant checkTag(byte tag) {
- if (this.tag != tag) throw new InternalError(this.toString());
- return this;
- }
- public String itemString() { return (String)item; }
- public Short itemIndex() { return (Short)item; }
- public Short[] itemIndexes() { return (Short[])item; }
- public void readFrom(DataInputStream in) throws IOException {
- throw new InternalError("do not call");
- }
- public void writeTo(DataOutputStream out) throws IOException {
- writeOutputs(out, tag, item);
- }
- public boolean equals(Object x) { return (x instanceof Constant && equals((Constant)x)); }
- public boolean equals(Constant that) {
- return (this.tag == that.tag && this.itemAsComparable().equals(that.itemAsComparable()));
- }
- public int hashCode() { return (tag * 31) + this.itemAsComparable().hashCode(); }
- public Object itemAsComparable() {
- switch (tag) {
- case CONSTANT_Double: return Double.longBitsToDouble((Long)item);
- case CONSTANT_Float: return Float.intBitsToFloat((Integer)item);
- }
- return (item instanceof Object[] ? Arrays.asList((Object[])item) : item);
- }
- public String toString() {
- String itstr = String.valueOf(itemAsComparable());
- return (index + ":" + tagName(tag) + (itstr.startsWith("[")?"":"=") + itstr);
- }
- private static String[] TAG_NAMES;
- public static String tagName(byte tag) { // used for error messages
- if (TAG_NAMES == null)
- TAG_NAMES = ("None Utf8 Unicode Integer Float Long Double Class String"
- +" Fieldref Methodref InterfaceMethodref NameAndType #13 #14"
- +" MethodHandle MethodType InvokeDynamic#17 InvokeDynamic").split(" ");
- if ((tag & 0xFF) >= TAG_NAMES.length) return "#"+(tag & 0xFF);
- return TAG_NAMES[tag & 0xFF];
- }
- }
-
- public static class Pool extends CountedList<Constant> implements Chunk {
- private Map<String,Short> strings = new TreeMap<>();
-
- public Pool() {
- super(Constant.class);
- }
- public void readFrom(DataInputStream in) throws IOException {
- int count = in.readUnsignedShort();
- add(null); // always ignore first item
- while (size() < count) {
- readConstant(in);
- }
- }
- public <T> Constant<T> addConstant(byte tag, T item) {
- Constant<T> con = new Constant<>(size(), tag, item);
- int idx = indexOf(con);
- if (idx >= 0) return get(idx);
- add(con);
- if (tag == CONSTANT_Utf8) strings.put((String)item, (short) con.index);
- return con;
- }
- private void readConstant(DataInputStream in) throws IOException {
- byte tag = in.readByte();
- int index = size();
- Object arg;
- switch (tag) {
- case CONSTANT_Utf8:
- arg = in.readUTF();
- strings.put((String) arg, (short) size());
- break;
- case CONSTANT_Integer:
- case CONSTANT_Float:
- arg = in.readInt(); break;
- case CONSTANT_Long:
- case CONSTANT_Double:
- add(new Constant(index, tag, in.readLong()));
- add(null);
- return;
- case CONSTANT_Class:
- case CONSTANT_String:
- arg = in.readShort(); break;
- case CONSTANT_Field:
- case CONSTANT_Method:
- case CONSTANT_InterfaceMethod:
- case CONSTANT_NameAndType:
- case CONSTANT_InvokeDynamic_17:
- case CONSTANT_InvokeDynamic:
- // read an ordered pair
- arg = new Short[] { in.readShort(), in.readShort() };
- break;
- case CONSTANT_MethodHandle:
- // read an ordered pair; first part is a u1 (not u2)
- arg = new Object[] { in.readByte(), in.readShort() };
- break;
- case CONSTANT_MethodType:
- arg = in.readShort(); break;
- default:
- throw new InternalError("bad CP tag "+tag);
- }
- add(new Constant(index, tag, arg));
- }
-
- // Access:
- public Constant get(int index) {
- // extra 1-bits get into the shorts
- return super.get((char) index);
- }
- String getString(byte tag, short index) {
- get(index).checkTag(tag);
- return getString(index);
- }
- String getString(short index) {
- Object v = get(index).item;
- if (v instanceof Short)
- v = get((Short)v).checkTag(CONSTANT_Utf8).item;
- return (String) v;
- }
- String[] getStrings(Short[] indexes) {
- String[] res = new String[indexes.length];
- for (int i = 0; i < indexes.length; i++)
- res[i] = getString(indexes[i]);
- return res;
- }
- int stringIndex(String name, boolean createIfNotFound) {
- Short x = strings.get(name);
- if (x != null) return (char)(int) x;
- if (!createIfNotFound) return 0;
- return addConstant(CONSTANT_Utf8, name).index;
- }
- Short[] getMemberRef(short index) {
- Short[] cls_nnt = get(index).itemIndexes();
- Short[] name_type = get(cls_nnt[1]).itemIndexes();
- return new Short[]{ cls_nnt[0], name_type[0], name_type[1] };
- }
- }
-
- public class ClassFile extends Outer implements Chunk {
- ClassFile(File f) throws IOException {
- DataInputStream in = openInput(f);
- try {
- readFrom(in);
- } finally {
- if (in != null) in.close();
- }
- }
-
- public int magic, version; // <min:maj>
- public final Pool pool = new Pool();
- public short access, thisc, superc;
- public final List<Short> interfaces = new CountedList<>(Short.class);
- public final List<Field> fields = new CountedList<>(Field.class);
- public final List<Method> methods = new CountedList<>(Method.class);
- public final List<Attr> attrs = new CountedList<>(Attr.class);
-
- public final void readFrom(DataInputStream in) throws IOException {
- magic = in.readInt(); version = in.readInt();
- if (magic != 0xCAFEBABE) throw new IOException("bad magic number");
- pool.readFrom(in);
- Code_index = pool.stringIndex("Code", false);
- access = in.readShort(); thisc = in.readShort(); superc = in.readShort();
- readInputs(in, interfaces, fields, methods, attrs);
- if (in.read() >= 0) throw new IOException("junk after end of file");
- linkInners();
- }
-
- void writeTo(File f) throws IOException {
- DataOutputStream out = openOutput(f);
- try {
- writeTo(out);
- } finally {
- out.close();
- }
- }
-
- public void writeTo(DataOutputStream out) throws IOException {
- writeOutputs(out, magic, version, pool,
- access, thisc, superc, interfaces,
- fields, methods, attrs);
- }
-
- public byte[] toByteArray() {
- try {
- ByteArrayOutputStream buf = new ByteArrayOutputStream();
- writeTo(new DataOutputStream(buf));
- return buf.toByteArray();
- } catch (IOException ex) {
- throw new InternalError();
- }
- }
-
- public List<Inner> inners() {
- List<Inner> inns = new ArrayList<>();
- inns.addAll(fields); inns.addAll(methods); inns.addAll(attrs);
- return inns;
- }
- public List<Attr> attrs() { return attrs; }
-
- // derived stuff:
- public String nameString() { return pool.getString(CONSTANT_Class, thisc); }
- int Code_index;
- }
-
- private static <T extends Member> T findMember(List<T> mems, int name, int type) {
- if (name == 0 || type == 0) return null;
- for (T m : mems) {
- if (m.name == name && m.type == type) return m;
- }
- return null;
- }
-
- public static class Member extends InnerOuter implements Chunk {
- public short access, name, type;
- public final List<Attr> attrs = new CountedList<>(Attr.class);
- public void readFrom(DataInputStream in) throws IOException {
- access = in.readShort(); name = in.readShort(); type = in.readShort();
- readInputs(in, attrs);
- }
- public void writeTo(DataOutputStream out) throws IOException {
- writeOutputs(out, access, name, type, attrs);
- }
- public List<Attr> inners() { return attrs; }
- public List<Attr> attrs() { return attrs; }
- public ClassFile outer() { return (ClassFile) outer; }
- public String nameString() { return outer().pool.getString(CONSTANT_Utf8, name); }
- public String typeString() { return outer().pool.getString(CONSTANT_Utf8, type); }
- public String toString() {
- if (outer == null) return super.toString();
- return nameString() + (this instanceof Method ? "" : ":")
- + simplifyType(typeString());
- }
- }
- public static class Field extends Member {
- }
- public static class Method extends Member {
- public Code code() {
- Attr a = findAttr("Code");
- if (a == null) return null;
- return (Code) a.item;
- }
- public Instruction instructions() {
- Code code = code();
- if (code == null) return null;
- return code.instructions();
- }
- }
-
- public static class Attr extends InnerOuter implements Chunk {
- public short name;
- public int size = -1; // no pre-declared size
- public Object item;
-
- public Attr() {}
- public Attr(Outer outer, String name, Object item) {
- ClassFile cf = outer.outer(ClassFile.class);
- linkOuter(outer);
- this.name = (short) cf.pool.stringIndex(name, true);
- this.item = item;
- outer.attrs().add(this);
- }
- public void readFrom(DataInputStream in) throws IOException {
- name = in.readShort();
- size = in.readInt();
- item = readRawBytes(in, size);
- }
- public void writeTo(DataOutputStream out) throws IOException {
- out.writeShort(name);
- // write the 4-byte size header and then the contents:
- byte[] bytes;
- int trueSize;
- if (item instanceof byte[]) {
- bytes = (byte[]) item;
- out.writeInt(trueSize = bytes.length);
- out.write(bytes);
- } else {
- trueSize = flatten(out);
- //if (!(item instanceof Code)) System.err.println("wrote complex attr name="+(int)(char)name+" size="+trueSize+" data="+Arrays.toString(flatten()));
- }
- if (trueSize != size && size >= 0)
- System.err.println("warning: attribute size changed "+size+" to "+trueSize);
- }
- public void linkOuter(Outer o) {
- super.linkOuter(o);
- if (item instanceof byte[] &&
- outer instanceof Method &&
- ((Method)outer).outer().Code_index == name) {
- item = readInput((byte[])item, Code.class);
- }
- }
- public List<Inner> inners() {
- if (item instanceof Inner)
- return Collections.nCopies(1, (Inner)item);
- return Collections.emptyList();
- }
- public List<Attr> attrs() { return null; } // Code overrides this
- public byte[] flatten() {
- ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
- flatten(buf);
- return buf.toByteArray();
- }
- public int flatten(DataOutputStream out) throws IOException {
- ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
- int trueSize = flatten(buf);
- out.writeInt(trueSize);
- buf.writeTo(out);
- return trueSize;
- }
- private int flatten(ByteArrayOutputStream buf) {
- try {
- writeOutput(new DataOutputStream(buf), item);
- return buf.size();
- } catch (IOException ex) {
- throw new InternalError();
- }
- }
- public String nameString() {
- ClassFile cf = outer(ClassFile.class);
- if (cf == null) return "#"+name;
- return cf.pool.getString(name);
- }
- public String toString() {
- return nameString()+(size < 0 ? "=" : "["+size+"]=")+item;
- }
- }
-
- public static class Code extends InnerOuter implements Chunk {
- public short stacks, locals;
- public byte[] bytes;
- public final List<Short[]> etable = new CountedList<>(Short[].class, 4);
- public final List<Attr> attrs = new CountedList<>(Attr.class);
- // etable[N] = (N)*{ startpc, endpc, handlerpc, catchtype }
- public void readFrom(DataInputStream in) throws IOException {
- stacks = in.readShort(); locals = in.readShort();
- bytes = readRawBytes(in, in.readInt());
- readInputs(in, etable, attrs);
- }
- public void writeTo(DataOutputStream out) throws IOException {
- writeOutputs(out, stacks, locals, bytes.length, bytes, etable, attrs);
- }
- public List<Attr> inners() { return attrs; }
- public List<Attr> attrs() { return attrs; }
- public Instruction instructions() {
- return new Instruction(bytes, 0);
- }
- }
-
- // lots of constants
- private static final byte
- CONSTANT_Utf8 = 1,
- CONSTANT_Integer = 3,
- CONSTANT_Float = 4,
- CONSTANT_Long = 5,
- CONSTANT_Double = 6,
- CONSTANT_Class = 7,
- CONSTANT_String = 8,
- CONSTANT_Field = 9,
- CONSTANT_Method = 10,
- CONSTANT_InterfaceMethod = 11,
- CONSTANT_NameAndType = 12,
- CONSTANT_MethodHandle = 15, // JSR 292
- CONSTANT_MethodType = 16, // JSR 292
- CONSTANT_InvokeDynamic_17 = 17, // JSR 292, only occurs in old class files
- CONSTANT_InvokeDynamic = 18; // JSR 292
- private static final byte
- REF_getField = 1,
- REF_getStatic = 2,
- REF_putField = 3,
- REF_putStatic = 4,
- REF_invokeVirtual = 5,
- REF_invokeStatic = 6,
- REF_invokeSpecial = 7,
- REF_newInvokeSpecial = 8,
- REF_invokeInterface = 9;
-
- private static final int
- opc_nop = 0,
- opc_aconst_null = 1,
- opc_nconst_MIN = 2, // iconst_m1
- opc_nconst_MAX = 15, // dconst_1
- opc_bipush = 16,
- opc_sipush = 17,
- opc_ldc = 18,
- opc_ldc_w = 19,
- opc_ldc2_w = 20,
- opc_aload = 25,
- opc_aload_0 = 42,
- opc_aload_MAX = 45,
- opc_aaload = 50,
- opc_astore = 58,
- opc_astore_0 = 75,
- opc_astore_MAX = 78,
- opc_aastore = 83,
- opc_pop = 87,
- opc_pop2 = 88,
- opc_dup = 89,
- opc_dup_x1 = 90,
- opc_dup_x2 = 91,
- opc_dup2 = 92,
- opc_dup2_x1 = 93,
- opc_dup2_x2 = 94,
- opc_swap = 95,
- opc_tableswitch = 170,
- opc_lookupswitch = 171,
- opc_areturn = 176,
- opc_getstatic = 178,
- opc_putstatic = 179,
- opc_getfield = 180,
- opc_putfield = 181,
- opc_invokevirtual = 182,
- opc_invokespecial = 183,
- opc_invokestatic = 184,
- opc_invokeinterface = 185,
- opc_invokedynamic = 186,
- opc_new = 187,
- opc_anewarray = 189,
- opc_checkcast = 192,
- opc_ifnull = 198,
- opc_ifnonnull = 199,
- opc_wide = 196;
-
- private static final Object[] INSTRUCTION_CONSTANTS = {
- -1, 0, 1, 2, 3, 4, 5, 0L, 1L, 0.0F, 1.0F, 2.0F, 0.0D, 1.0D
- };
-
- private static final String INSTRUCTION_FORMATS =
- "nop$ aconst_null$L iconst_m1$I iconst_0$I iconst_1$I "+
- "iconst_2$I iconst_3$I iconst_4$I iconst_5$I lconst_0$J_ "+
- "lconst_1$J_ fconst_0$F fconst_1$F fconst_2$F dconst_0$D_ "+
- "dconst_1$D_ bipush=bx$I sipush=bxx$I ldc=bk$X ldc_w=bkk$X "+
- "ldc2_w=bkk$X_ iload=bl/wbll$I lload=bl/wbll$J_ fload=bl/wbll$F "+
- "dload=bl/wbll$D_ aload=bl/wbll$L iload_0$I iload_1$I "+
- "iload_2$I iload_3$I lload_0$J_ lload_1$J_ lload_2$J_ "+
- "lload_3$J_ fload_0$F fload_1$F fload_2$F fload_3$F dload_0$D_ "+
- "dload_1$D_ dload_2$D_ dload_3$D_ aload_0$L aload_1$L "+
- "aload_2$L aload_3$L iaload$LI$I laload$LI$J_ faload$LI$F "+
- "daload$LI$D_ aaload$LI$L baload$LI$I caload$LI$I saload$LI$I "+
- "istore=bl/wbll$I$ lstore=bl/wbll$J_$ fstore=bl/wbll$F$ "+
- "dstore=bl/wbll$D_$ astore=bl/wbll$L$ istore_0$I$ istore_1$I$ "+
- "istore_2$I$ istore_3$I$ lstore_0$J_$ lstore_1$J_$ "+
- "lstore_2$J_$ lstore_3$J_$ fstore_0$F$ fstore_1$F$ fstore_2$F$ "+
- "fstore_3$F$ dstore_0$D_$ dstore_1$D_$ dstore_2$D_$ "+
- "dstore_3$D_$ astore_0$L$ astore_1$L$ astore_2$L$ astore_3$L$ "+
- "iastore$LII$ lastore$LIJ_$ fastore$LIF$ dastore$LID_$ "+
- "aastore$LIL$ bastore$LII$ castore$LII$ sastore$LII$ pop$X$ "+
- "pop2$XX$ dup$X$XX dup_x1$XX$XXX dup_x2$XXX$XXXX dup2$XX$XXXX "+
- "dup2_x1$XXX$XXXXX dup2_x2$XXXX$XXXXXX swap$XX$XX "+
- "iadd$II$I ladd$J_J_$J_ fadd$FF$F dadd$D_D_$D_ isub$II$I "+
- "lsub$J_J_$J_ fsub$FF$F dsub$D_D_$D_ imul$II$I lmul$J_J_$J_ "+
- "fmul$FF$F dmul$D_D_$D_ idiv$II$I ldiv$J_J_$J_ fdiv$FF$F "+
- "ddiv$D_D_$D_ irem$II$I lrem$J_J_$J_ frem$FF$F drem$D_D_$D_ "+
- "ineg$I$I lneg$J_$J_ fneg$F$F dneg$D_$D_ ishl$II$I lshl$J_I$J_ "+
- "ishr$II$I lshr$J_I$J_ iushr$II$I lushr$J_I$J_ iand$II$I "+
- "land$J_J_$J_ ior$II$I lor$J_J_$J_ ixor$II$I lxor$J_J_$J_ "+
- "iinc=blx/wbllxx$ i2l$I$J_ i2f$I$F i2d$I$D_ l2i$J_$I l2f$J_$F "+
- "l2d$J_$D_ f2i$F$I f2l$F$J_ f2d$F$D_ d2i$D_$I d2l$D_$J_ "+
- "d2f$D_$F i2b$I$I i2c$I$I i2s$I$I lcmp fcmpl fcmpg dcmpl dcmpg "+
- "ifeq=boo ifne=boo iflt=boo ifge=boo ifgt=boo ifle=boo "+
- "if_icmpeq=boo if_icmpne=boo if_icmplt=boo if_icmpge=boo "+
- "if_icmpgt=boo if_icmple=boo if_acmpeq=boo if_acmpne=boo "+
- "goto=boo jsr=boo ret=bl/wbll tableswitch=* lookupswitch=* "+
- "ireturn lreturn freturn dreturn areturn return "+
- "getstatic=bkf$Q putstatic=bkf$Q$ getfield=bkf$L$Q "+
- "putfield=bkf$LQ$ invokevirtual=bkm$LQ$Q "+
- "invokespecial=bkm$LQ$Q invokestatic=bkm$Q$Q "+
- "invokeinterface=bkixx$LQ$Q invokedynamic=bkd__$Q$Q new=bkc$L "+
- "newarray=bx$I$L anewarray=bkc$I$L arraylength$L$I athrow "+
- "checkcast=bkc$L$L instanceof=bkc$L$I monitorenter$L "+
- "monitorexit$L wide=* multianewarray=bkcx ifnull=boo "+
- "ifnonnull=boo goto_w=boooo jsr_w=boooo ";
- private static final String[] INSTRUCTION_NAMES;
- private static final String[] INSTRUCTION_POPS;
- private static final int[] INSTRUCTION_INFO;
- static {
- String[] insns = INSTRUCTION_FORMATS.split(" ");
- assert(insns[opc_lookupswitch].startsWith("lookupswitch"));
- assert(insns[opc_tableswitch].startsWith("tableswitch"));
- assert(insns[opc_wide].startsWith("wide"));
- assert(insns[opc_invokedynamic].startsWith("invokedynamic"));
- int[] info = new int[256];
- String[] names = new String[256];
- String[] pops = new String[256];
- for (int i = 0; i < insns.length; i++) {
- String insn = insns[i];
- int dl = insn.indexOf('$');
- if (dl > 0) {
- String p = insn.substring(dl+1);
- if (p.indexOf('$') < 0) p = "$" + p;
- pops[i] = p;
- insn = insn.substring(0, dl);
- }
- int eq = insn.indexOf('=');
- if (eq < 0) {
- info[i] = 1;
- names[i] = insn;
- continue;
- }
- names[i] = insn.substring(0, eq);
- String fmt = insn.substring(eq+1);
- if (fmt.equals("*")) {
- info[i] = 0;
- continue;
- }
- int sl = fmt.indexOf('/');
- if (sl < 0) {
- info[i] = (char) fmt.length();
- } else {
- String wfmt = fmt.substring(sl+1);
- fmt = fmt.substring(0, sl);
- info[i] = (char)( fmt.length() + (wfmt.length() * 16) );
- }
- }
- INSTRUCTION_INFO = info;
- INSTRUCTION_NAMES = names;
- INSTRUCTION_POPS = pops;
- }
-
- public static class Instruction implements Cloneable {
- byte[] codeBase;
- int pc;
- int bc;
- int info;
- int wide;
- int len;
- Instruction(byte[] codeBase, int pc) {
- this.codeBase = codeBase;
- init(pc);
- }
- public Instruction clone() {
- try {
- return (Instruction) super.clone();
- } catch (CloneNotSupportedException ex) {
- throw new InternalError();
- }
- }
- private Instruction init(int pc) {
- this.pc = pc;
- this.bc = codeBase[pc] & 0xFF;
- this.info = INSTRUCTION_INFO[bc];
- this.wide = 0;
- this.len = (info & 0x0F);
- if (len == 0)
- computeLength();
- return this;
- }
- Instruction next() {
- if (len == 0 && bc != 0) throw new InternalError();
- int npc = pc + len;
- if (npc == codeBase.length)
- return null;
- return init(npc);
- }
- void forceNext(int newLen) {
- bc = opc_nop;
- len = newLen;
- }
-
- public String toString() {
- StringBuilder buf = new StringBuilder();
- buf.append(pc).append(":").append(INSTRUCTION_NAMES[bc]);
- switch (len) {
- case 3: buf.append(" ").append(u2At(1)); break;
- case 5: buf.append(" ").append(u2At(1)).append(" ").append(u2At(3)); break;
- default: for (int i = 1; i < len; i++) buf.append(" ").append(u1At(1));
- }
- return buf.toString();
- }
-
- // these are the hard parts
- private void computeLength() {
- int cases;
- switch (bc) {
- case opc_wide:
- bc = codeBase[pc + 1];
- info = INSTRUCTION_INFO[bc];
- len = ((info >> 4) & 0x0F);
- if (len == 0) throw new RuntimeException("misplaced wide bytecode: "+bc);
- return;
-
- case opc_tableswitch:
- cases = (u4At(alignedIntOffset(2)) - u4At(alignedIntOffset(1)) + 1);
- len = alignedIntOffset(3 + cases*1);
- return;
-
- case opc_lookupswitch:
- cases = u4At(alignedIntOffset(1));
- len = alignedIntOffset(2 + cases*2);
- return;
-
- default:
- throw new RuntimeException("unknown bytecode: "+bc);
- }
- }
- // switch code
- // clget the Nth int (where 0 is the first after the opcode itself)
- public int alignedIntOffset(int n) {
- int pos = pc + 1;
- pos += ((-pos) & 0x03); // align it
- pos += (n * 4);
- return pos - pc;
- }
- public int u1At(int pos) {
- return (codeBase[pc+pos] & 0xFF);
- }
- public int u2At(int pos) {
- return (u1At(pos+0)<<8) + u1At(pos+1);
- }
- public int u4At(int pos) {
- return (u2At(pos+0)<<16) + u2At(pos+2);
- }
- public void u1AtPut(int pos, int x) {
- codeBase[pc+pos] = (byte)x;
- }
- public void u2AtPut(int pos, int x) {
- codeBase[pc+pos+0] = (byte)(x >> 8);
- codeBase[pc+pos+1] = (byte)(x >> 0);
- }
- }
-
- static String simplifyType(String type) {
- String simpleType = OBJ_SIGNATURE.matcher(type).replaceAll("L");
- assert(simpleType.matches("^\\([A-Z]*\\)[A-Z]$"));
- // change (DD)D to (D_D_)D_
- simpleType = WIDE_SIGNATURE.matcher(simpleType).replaceAll("\\0_");
- return simpleType;
- }
- static int argsize(String type) {
- return simplifyType(type).length()-3;
- }
- private static final Pattern OBJ_SIGNATURE = Pattern.compile("\\[*L[^;]*;|\\[+[A-Z]");
- private static final Pattern WIDE_SIGNATURE = Pattern.compile("[JD]");
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/6987555/Test6987555.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6987555
+ * @summary JSR 292 unboxing to a boolean value fails on big-endian SPARC
+ *
+ * @run main/othervm -Xint -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6987555
+ */
+
+import java.lang.invoke.*;
+
+public class Test6987555 {
+ private static final Class CLASS = Test6987555.class;
+ private static final String NAME = "foo";
+ private static final boolean DEBUG = false;
+
+ public static void main(String[] args) throws Throwable {
+ testboolean();
+ testbyte();
+ testchar();
+ testshort();
+ testint();
+ }
+
+ // boolean
+ static void testboolean() throws Throwable {
+ doboolean(false);
+ doboolean(true);
+ }
+ static void doboolean(boolean x) throws Throwable {
+ if (DEBUG) System.out.println("boolean=" + x);
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(boolean.class, boolean.class));
+ MethodHandle mh2 = mh1.asType(MethodType.methodType(boolean.class, Boolean.class));
+ boolean a = (boolean) mh1.invokeExact(x);
+ boolean b = (boolean) mh2.invokeExact(Boolean.valueOf(x));
+ assert a == b : a + " != " + b;
+ }
+
+ // byte
+ static void testbyte() throws Throwable {
+ byte[] a = new byte[] {
+ Byte.MIN_VALUE,
+ Byte.MIN_VALUE + 1,
+ -0x0F,
+ -1,
+ 0,
+ 1,
+ 0x0F,
+ Byte.MAX_VALUE - 1,
+ Byte.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ dobyte(a[i]);
+ }
+ }
+ static void dobyte(byte x) throws Throwable {
+ if (DEBUG) System.out.println("byte=" + x);
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(byte.class, byte.class));
+ MethodHandle mh2 = mh1.asType(MethodType.methodType(byte.class, Byte.class));
+ byte a = (byte) mh1.invokeExact(x);
+ byte b = (byte) mh2.invokeExact(Byte.valueOf(x));
+ assert a == b : a + " != " + b;
+ }
+
+ // char
+ static void testchar() throws Throwable {
+ char[] a = new char[] {
+ Character.MIN_VALUE,
+ Character.MIN_VALUE + 1,
+ 0x000F,
+ 0x00FF,
+ 0x0FFF,
+ Character.MAX_VALUE - 1,
+ Character.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ dochar(a[i]);
+ }
+ }
+ static void dochar(char x) throws Throwable {
+ if (DEBUG) System.out.println("char=" + x);
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(char.class, char.class));
+ MethodHandle mh2 = mh1.asType(MethodType.methodType(char.class, Character.class));
+ char a = (char) mh1.invokeExact(x);
+ char b = (char) mh2.invokeExact(Character.valueOf(x));
+ assert a == b : a + " != " + b;
+ }
+
+ // short
+ static void testshort() throws Throwable {
+ short[] a = new short[] {
+ Short.MIN_VALUE,
+ Short.MIN_VALUE + 1,
+ -0x0FFF,
+ -0x00FF,
+ -0x000F,
+ -1,
+ 0,
+ 1,
+ 0x000F,
+ 0x00FF,
+ 0x0FFF,
+ Short.MAX_VALUE - 1,
+ Short.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ doshort(a[i]);
+ }
+ }
+ static void doshort(short x) throws Throwable {
+ if (DEBUG) System.out.println("short=" + x);
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(short.class, short.class));
+ MethodHandle mh2 = mh1.asType(MethodType.methodType(short.class, Short.class));
+ short a = (short) mh1.invokeExact(x);
+ short b = (short) mh2.invokeExact(Short.valueOf(x));
+ assert a == b : a + " != " + b;
+ }
+
+ // int
+ static void testint() throws Throwable {
+ int[] a = new int[] {
+ Integer.MIN_VALUE,
+ Integer.MIN_VALUE + 1,
+ -0x00000FFF,
+ -0x000000FF,
+ -0x0000000F,
+ -1,
+ 0,
+ 1,
+ 0x0000000F,
+ 0x000000FF,
+ 0x00000FFF,
+ Integer.MAX_VALUE - 1,
+ Integer.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ doint(a[i]);
+ }
+ }
+ static void doint(int x) throws Throwable {
+ if (DEBUG) System.out.println("int=" + x);
+ MethodHandle mh1 = MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(int.class, int.class));
+ MethodHandle mh2 = mh1.asType(MethodType.methodType(int.class, Integer.class));
+ int a = (int) mh1.invokeExact(x);
+ int b = (int) mh2.invokeExact(Integer.valueOf(x));
+ assert a == b : a + " != " + b;
+ }
+
+ public static boolean foo(boolean i) { return i; }
+ public static byte foo(byte i) { return i; }
+ public static char foo(char i) { return i; }
+ public static short foo(short i) { return i; }
+ public static int foo(int i) { return i; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/6991596/Test6991596.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6991596
+ * @summary JSR 292 unimplemented adapter_opt_i2i and adapter_opt_l2i on SPARC
+ *
+ * @run main/othervm -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6991596
+ */
+
+import java.lang.invoke.*;
+
+public class Test6991596 {
+ private static final Class CLASS = Test6991596.class;
+ private static final String NAME = "foo";
+ private static final boolean DEBUG = System.getProperty("DEBUG", "false").equals("true");
+
+ public static void main(String[] args) throws Throwable {
+ testboolean();
+ testbyte();
+ testchar();
+ testshort();
+ testint();
+ testlong();
+ }
+
+ // Helpers to get various methods.
+ static MethodHandle getmh1(Class ret, Class arg) throws ReflectiveOperationException {
+ return MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(ret, arg));
+ }
+ static MethodHandle getmh2(MethodHandle mh1, Class ret, Class arg) {
+ return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
+ }
+ static MethodHandle getmh3(MethodHandle mh1, Class ret, Class arg) {
+ return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
+ }
+
+ // test adapter_opt_i2i
+ static void testboolean() throws Throwable {
+ boolean[] a = new boolean[] {
+ true,
+ false
+ };
+ for (int i = 0; i < a.length; i++) {
+ doboolean(a[i]);
+ }
+ }
+ static void doboolean(boolean x) throws Throwable {
+ if (DEBUG) System.out.println("boolean=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, boolean.class);
+ // TODO add this for all cases when the bugs are fixed.
+ //MethodHandle mh3 = getmh3(mh1, boolean.class, boolean.class);
+ boolean a = (boolean) mh1.invokeExact((boolean) x);
+ boolean b = (boolean) mh2.invokeExact(x);
+ //boolean c = mh3.<boolean>invokeExact((boolean) x);
+ check(x, a, b);
+ //check(x, c, x);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class );
+ MethodHandle mh2 = getmh2(mh1, byte.class, boolean.class);
+ byte a = (byte) mh1.invokeExact((byte) (x ? 1 : 0));
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, boolean.class);
+ char a = (char) mh1.invokeExact((char) (x ? 1 : 0));
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, boolean.class);
+ short a = (short) mh1.invokeExact((short) (x ? 1 : 0));
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ static void testbyte() throws Throwable {
+ byte[] a = new byte[] {
+ Byte.MIN_VALUE,
+ Byte.MIN_VALUE + 1,
+ -0x0F,
+ -1,
+ 0,
+ 1,
+ 0x0F,
+ Byte.MAX_VALUE - 1,
+ Byte.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ dobyte(a[i]);
+ }
+ }
+ static void dobyte(byte x) throws Throwable {
+ if (DEBUG) System.out.println("byte=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, byte.class);
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class);
+ MethodHandle mh2 = getmh2(mh1, byte.class, byte.class);
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, byte.class);
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, byte.class);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ static void testchar() throws Throwable {
+ char[] a = new char[] {
+ Character.MIN_VALUE,
+ Character.MIN_VALUE + 1,
+ 0x000F,
+ 0x00FF,
+ 0x0FFF,
+ Character.MAX_VALUE - 1,
+ Character.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ dochar(a[i]);
+ }
+ }
+ static void dochar(char x) throws Throwable {
+ if (DEBUG) System.out.println("char=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, char.class);
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class);
+ MethodHandle mh2 = getmh2(mh1, byte.class, char.class);
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, char.class);
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, char.class);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ static void testshort() throws Throwable {
+ short[] a = new short[] {
+ Short.MIN_VALUE,
+ Short.MIN_VALUE + 1,
+ -0x0FFF,
+ -0x00FF,
+ -0x000F,
+ -1,
+ 0,
+ 1,
+ 0x000F,
+ 0x00FF,
+ 0x0FFF,
+ Short.MAX_VALUE - 1,
+ Short.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ doshort(a[i]);
+ }
+ }
+ static void doshort(short x) throws Throwable {
+ if (DEBUG) System.out.println("short=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, short.class);
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class);
+ MethodHandle mh2 = getmh2(mh1, byte.class, short.class);
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, short.class);
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, short.class);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ static void testint() throws Throwable {
+ int[] a = new int[] {
+ Integer.MIN_VALUE,
+ Integer.MIN_VALUE + 1,
+ -0x0FFFFFFF,
+ -0x00FFFFFF,
+ -0x000FFFFF,
+ -0x0000FFFF,
+ -0x00000FFF,
+ -0x000000FF,
+ -0x0000000F,
+ -1,
+ 0,
+ 1,
+ 0x0000000F,
+ 0x000000FF,
+ 0x00000FFF,
+ 0x0000FFFF,
+ 0x000FFFFF,
+ 0x00FFFFFF,
+ 0x0FFFFFFF,
+ Integer.MAX_VALUE - 1,
+ Integer.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ doint(a[i]);
+ }
+ }
+ static void doint(int x) throws Throwable {
+ if (DEBUG) System.out.println("int=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, int.class);
+ boolean a = (boolean) mh1.invokeExact((x & 1) == 1);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class);
+ MethodHandle mh2 = getmh2(mh1, byte.class, int.class);
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, int.class);
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, int.class);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ assert a == b : a + " != " + b;
+ check(x, a, b);
+ }
+
+ // int
+ {
+ MethodHandle mh1 = getmh1( int.class, int.class);
+ MethodHandle mh2 = getmh2(mh1, int.class, int.class);
+ int a = (int) mh1.invokeExact((int) x);
+ int b = (int) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ // test adapter_opt_l2i
+ static void testlong() throws Throwable {
+ long[] a = new long[] {
+ Long.MIN_VALUE,
+ Long.MIN_VALUE + 1,
+ -0x000000000FFFFFFFL,
+ -0x0000000000FFFFFFL,
+ -0x00000000000FFFFFL,
+ -0x000000000000FFFFL,
+ -0x0000000000000FFFL,
+ -0x00000000000000FFL,
+ -0x000000000000000FL,
+ -1L,
+ 0L,
+ 1L,
+ 0x000000000000000FL,
+ 0x00000000000000FFL,
+ 0x0000000000000FFFL,
+ 0x0000000000000FFFL,
+ 0x000000000000FFFFL,
+ 0x00000000000FFFFFL,
+ 0x0000000000FFFFFFL,
+ 0x000000000FFFFFFFL,
+ Long.MAX_VALUE - 1,
+ Long.MAX_VALUE
+ };
+ for (int i = 0; i < a.length; i++) {
+ dolong(a[i]);
+ }
+ }
+ static void dolong(long x) throws Throwable {
+ if (DEBUG) System.out.println("long=" + x);
+
+ // boolean
+ {
+ MethodHandle mh1 = getmh1( boolean.class, boolean.class);
+ MethodHandle mh2 = getmh2(mh1, boolean.class, long.class);
+ boolean a = (boolean) mh1.invokeExact((x & 1L) == 1L);
+ boolean b = (boolean) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // byte
+ {
+ MethodHandle mh1 = getmh1( byte.class, byte.class);
+ MethodHandle mh2 = getmh2(mh1, byte.class, long.class);
+ byte a = (byte) mh1.invokeExact((byte) x);
+ byte b = (byte) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // char
+ {
+ MethodHandle mh1 = getmh1( char.class, char.class);
+ MethodHandle mh2 = getmh2(mh1, char.class, long.class);
+ char a = (char) mh1.invokeExact((char) x);
+ char b = (char) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // short
+ {
+ MethodHandle mh1 = getmh1( short.class, short.class);
+ MethodHandle mh2 = getmh2(mh1, short.class, long.class);
+ short a = (short) mh1.invokeExact((short) x);
+ short b = (short) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+
+ // int
+ {
+ MethodHandle mh1 = getmh1( int.class, int.class);
+ MethodHandle mh2 = getmh2(mh1, int.class, long.class);
+ int a = (int) mh1.invokeExact((int) x);
+ int b = (int) mh2.invokeExact(x);
+ check(x, a, b);
+ }
+ }
+
+ static void check(boolean x, boolean e, boolean a) { p(z2h(x), z2h(e), z2h(a)); assert e == a : z2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+ static void check(boolean x, byte e, byte a) { p(z2h(x), i2h(e), i2h(a)); assert e == a : z2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+ static void check(boolean x, int e, int a) { p(z2h(x), i2h(e), i2h(a)); assert e == a : z2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+ static void check(int x, boolean e, boolean a) { p(i2h(x), z2h(e), z2h(a)); assert e == a : i2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+ static void check(int x, byte e, byte a) { p(i2h(x), i2h(e), i2h(a)); assert e == a : i2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+ static void check(int x, int e, int a) { p(i2h(x), i2h(e), i2h(a)); assert e == a : i2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+ static void check(long x, boolean e, boolean a) { p(l2h(x), z2h(e), z2h(a)); assert e == a : l2h(x) + ": " + z2h(e) + " != " + z2h(a); }
+ static void check(long x, byte e, byte a) { p(l2h(x), i2h(e), i2h(a)); assert e == a : l2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+ static void check(long x, int e, int a) { p(l2h(x), i2h(e), i2h(a)); assert e == a : l2h(x) + ": " + i2h(e) + " != " + i2h(a); }
+
+ static void p(String x, String e, String a) { if (DEBUG) System.out.println(x + ": expected: " + e + ", actual: " + a); }
+
+ static String z2h(boolean x) { return x ? "1" : "0"; }
+ static String i2h(int x) { return Integer.toHexString(x); }
+ static String l2h(long x) { return Long.toHexString(x); }
+
+ // to int
+ public static boolean foo(boolean i) { return i; }
+ public static byte foo(byte i) { return i; }
+ public static char foo(char i) { return i; }
+ public static short foo(short i) { return i; }
+ public static int foo(int i) { return i; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/ClassValueTest.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary tests for class-specific values
+ * @compile ClassValueTest.java
+ * @run junit/othervm test.java.lang.invoke.ClassValueTest
+ */
+
+/*
+ Manually:
+ $ $JAVA7X_HOME/bin/javac -d foo -cp $JUNIT4_JAR test/java/lang/invoke/ClassValueTest.java
+ $ $JAVA7X_HOME/bin/java -cp foo:$JUNIT4_JAR org.junit.runner.JUnitCore test.java.lang.invoke.ClassValueTest
+ Output: .testAdd => 1000 : Integer
+ */
+
+package test.java.lang.invoke;
+
+import java.util.*;
+
+import java.lang.invoke.*;
+
+import org.junit.*;
+import static org.junit.Assert.*;
+
+/**
+ * @author jrose
+ */
+public class ClassValueTest {
+ static String nameForCV1(Class<?> type) {
+ return "CV1:" + type.getName();
+ }
+ static int countForCV1;
+ static final ClassValue<String> CV1 = new CV1();
+ private static class CV1 extends ClassValue<String> {
+ protected String computeValue(Class<?> type) {
+ countForCV1++;
+ return nameForCV1(type);
+ }
+ }
+
+ static final Class[] CLASSES = {
+ String.class,
+ Integer.class,
+ int.class,
+ boolean[].class,
+ char[][].class,
+ ClassValueTest.class
+ };
+
+ @Test
+ public void testGet() {
+ countForCV1 = 0;
+ for (Class c : CLASSES) {
+ assertEquals(nameForCV1(c), CV1.get(c));
+ }
+ assertEquals(CLASSES.length, countForCV1);
+ for (Class c : CLASSES) {
+ assertEquals(nameForCV1(c), CV1.get(c));
+ }
+ assertEquals(CLASSES.length, countForCV1);
+ }
+
+ @Test
+ public void testRemove() {
+ for (Class c : CLASSES) {
+ CV1.get(c);
+ }
+ countForCV1 = 0;
+ int REMCOUNT = 3;
+ for (int i = 0; i < REMCOUNT; i++) {
+ CV1.remove(CLASSES[i]);
+ }
+ assertEquals(0, countForCV1); // no change
+ for (Class c : CLASSES) {
+ assertEquals(nameForCV1(c), CV1.get(c));
+ }
+ assertEquals(REMCOUNT, countForCV1);
+ }
+
+ static String nameForCVN(Class<?> type, int n) {
+ return "CV[" + n + "]" + type.getName();
+ }
+ static int countForCVN;
+ static class CVN extends ClassValue<String> {
+ final int n;
+ CVN(int n) { this.n = n; }
+ protected String computeValue(Class<?> type) {
+ countForCVN++;
+ return nameForCVN(type, n);
+ }
+ };
+
+ @Test
+ public void testGetMany() {
+ int CVN_COUNT1 = 100, CVN_COUNT2 = 100;
+ CVN cvns[] = new CVN[CVN_COUNT1 * CVN_COUNT2];
+ for (int n = 0; n < cvns.length; n++) {
+ cvns[n] = new CVN(n);
+ }
+ countForCVN = 0;
+ for (int pass = 0; pass <= 2; pass++) {
+ for (int i1 = 0; i1 < CVN_COUNT1; i1++) {
+ eachClass:
+ for (Class c : CLASSES) {
+ for (int i2 = 0; i2 < CVN_COUNT2; i2++) {
+ int n = i1*CVN_COUNT2 + i2;
+ assertEquals(0, countForCVN);
+ assertEquals(nameForCVN(c, n), cvns[n].get(c));
+ cvns[n].get(c); //get it again
+ //System.out.println("getting "+n+":"+cvns[n].get(c));
+ boolean doremove = (((i1 + i2) & 3) == 0);
+ switch (pass) {
+ case 0:
+ assertEquals(1, countForCVN);
+ break;
+ case 1:
+ // remove on middle pass
+ assertEquals(0, countForCVN);
+ if (doremove) {
+ //System.out.println("removing "+n+":"+cvns[n].get(c));
+ cvns[n].remove(c);
+ assertEquals(0, countForCVN);
+ }
+ break;
+ case 2:
+ assertEquals(doremove ? 1 : 0, countForCVN);
+ break;
+ }
+ countForCVN = 0;
+ if (i1 > i2 && i1 < i2+5) continue eachClass; // leave diagonal gap
+ }
+ }
+ }
+ }
+ assertEquals(countForCVN, 0);
+ for (int n = 0; n < cvns.length; n++) {
+ for (Class c : CLASSES) {
+ assertEquals(nameForCVN(c, n), cvns[n].get(c));
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/InvokeDynamicPrintArgs.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary smoke test for invokedynamic instructions
+ * @build indify.Indify
+ * @compile InvokeDynamicPrintArgs.java
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic
+ * indify.Indify
+ * --verify-specifier-count=3 --transitionalJSR292=false
+ * --expand-properties --classpath ${test.classes}
+ * --java test.java.lang.invoke.InvokeDynamicPrintArgs --check-output
+ */
+
+package test.java.lang.invoke;
+
+import org.junit.Test;
+
+import java.util.*;
+import java.io.*;
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+public class InvokeDynamicPrintArgs {
+ public static void main(String... av) throws Throwable {
+ if (av.length > 0) openBuf(); // --check-output mode
+ System.out.println("Printing some argument lists, starting with a empty one:");
+ INDY_nothing().invokeExact(); // BSM specifier #0 = {bsm}
+ INDY_bar().invokeExact("bar arg", 1); // BSM specifier #1 = {bsm2, Void.class, "void type"}
+ INDY_bar2().invokeExact("bar2 arg", 222); // BSM specifier #1 = (same)
+ INDY_baz().invokeExact("baz arg", 2, 3.14); // BSM specifier #2 = {bsm2, 1234.5}
+ INDY_foo().invokeExact("foo arg"); // BSM specifier #0 = (same)
+ // Hence, BSM specifier count should be 3. See "--verify-specifier-count=3" above.
+ System.out.println("Done printing argument lists.");
+ closeBuf();
+ }
+
+ @Test
+ public void testInvokeDynamicPrintArgs() throws IOException {
+ System.err.println(System.getProperties());
+ String testClassPath = System.getProperty("build.test.classes.dir");
+ if (testClassPath == null) throw new RuntimeException();
+ String[] args = new String[]{
+ "--verify-specifier-count=3", "--transitionalJSR292=false",
+ "--expand-properties", "--classpath", testClassPath,
+ "--java", "test.java.lang.invoke.InvokeDynamicPrintArgs", "--check-output"
+ };
+ System.err.println("Indify: "+Arrays.toString(args));
+ indify.Indify.main(args);
+ }
+
+ private static PrintStream oldOut;
+ private static ByteArrayOutputStream buf;
+ private static void openBuf() {
+ oldOut = System.out;
+ buf = new ByteArrayOutputStream();
+ System.setOut(new PrintStream(buf));
+ }
+ private static void closeBuf() {
+ if (buf == null) return;
+ System.out.flush();
+ System.setOut(oldOut);
+ String[] haveLines = new String(buf.toByteArray()).split("[\n\r]+");
+ for (String line : haveLines) System.out.println(line);
+ Iterator<String> iter = Arrays.asList(haveLines).iterator();
+ for (String want : EXPECT_OUTPUT) {
+ String have = iter.hasNext() ? iter.next() : "[EOF]";
+ if (want.equals(have)) continue;
+ System.err.println("want line: "+want);
+ System.err.println("have line: "+have);
+ throw new AssertionError("unexpected output: "+have);
+ }
+ if (iter.hasNext())
+ throw new AssertionError("unexpected output: "+iter.next());
+ }
+ private static final String[] EXPECT_OUTPUT = {
+ "Printing some argument lists, starting with a empty one:",
+ "[test.java.lang.invoke.InvokeDynamicPrintArgs, nothing, ()void][]",
+ "[test.java.lang.invoke.InvokeDynamicPrintArgs, bar, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar arg, 1]",
+ "[test.java.lang.invoke.InvokeDynamicPrintArgs, bar2, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar2 arg, 222]",
+ "[test.java.lang.invoke.InvokeDynamicPrintArgs, baz, (String,int,double)void, 1234.5][baz arg, 2, 3.14]",
+ "[test.java.lang.invoke.InvokeDynamicPrintArgs, foo, (String)void][foo arg]",
+ "Done printing argument lists."
+ };
+
+ private static void printArgs(Object bsmInfo, Object... args) {
+ System.out.println(bsmInfo+Arrays.deepToString(args));
+ }
+ private static MethodHandle MH_printArgs() throws ReflectiveOperationException {
+ shouldNotCallThis();
+ return lookup().findStatic(lookup().lookupClass(),
+ "printArgs", methodType(void.class, Object.class, Object[].class));
+ }
+
+ private static CallSite bsm(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
+ // ignore caller and name, but match the type:
+ Object bsmInfo = Arrays.asList(caller, name, type);
+ return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
+ }
+ private static MethodType MT_bsm() {
+ shouldNotCallThis();
+ return methodType(CallSite.class, Lookup.class, String.class, MethodType.class);
+ }
+ private static MethodHandle MH_bsm() throws ReflectiveOperationException {
+ shouldNotCallThis();
+ return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());
+ }
+
+ private static CallSite bsm2(Lookup caller, String name, MethodType type, Object... arg) throws ReflectiveOperationException {
+ // ignore caller and name, but match the type:
+ List<Object> bsmInfo = new ArrayList<>(Arrays.asList(caller, name, type));
+ bsmInfo.addAll(Arrays.asList((Object[])arg));
+ return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
+ }
+ private static MethodType MT_bsm2() {
+ shouldNotCallThis();
+ return methodType(CallSite.class, Lookup.class, String.class, MethodType.class, Object[].class);
+ }
+ private static MethodHandle MH_bsm2() throws ReflectiveOperationException {
+ shouldNotCallThis();
+ return lookup().findStatic(lookup().lookupClass(), "bsm2", MT_bsm2());
+ }
+
+ private static MethodHandle INDY_nothing() throws Throwable {
+ shouldNotCallThis();
+ return ((CallSite) MH_bsm().invokeGeneric(lookup(),
+ "nothing", methodType(void.class)
+ )).dynamicInvoker();
+ }
+ private static MethodHandle INDY_foo() throws Throwable {
+ shouldNotCallThis();
+ return ((CallSite) MH_bsm().invokeGeneric(lookup(),
+ "foo", methodType(void.class, String.class)
+ )).dynamicInvoker();
+ }
+ private static MethodHandle INDY_bar() throws Throwable {
+ shouldNotCallThis();
+ return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
+ "bar", methodType(void.class, String.class, int.class)
+ , new Object[] { Void.class, "void type!",
+ 1, 234.5F, 67.5, (long)89 }
+ )).dynamicInvoker();
+ }
+ private static MethodHandle INDY_bar2() throws Throwable {
+ shouldNotCallThis();
+ return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
+ "bar2", methodType(void.class, String.class, int.class)
+ , new Object[] { Void.class, "void type!",
+ 1, 234.5F, 67.5, (long)89 }
+ )).dynamicInvoker();
+ }
+ private static MethodHandle INDY_baz() throws Throwable {
+ shouldNotCallThis();
+ return ((CallSite) MH_bsm2().invokeGeneric(lookup(),
+ "baz", methodType(void.class, String.class, int.class, double.class)
+ , 1234.5
+ )).dynamicInvoker();
+ }
+
+ private static void shouldNotCallThis() {
+ // if this gets called, the transformation has not taken place
+ if (System.getProperty("InvokeDynamicPrintArgs.allow-untransformed") != null) return;
+ throw new AssertionError("this code should be statically transformed away by Indify");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/InvokeGenericTest.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,484 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodHandle.invokeGeneric
+ * @compile -XDallowTransitionalJSR292=no -target 7 InvokeGenericTest.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.InvokeGenericTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+import java.lang.reflect.*;
+import java.util.*;
+import org.junit.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+
+/**
+ *
+ * @author jrose
+ */
+public class InvokeGenericTest {
+ // How much output?
+ static int verbosity = 0;
+ static {
+ String vstr = System.getProperty("test.java.lang.invoke.InvokeGenericTest.verbosity");
+ if (vstr != null) verbosity = Integer.parseInt(vstr);
+ }
+
+ @Test
+ public void testFirst() throws Throwable {
+ verbosity += 9; try {
+ // left blank for debugging
+ } finally { printCounts(); verbosity -= 9; }
+ }
+
+ public InvokeGenericTest() {
+ }
+
+ @Before
+ public void checkImplementedPlatform() {
+ boolean platformOK = false;
+ Properties properties = System.getProperties();
+ String vers = properties.getProperty("java.vm.version");
+ String name = properties.getProperty("java.vm.name");
+ String arch = properties.getProperty("os.arch");
+ if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
+ arch.equals("sparc") || arch.equals("sparcv9")) &&
+ (name.contains("Client") || name.contains("Server"))
+ ) {
+ platformOK = true;
+ } else {
+ System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
+ }
+ assumeTrue(platformOK);
+ }
+
+ String testName;
+ static int allPosTests, allNegTests;
+ int posTests, negTests;
+ @After
+ public void printCounts() {
+ if (verbosity >= 2 && (posTests | negTests) != 0) {
+ System.out.println();
+ if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run");
+ if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run");
+ allPosTests += posTests;
+ allNegTests += negTests;
+ posTests = negTests = 0;
+ }
+ }
+ void countTest(boolean positive) {
+ if (positive) ++posTests;
+ else ++negTests;
+ }
+ void countTest() { countTest(true); }
+ void startTest(String name) {
+ if (testName != null) printCounts();
+ if (verbosity >= 1)
+ System.out.println(name);
+ posTests = negTests = 0;
+ testName = name;
+ }
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ calledLog.clear();
+ calledLog.add(null);
+ nextArgVal = INITIAL_ARG_VAL;
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ int posTests = allPosTests, negTests = allNegTests;
+ if (verbosity >= 2 && (posTests | negTests) != 0) {
+ System.out.println();
+ if (posTests != 0) System.out.println("=== "+posTests+" total positive test cases");
+ if (negTests != 0) System.out.println("=== "+negTests+" total negative test cases");
+ }
+ }
+
+ static List<Object> calledLog = new ArrayList<Object>();
+ static Object logEntry(String name, Object... args) {
+ return Arrays.asList(name, Arrays.asList(args));
+ }
+ static Object called(String name, Object... args) {
+ Object entry = logEntry(name, args);
+ calledLog.add(entry);
+ return entry;
+ }
+ static void assertCalled(String name, Object... args) {
+ Object expected = logEntry(name, args);
+ Object actual = calledLog.get(calledLog.size() - 1);
+ if (expected.equals(actual) && verbosity < 9) return;
+ System.out.println("assertCalled "+name+":");
+ System.out.println("expected: "+expected);
+ System.out.println("actual: "+actual);
+ System.out.println("ex. types: "+getClasses(expected));
+ System.out.println("act. types: "+getClasses(actual));
+ assertEquals("previous method call", expected, actual);
+ }
+ static void printCalled(MethodHandle target, String name, Object... args) {
+ if (verbosity >= 3)
+ System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
+ }
+
+ static Object castToWrapper(Object value, Class<?> dst) {
+ Object wrap = null;
+ if (value instanceof Number)
+ wrap = castToWrapperOrNull(((Number)value).longValue(), dst);
+ if (value instanceof Character)
+ wrap = castToWrapperOrNull((char)(Character)value, dst);
+ if (wrap != null) return wrap;
+ return dst.cast(value);
+ }
+
+ static Object castToWrapperOrNull(long value, Class<?> dst) {
+ if (dst == int.class || dst == Integer.class)
+ return (int)(value);
+ if (dst == long.class || dst == Long.class)
+ return (long)(value);
+ if (dst == char.class || dst == Character.class)
+ return (char)(value);
+ if (dst == short.class || dst == Short.class)
+ return (short)(value);
+ if (dst == float.class || dst == Float.class)
+ return (float)(value);
+ if (dst == double.class || dst == Double.class)
+ return (double)(value);
+ if (dst == byte.class || dst == Byte.class)
+ return (byte)(value);
+ if (dst == boolean.class || dst == boolean.class)
+ return ((value % 29) & 1) == 0;
+ return null;
+ }
+
+ static final int ONE_MILLION = (1000*1000), // first int value
+ TEN_BILLION = (10*1000*1000*1000), // scale factor to reach upper 32 bits
+ INITIAL_ARG_VAL = ONE_MILLION << 1; // <<1 makes space for sign bit;
+ static long nextArgVal;
+ static long nextArg(boolean moreBits) {
+ long val = nextArgVal++;
+ long sign = -(val & 1); // alternate signs
+ val >>= 1;
+ if (moreBits)
+ // Guarantee some bits in the high word.
+ // In any case keep the decimal representation simple-looking,
+ // with lots of zeroes, so as not to make the printed decimal
+ // strings unnecessarily noisy.
+ val += (val % ONE_MILLION) * TEN_BILLION;
+ return val ^ sign;
+ }
+ static int nextArg() {
+ // Produce a 32-bit result something like ONE_MILLION+(smallint).
+ // Example: 1_000_042.
+ return (int) nextArg(false);
+ }
+ static long nextArg(Class<?> kind) {
+ if (kind == long.class || kind == Long.class ||
+ kind == double.class || kind == Double.class)
+ // produce a 64-bit result something like
+ // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
+ // Example: 10_000_420_001_000_042.
+ return nextArg(true);
+ return (long) nextArg();
+ }
+
+ static Object randomArg(Class<?> param) {
+ Object wrap = castToWrapperOrNull(nextArg(param), param);
+ if (wrap != null) {
+ return wrap;
+ }
+// import sun.invoke.util.Wrapper;
+// Wrapper wrap = Wrapper.forBasicType(dst);
+// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
+// wrap = Wrapper.forWrapperType(dst);
+// if (wrap != Wrapper.OBJECT)
+// return wrap.wrap(nextArg++);
+ if (param.isInterface()) {
+ for (Class<?> c : param.getClasses()) {
+ if (param.isAssignableFrom(c) && !c.isInterface())
+ { param = c; break; }
+ }
+ }
+ if (param.isInterface() || param.isAssignableFrom(String.class))
+ return "#"+nextArg();
+ else
+ try {
+ return param.newInstance();
+ } catch (InstantiationException ex) {
+ } catch (IllegalAccessException ex) {
+ }
+ return null; // random class not Object, String, Integer, etc.
+ }
+ static Object[] randomArgs(Class<?>... params) {
+ Object[] args = new Object[params.length];
+ for (int i = 0; i < args.length; i++)
+ args[i] = randomArg(params[i]);
+ return args;
+ }
+ static Object[] randomArgs(int nargs, Class<?> param) {
+ Object[] args = new Object[nargs];
+ for (int i = 0; i < args.length; i++)
+ args[i] = randomArg(param);
+ return args;
+ }
+
+ static final Object ANON_OBJ = new Object();
+ static Object zeroArg(Class<?> param) {
+ Object x = castToWrapperOrNull(0L, param);
+ if (x != null) return x;
+ if (param.isInterface() || param.isAssignableFrom(String.class)) return "\"\"";
+ if (param == Object.class) return ANON_OBJ;
+ if (param.getComponentType() != null) return Array.newInstance(param.getComponentType(), 0);
+ return null;
+ }
+ static Object[] zeroArgs(Class<?>... params) {
+ Object[] args = new Object[params.length];
+ for (int i = 0; i < args.length; i++)
+ args[i] = zeroArg(params[i]);
+ return args;
+ }
+ static Object[] zeroArgs(List<Class<?>> params) {
+ return zeroArgs(params.toArray(new Class<?>[0]));
+ }
+
+ static <T, E extends T> T[] array(Class<T[]> atype, E... a) {
+ return Arrays.copyOf(a, a.length, atype);
+ }
+ static <T> T[] cat(T[] a, T... b) {
+ int alen = a.length, blen = b.length;
+ if (blen == 0) return a;
+ T[] c = Arrays.copyOf(a, alen + blen);
+ System.arraycopy(b, 0, c, alen, blen);
+ return c;
+ }
+ static Integer[] boxAll(int... vx) {
+ Integer[] res = new Integer[vx.length];
+ for (int i = 0; i < res.length; i++) {
+ res[i] = vx[i];
+ }
+ return res;
+ }
+ static Object getClasses(Object x) {
+ if (x == null) return x;
+ if (x instanceof String) return x; // keep the name
+ if (x instanceof List) {
+ // recursively report classes of the list elements
+ Object[] xa = ((List)x).toArray();
+ for (int i = 0; i < xa.length; i++)
+ xa[i] = getClasses(xa[i]);
+ return Arrays.asList(xa);
+ }
+ return x.getClass().getSimpleName();
+ }
+
+ static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) {
+ return changeArgTypes(target, 0, 999, argType);
+ }
+ static MethodHandle changeArgTypes(MethodHandle target,
+ int beg, int end, Class<?> argType) {
+ MethodType targetType = target.type();
+ end = Math.min(end, targetType.parameterCount());
+ ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList());
+ Collections.fill(argTypes.subList(beg, end), argType);
+ MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
+ return MethodHandles.convertArguments(target, ttype2);
+ }
+
+ // This lookup is good for all members in and under InvokeGenericTest.
+ static final Lookup LOOKUP = MethodHandles.lookup();
+
+ Map<List<Class<?>>, MethodHandle> CALLABLES = new HashMap<List<Class<?>>, MethodHandle>();
+ MethodHandle callable(List<Class<?>> params) {
+ MethodHandle mh = CALLABLES.get(params);
+ if (mh == null) {
+ mh = collector_MH.asType(methodType(Object.class, params));
+ CALLABLES.put(params, mh);
+ }
+ return mh;
+ }
+ MethodHandle callable(Class<?>... params) {
+ return callable(Arrays.asList(params));
+ }
+ private static Object collector(Object... args) {
+ return Arrays.asList(args);
+ }
+ private static final MethodHandle collector_MH;
+ static {
+ try {
+ collector_MH
+ = LOOKUP.findStatic(LOOKUP.lookupClass(),
+ "collector",
+ methodType(Object.class, Object[].class));
+ } catch (ReflectiveOperationException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Test
+ public void testSimple() throws Throwable {
+ startTest("testSimple");
+ countTest();
+ String[] args = { "one", "two" };
+ MethodHandle mh = callable(Object.class, String.class);
+ Object res; List resl;
+ res = resl = (List) mh.invokeGeneric((String)args[0], (Object)args[1]);
+ //System.out.println(res);
+ assertEquals(Arrays.asList(args), res);
+ }
+
+ @Test
+ public void testWrongArgumentCount() throws Throwable {
+ startTest("testWrongArgumentCount");
+ for (int i = 0; i <= 10; i++) {
+ testWrongArgumentCount(Collections.<Class<?>>nCopies(i, Integer.class));
+ if (i <= 4) {
+ testWrongArgumentCount(Collections.<Class<?>>nCopies(i, int.class));
+ testWrongArgumentCount(Collections.<Class<?>>nCopies(i, long.class));
+ }
+ }
+ }
+ public void testWrongArgumentCount(List<Class<?>> params) throws Throwable {
+ int max = params.size();
+ for (int i = 0; i < max; i++) {
+ List<Class<?>> params2 = params.subList(0, i);
+ for (int k = 0; k <= 2; k++) {
+ if (k == 1) params = methodType(Object.class, params).generic().parameterList();
+ if (k == 2) params2 = methodType(Object.class, params2).generic().parameterList();
+ testWrongArgumentCount(params, params2);
+ testWrongArgumentCount(params2, params);
+ }
+ }
+ }
+ public void testWrongArgumentCount(List<Class<?>> expect, List<Class<?>> observe) throws Throwable {
+ countTest(false);
+ if (expect.equals(observe))
+ assert(false);
+ MethodHandle target = callable(expect);
+ Object[] args = zeroArgs(observe);
+ Object junk;
+ try {
+ switch (args.length) {
+ case 0:
+ junk = target.invokeGeneric(); break;
+ case 1:
+ junk = target.invokeGeneric(args[0]); break;
+ case 2:
+ junk = target.invokeGeneric(args[0], args[1]); break;
+ case 3:
+ junk = target.invokeGeneric(args[0], args[1], args[2]); break;
+ case 4:
+ junk = target.invokeGeneric(args[0], args[1], args[2], args[3]); break;
+ default:
+ junk = target.invokeWithArguments(args); break;
+ }
+ } catch (WrongMethodTypeException ex) {
+ return;
+ } catch (Exception ex) {
+ throw new RuntimeException("wrong exception calling "+target+target.type()+" on "+Arrays.asList(args)+" : "+ex);
+ }
+ throw new RuntimeException("bad success calling "+target+target.type()+" on "+Arrays.asList(args));
+ }
+
+ /** Make a list of all combinations of the given types, with the given arities.
+ * A void return type is possible iff the first type is void.class.
+ */
+ static List<MethodType> allMethodTypes(int minargc, int maxargc, Class<?>... types) {
+ ArrayList<MethodType> result = new ArrayList<MethodType>();
+ if (types.length > 0) {
+ ArrayList<MethodType> argcTypes = new ArrayList<MethodType>();
+ // build arity-zero types first
+ for (Class<?> rtype : types) {
+ argcTypes.add(MethodType.methodType(rtype));
+ }
+ if (types[0] == void.class)
+ // void is not an argument type
+ types = Arrays.copyOfRange(types, 1, types.length);
+ for (int argc = 0; argc <= maxargc; argc++) {
+ if (argc >= minargc)
+ result.addAll(argcTypes);
+ if (argc >= maxargc)
+ break;
+ ArrayList<MethodType> prevTypes = argcTypes;
+ argcTypes = new ArrayList<MethodType>();
+ for (MethodType prevType : prevTypes) {
+ for (Class<?> ptype : types) {
+ argcTypes.add(prevType.insertParameterTypes(argc, ptype));
+ }
+ }
+ }
+ }
+ return Collections.unmodifiableList(result);
+ }
+ static List<MethodType> allMethodTypes(int argc, Class<?>... types) {
+ return allMethodTypes(argc, argc, types);
+ }
+
+ interface RandomInterface { }
+
+ MethodHandle toString_MH;
+
+ @Test
+ public void testReferenceConversions() throws Throwable {
+ startTest("testReferenceConversions");
+ toString_MH = LOOKUP.
+ findVirtual(Object.class, "toString", MethodType.methodType(String.class));
+ String[] args = { "one", "two" };
+ for (MethodType type : allMethodTypes(2, Object.class, String.class, RandomInterface.class)) {
+ testReferenceConversions(type, args);
+ }
+ }
+ public void testReferenceConversions(MethodType type, Object... args) throws Throwable {
+ countTest();
+ if (verbosity > 3) System.out.println("target type: "+type);
+ MethodHandle mh = callable(type.parameterList());
+ MethodHandle tsdrop = MethodHandles.dropArguments(toString_MH, 1, type.parameterList());
+ mh = MethodHandles.foldArguments(tsdrop, mh);
+ mh = mh.asType(type);
+ Object res = mh.invokeGeneric((String)args[0], (Object)args[1]);
+ //System.out.println(res);
+ assertEquals(Arrays.asList(args).toString(), res);
+ }
+
+
+ @Test @Ignore("known failure pending 6939861")
+ public void testBoxConversions() throws Throwable {
+ startTest("testBoxConversions");
+ countTest();
+ Integer[] args = { 1, 2 };
+ MethodHandle mh = callable(Object.class, int.class);
+ Object res; List resl;
+ res = resl = (List) mh.invokeGeneric((int)args[0], (Object)args[1]);
+ //System.out.println(res);
+ assertEquals(Arrays.asList(args), res);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary example code used in javadoc for java.lang.invoke API
+ * @compile -XDallowTransitionalJSR292=no JavaDocExamplesTest.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.JavaDocExamplesTest
+ */
+
+/*
+---- To run outside jtreg:
+$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
+ $DAVINCI/sources/jdk/test/java/lang/invoke/JavaDocExamplesTest.java
+$ $JAVA7X_HOME/bin/java -cp $JUNIT4_JAR:/tmp/Classes \
+ -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
+ -Dtest.java.lang.invoke.JavaDocExamplesTest.verbosity=1 \
+ test.java.lang.invoke.JavaDocExamplesTest
+----
+*/
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.junit.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+
+/**
+ * @author jrose
+ */
+public class JavaDocExamplesTest {
+ /** Wrapper for running the JUnit tests in this module.
+ * Put JUnit on the classpath!
+ */
+ public static void main(String... ignore) {
+ org.junit.runner.JUnitCore.runClasses(JavaDocExamplesTest.class);
+ }
+ // How much output?
+ static int verbosity = Integer.getInteger("test.java.lang.invoke.JavaDocExamplesTest.verbosity", 0);
+
+{}
+static final private Lookup LOOKUP = lookup();
+// static final private MethodHandle CONCAT_1 = LOOKUP.findVirtual(String.class,
+// "concat", methodType(String.class, String.class));
+// static final private MethodHandle HASHCODE_1 = LOOKUP.findVirtual(Object.class,
+// "hashCode", methodType(int.class));
+
+// form required if ReflectiveOperationException is intercepted:
+static final private MethodHandle CONCAT_2, HASHCODE_2;
+static {
+ try {
+ CONCAT_2 = LOOKUP.findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+ HASHCODE_2 = LOOKUP.findVirtual(Object.class,
+ "hashCode", methodType(int.class));
+ } catch (ReflectiveOperationException ex) {
+ throw new RuntimeException(ex);
+ }
+}
+{}
+
+ @Test public void testFindVirtual() throws Throwable {
+{}
+MethodHandle CONCAT_3 = LOOKUP.findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+MethodHandle HASHCODE_3 = LOOKUP.findVirtual(Object.class,
+ "hashCode", methodType(int.class));
+//assertEquals("xy", (String) CONCAT_1.invokeExact("x", "y"));
+assertEquals("xy", (String) CONCAT_2.invokeExact("x", "y"));
+assertEquals("xy", (String) CONCAT_3.invokeExact("x", "y"));
+//assertEquals("xy".hashCode(), (int) HASHCODE_1.invokeExact((Object)"xy"));
+assertEquals("xy".hashCode(), (int) HASHCODE_2.invokeExact((Object)"xy"));
+assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy"));
+{}
+ }
+ @Test public void testDropArguments() throws Throwable {
+ {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
+MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
+assertEquals(bigType, d0.type());
+assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
+ }}
+ {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle d0 = dropArguments(cat, 0, String.class);
+assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
+MethodHandle d1 = dropArguments(cat, 1, String.class);
+assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
+MethodHandle d2 = dropArguments(cat, 2, String.class);
+assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
+MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
+assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
+ }}
+ }
+
+ @Test public void testFilterArguments() throws Throwable {
+ {{
+{} /// JAVADOC
+MethodHandle cat = lookup().findVirtual(String.class,
+ "concat", methodType(String.class, String.class));
+MethodHandle upcase = lookup().findVirtual(String.class,
+ "toUpperCase", methodType(String.class));
+assertEquals("xy", (String) cat.invokeExact("x", "y"));
+MethodHandle f0 = filterArguments(cat, 0, upcase);
+assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
+MethodHandle f1 = filterArguments(cat, 1, upcase);
+assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
+MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
+assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
+ }}
+ }
+
+ static void assertEquals(Object exp, Object act) {
+ if (verbosity > 0)
+ System.out.println("result: "+act);
+ Assert.assertEquals(exp, act);
+ }
+
+ @Test public void testMethodHandlesSummary() throws Throwable {
+ {{
+{} /// JAVADOC
+Object x, y; String s; int i;
+MethodType mt; MethodHandle mh;
+MethodHandles.Lookup lookup = MethodHandles.lookup();
+// mt is (char,char)String
+mt = MethodType.methodType(String.class, char.class, char.class);
+mh = lookup.findVirtual(String.class, "replace", mt);
+s = (String) mh.invokeExact("daddy",'d','n');
+// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
+assert(s.equals("nanny"));
+// weakly typed invocation (using MHs.invoke)
+s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
+assert(s.equals("savvy"));
+// mt is (Object[])List
+mt = MethodType.methodType(java.util.List.class, Object[].class);
+mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
+assert(mh.isVarargsCollector());
+x = mh.invokeGeneric("one", "two");
+// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
+assert(x.equals(java.util.Arrays.asList("one","two")));
+// mt is (Object,Object,Object)Object
+mt = MethodType.genericMethodType(3);
+mh = mh.asType(mt);
+x = mh.invokeExact((Object)1, (Object)2, (Object)3);
+// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+assert(x.equals(java.util.Arrays.asList(1,2,3)));
+// mt is { => int}
+mt = MethodType.methodType(int.class);
+mh = lookup.findVirtual(java.util.List.class, "size", mt);
+i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
+// invokeExact(Ljava/util/List;)I
+assert(i == 3);
+mt = MethodType.methodType(void.class, String.class);
+mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
+mh.invokeExact(System.out, "Hello, world.");
+// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
+{}
+ }}
+ }
+
+ @Test public void testAsVarargsCollector() throws Throwable {
+ {{
+{} /// JAVADOC
+MethodHandle asList = publicLookup()
+ .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
+ .asVarargsCollector(Object[].class);
+assertEquals("[]", asList.invokeGeneric().toString());
+assertEquals("[1]", asList.invokeGeneric(1).toString());
+assertEquals("[two, too]", asList.invokeGeneric("two", "too").toString());
+Object[] argv = { "three", "thee", "tee" };
+assertEquals("[three, thee, tee]", asList.invokeGeneric(argv).toString());
+List ls = (List) asList.invokeGeneric((Object)argv);
+assertEquals(1, ls.size());
+assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
+ }}
+ }
+
+ @Test public void testVarargsCollectorSuppression() throws Throwable {
+ {{
+{} /// JAVADOC
+MethodHandle vamh = publicLookup()
+ .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
+ .asVarargsCollector(Object[].class);
+MethodHandle mh = MethodHandles.exactInvoker(vamh.type()).bindTo(vamh);
+assert(vamh.type().equals(mh.type()));
+assertEquals("[1, 2, 3]", vamh.invokeGeneric(1,2,3).toString());
+boolean failed = false;
+try { mh.invokeGeneric(1,2,3); }
+catch (WrongMethodTypeException ex) { failed = true; }
+assert(failed);
+{}
+ }}
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/MethodHandlesTest.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,2400 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodHandles
+ * @compile -source 7 -target 7 -XDallowTransitionalJSR292=no MethodHandlesTest.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.MethodHandlesTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.*;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.reflect.*;
+import java.util.*;
+import org.junit.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+
+/**
+ *
+ * @author jrose
+ */
+public class MethodHandlesTest {
+ // How much output?
+ static int verbosity = 0;
+ static {
+ String vstr = System.getProperty("test.java.lang.invoke.MethodHandlesTest.verbosity");
+ if (vstr != null) verbosity = Integer.parseInt(vstr);
+ }
+
+ // Set this true during development if you want to fast-forward to
+ // a particular new, non-working test. Tests which are known to
+ // work (or have recently worked) test this flag and return on true.
+ static boolean CAN_SKIP_WORKING = false;
+ //static { CAN_SKIP_WORKING = true; }
+
+ // Set true to test more calls. If false, some tests are just
+ // lookups, without exercising the actual method handle.
+ static boolean DO_MORE_CALLS = true;
+
+ @Test
+ public void testFirst() throws Throwable {
+ verbosity += 9; try {
+ // left blank for debugging
+ } finally { printCounts(); verbosity -= 9; }
+ }
+
+ // current failures
+ @Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
+ public void testFail_1() throws Throwable {
+ // AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters
+ testSpreadArguments(int.class, 0, 6);
+ }
+ @Test @Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args")
+ public void testFail_2() throws Throwable {
+ // if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes:
+ testSpreadArguments(Object.class, 0, 2);
+ }
+ @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
+ public void testFail_3() throws Throwable {
+ // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
+ testSpreadArguments(int.class, 1, 2);
+ }
+ @Test @Ignore("IllArgEx failure in call to ToGeneric.make")
+ public void testFail_4() throws Throwable {
+ // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
+ testCollectArguments(int.class, 1, 2);
+ }
+ @Test @Ignore("cannot collect leading primitive types")
+ public void testFail_5() throws Throwable {
+ // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
+ testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class));
+ }
+ @Test @Ignore("should not insert arguments beyond MethodHandlePushLimit")
+ public void testFail_6() throws Throwable {
+ // ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13
+ testInsertArguments(0, 0, MAX_ARG_INCREASE+10);
+ }
+ static final int MAX_ARG_INCREASE = 3;
+
+ public MethodHandlesTest() {
+ }
+
+ @Before
+ public void checkImplementedPlatform() {
+ boolean platformOK = false;
+ Properties properties = System.getProperties();
+ String vers = properties.getProperty("java.vm.version");
+ String name = properties.getProperty("java.vm.name");
+ String arch = properties.getProperty("os.arch");
+ if ((arch.equals("amd64") || arch.equals("i386") || arch.equals("x86") ||
+ arch.equals("sparc") || arch.equals("sparcv9")) &&
+ (name.contains("Client") || name.contains("Server"))
+ ) {
+ platformOK = true;
+ } else {
+ System.err.println("Skipping tests for unsupported platform: "+Arrays.asList(vers, name, arch));
+ }
+ assumeTrue(platformOK);
+ }
+
+ String testName;
+ static int allPosTests, allNegTests;
+ int posTests, negTests;
+ @After
+ public void printCounts() {
+ if (verbosity >= 2 && (posTests | negTests) != 0) {
+ System.out.println();
+ if (posTests != 0) System.out.println("=== "+testName+": "+posTests+" positive test cases run");
+ if (negTests != 0) System.out.println("=== "+testName+": "+negTests+" negative test cases run");
+ allPosTests += posTests;
+ allNegTests += negTests;
+ posTests = negTests = 0;
+ }
+ }
+ void countTest(boolean positive) {
+ if (positive) ++posTests;
+ else ++negTests;
+ }
+ void countTest() { countTest(true); }
+ void startTest(String name) {
+ if (testName != null) printCounts();
+ if (verbosity >= 1)
+ System.out.println(name);
+ posTests = negTests = 0;
+ testName = name;
+ }
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ calledLog.clear();
+ calledLog.add(null);
+ nextArgVal = INITIAL_ARG_VAL;
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ int posTests = allPosTests, negTests = allNegTests;
+ if (verbosity >= 2 && (posTests | negTests) != 0) {
+ System.out.println();
+ if (posTests != 0) System.out.println("=== "+posTests+" total positive test cases");
+ if (negTests != 0) System.out.println("=== "+negTests+" total negative test cases");
+ }
+ }
+
+ static List<Object> calledLog = new ArrayList<Object>();
+ static Object logEntry(String name, Object... args) {
+ return Arrays.asList(name, Arrays.asList(args));
+ }
+ static Object called(String name, Object... args) {
+ Object entry = logEntry(name, args);
+ calledLog.add(entry);
+ return entry;
+ }
+ static void assertCalled(String name, Object... args) {
+ Object expected = logEntry(name, args);
+ Object actual = calledLog.get(calledLog.size() - 1);
+ if (expected.equals(actual) && verbosity < 9) return;
+ System.out.println("assertCalled "+name+":");
+ System.out.println("expected: "+expected);
+ System.out.println("actual: "+actual);
+ System.out.println("ex. types: "+getClasses(expected));
+ System.out.println("act. types: "+getClasses(actual));
+ assertEquals("previous method call", expected, actual);
+ }
+ static void printCalled(MethodHandle target, String name, Object... args) {
+ if (verbosity >= 3)
+ System.out.println("calling MH="+target+" to "+name+Arrays.toString(args));
+ }
+
+ static Object castToWrapper(Object value, Class<?> dst) {
+ Object wrap = null;
+ if (value instanceof Number)
+ wrap = castToWrapperOrNull(((Number)value).longValue(), dst);
+ if (value instanceof Character)
+ wrap = castToWrapperOrNull((char)(Character)value, dst);
+ if (wrap != null) return wrap;
+ return dst.cast(value);
+ }
+
+ static Object castToWrapperOrNull(long value, Class<?> dst) {
+ if (dst == int.class || dst == Integer.class)
+ return (int)(value);
+ if (dst == long.class || dst == Long.class)
+ return (long)(value);
+ if (dst == char.class || dst == Character.class)
+ return (char)(value);
+ if (dst == short.class || dst == Short.class)
+ return (short)(value);
+ if (dst == float.class || dst == Float.class)
+ return (float)(value);
+ if (dst == double.class || dst == Double.class)
+ return (double)(value);
+ if (dst == byte.class || dst == Byte.class)
+ return (byte)(value);
+ if (dst == boolean.class || dst == boolean.class)
+ return ((value % 29) & 1) == 0;
+ return null;
+ }
+
+ static final int ONE_MILLION = (1000*1000), // first int value
+ TEN_BILLION = (10*1000*1000*1000), // scale factor to reach upper 32 bits
+ INITIAL_ARG_VAL = ONE_MILLION << 1; // <<1 makes space for sign bit;
+ static long nextArgVal;
+ static long nextArg(boolean moreBits) {
+ long val = nextArgVal++;
+ long sign = -(val & 1); // alternate signs
+ val >>= 1;
+ if (moreBits)
+ // Guarantee some bits in the high word.
+ // In any case keep the decimal representation simple-looking,
+ // with lots of zeroes, so as not to make the printed decimal
+ // strings unnecessarily noisy.
+ val += (val % ONE_MILLION) * TEN_BILLION;
+ return val ^ sign;
+ }
+ static int nextArg() {
+ // Produce a 32-bit result something like ONE_MILLION+(smallint).
+ // Example: 1_000_042.
+ return (int) nextArg(false);
+ }
+ static long nextArg(Class<?> kind) {
+ if (kind == long.class || kind == Long.class ||
+ kind == double.class || kind == Double.class)
+ // produce a 64-bit result something like
+ // ((TEN_BILLION+1) * (ONE_MILLION+(smallint)))
+ // Example: 10_000_420_001_000_042.
+ return nextArg(true);
+ return (long) nextArg();
+ }
+
+ static Object randomArg(Class<?> param) {
+ Object wrap = castToWrapperOrNull(nextArg(param), param);
+ if (wrap != null) {
+ return wrap;
+ }
+// import sun.invoke.util.Wrapper;
+// Wrapper wrap = Wrapper.forBasicType(dst);
+// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
+// wrap = Wrapper.forWrapperType(dst);
+// if (wrap != Wrapper.OBJECT)
+// return wrap.wrap(nextArg++);
+ if (param.isInterface()) {
+ for (Class<?> c : param.getClasses()) {
+ if (param.isAssignableFrom(c) && !c.isInterface())
+ { param = c; break; }
+ }
+ }
+ if (param.isInterface() || param.isAssignableFrom(String.class))
+ return "#"+nextArg();
+ else
+ try {
+ return param.newInstance();
+ } catch (InstantiationException ex) {
+ } catch (IllegalAccessException ex) {
+ }
+ return null; // random class not Object, String, Integer, etc.
+ }
+ static Object[] randomArgs(Class<?>... params) {
+ Object[] args = new Object[params.length];
+ for (int i = 0; i < args.length; i++)
+ args[i] = randomArg(params[i]);
+ return args;
+ }
+ static Object[] randomArgs(int nargs, Class<?> param) {
+ Object[] args = new Object[nargs];
+ for (int i = 0; i < args.length; i++)
+ args[i] = randomArg(param);
+ return args;
+ }
+
+ static <T, E extends T> T[] array(Class<T[]> atype, E... a) {
+ return Arrays.copyOf(a, a.length, atype);
+ }
+ static <T> T[] cat(T[] a, T... b) {
+ int alen = a.length, blen = b.length;
+ if (blen == 0) return a;
+ T[] c = Arrays.copyOf(a, alen + blen);
+ System.arraycopy(b, 0, c, alen, blen);
+ return c;
+ }
+ static Integer[] boxAll(int... vx) {
+ Integer[] res = new Integer[vx.length];
+ for (int i = 0; i < res.length; i++) {
+ res[i] = vx[i];
+ }
+ return res;
+ }
+ static Object getClasses(Object x) {
+ if (x == null) return x;
+ if (x instanceof String) return x; // keep the name
+ if (x instanceof List) {
+ // recursively report classes of the list elements
+ Object[] xa = ((List)x).toArray();
+ for (int i = 0; i < xa.length; i++)
+ xa[i] = getClasses(xa[i]);
+ return Arrays.asList(xa);
+ }
+ return x.getClass().getSimpleName();
+ }
+
+ /** Return lambda(arg...[arity]) { new Object[]{ arg... } } */
+ static MethodHandle varargsList(int arity) {
+ return ValueConversions.varargsList(arity);
+ }
+ /** Return lambda(arg...[arity]) { Arrays.asList(arg...) } */
+ static MethodHandle varargsArray(int arity) {
+ return ValueConversions.varargsArray(arity);
+ }
+ /** Variation of varargsList, but with the given rtype. */
+ static MethodHandle varargsList(int arity, Class<?> rtype) {
+ MethodHandle list = varargsList(arity);
+ MethodType listType = list.type().changeReturnType(rtype);
+ if (List.class.isAssignableFrom(rtype) || rtype == void.class || rtype == Object.class) {
+ // OK
+ } else if (rtype.isAssignableFrom(String.class)) {
+ if (LIST_TO_STRING == null)
+ try {
+ LIST_TO_STRING = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToString",
+ MethodType.methodType(String.class, List.class));
+ } catch (Exception ex) { throw new RuntimeException(ex); }
+ list = MethodHandles.filterReturnValue(list, LIST_TO_STRING);
+ } else if (rtype.isPrimitive()) {
+ if (LIST_TO_INT == null)
+ try {
+ LIST_TO_INT = PRIVATE.findStatic(PRIVATE.lookupClass(), "listToInt",
+ MethodType.methodType(int.class, List.class));
+ } catch (Exception ex) { throw new RuntimeException(ex); }
+ list = MethodHandles.filterReturnValue(list, LIST_TO_INT);
+ list = MethodHandles.explicitCastArguments(list, listType);
+ } else {
+ throw new RuntimeException("varargsList: "+rtype);
+ }
+ return list.asType(listType);
+ }
+ private static MethodHandle LIST_TO_STRING, LIST_TO_INT;
+ private static String listToString(List x) { return x.toString(); }
+ private static int listToInt(List x) { return x.toString().hashCode(); }
+
+ static MethodHandle changeArgTypes(MethodHandle target, Class<?> argType) {
+ return changeArgTypes(target, 0, 999, argType);
+ }
+ static MethodHandle changeArgTypes(MethodHandle target,
+ int beg, int end, Class<?> argType) {
+ MethodType targetType = target.type();
+ end = Math.min(end, targetType.parameterCount());
+ ArrayList<Class<?>> argTypes = new ArrayList<Class<?>>(targetType.parameterList());
+ Collections.fill(argTypes.subList(beg, end), argType);
+ MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
+ return MethodHandles.convertArguments(target, ttype2);
+ }
+
+ // This lookup is good for all members in and under MethodHandlesTest.
+ static final Lookup PRIVATE = MethodHandles.lookup();
+ // This lookup is good for package-private members but not private ones.
+ static final Lookup PACKAGE = PackageSibling.lookup();
+ // This lookup is good only for public members.
+ static final Lookup PUBLIC = MethodHandles.publicLookup();
+
+ // Subject methods...
+ static class Example implements IntExample {
+ final String name;
+ public Example() { name = "Example#"+nextArg(); }
+ protected Example(String name) { this.name = name; }
+ protected Example(int x) { this(); called("protected <init>", this, x); }
+ @Override public String toString() { return name; }
+
+ public void v0() { called("v0", this); }
+ void pkg_v0() { called("pkg_v0", this); }
+ private void pri_v0() { called("pri_v0", this); }
+ public static void s0() { called("s0"); }
+ static void pkg_s0() { called("pkg_s0"); }
+ private static void pri_s0() { called("pri_s0"); }
+
+ public Object v1(Object x) { return called("v1", this, x); }
+ public Object v2(Object x, Object y) { return called("v2", this, x, y); }
+ public Object v2(Object x, int y) { return called("v2", this, x, y); }
+ public Object v2(int x, Object y) { return called("v2", this, x, y); }
+ public Object v2(int x, int y) { return called("v2", this, x, y); }
+ public static Object s1(Object x) { return called("s1", x); }
+ public static Object s2(int x) { return called("s2", x); }
+ public static Object s3(long x) { return called("s3", x); }
+ public static Object s4(int x, int y) { return called("s4", x, y); }
+ public static Object s5(long x, int y) { return called("s5", x, y); }
+ public static Object s6(int x, long y) { return called("s6", x, y); }
+ public static Object s7(float x, double y) { return called("s7", x, y); }
+
+ static final Lookup EXAMPLE = MethodHandles.lookup(); // for testing findSpecial
+ }
+ static final Lookup EXAMPLE = Example.EXAMPLE;
+ public static class PubExample extends Example {
+ public PubExample() { super("PubExample#"+nextArg()); }
+ }
+ static class SubExample extends Example {
+ @Override public void v0() { called("Sub/v0", this); }
+ @Override void pkg_v0() { called("Sub/pkg_v0", this); }
+ private SubExample(int x) { called("<init>", this, x); }
+ public SubExample() { super("SubExample#"+nextArg()); }
+ }
+ public static interface IntExample {
+ public void v0();
+ public static class Impl implements IntExample {
+ public void v0() { called("Int/v0", this); }
+ final String name;
+ public Impl() { name = "Impl#"+nextArg(); }
+ @Override public String toString() { return name; }
+ }
+ }
+
+ static final Object[][][] ACCESS_CASES = {
+ { { false, PUBLIC }, { false, PACKAGE }, { false, PRIVATE }, { false, EXAMPLE } }, //[0]: all false
+ { { false, PUBLIC }, { false, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[1]: only PRIVATE
+ { { false, PUBLIC }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[2]: PUBLIC false
+ { { true, PUBLIC }, { true, PACKAGE }, { true, PRIVATE }, { true, EXAMPLE } }, //[3]: all true
+ };
+
+ static Object[][] accessCases(Class<?> defc, String name, boolean isSpecial) {
+ Object[][] cases;
+ if (name.contains("pri_") || isSpecial) {
+ cases = ACCESS_CASES[1]; // PRIVATE only
+ } else if (name.contains("pkg_") || !Modifier.isPublic(defc.getModifiers())) {
+ cases = ACCESS_CASES[2]; // not PUBLIC
+ } else {
+ assertTrue(name.indexOf('_') < 0);
+ boolean pubc = Modifier.isPublic(defc.getModifiers());
+ if (pubc)
+ cases = ACCESS_CASES[3]; // all access levels
+ else
+ cases = ACCESS_CASES[2]; // PACKAGE but not PUBLIC
+ }
+ if (defc != Example.class && cases[cases.length-1][1] == EXAMPLE)
+ cases = Arrays.copyOfRange(cases, 0, cases.length-1);
+ return cases;
+ }
+ static Object[][] accessCases(Class<?> defc, String name) {
+ return accessCases(defc, name, false);
+ }
+
+ @Test
+ public void testFindStatic() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("findStatic");
+ testFindStatic(PubExample.class, void.class, "s0");
+ testFindStatic(Example.class, void.class, "s0");
+ testFindStatic(Example.class, void.class, "pkg_s0");
+ testFindStatic(Example.class, void.class, "pri_s0");
+
+ testFindStatic(Example.class, Object.class, "s1", Object.class);
+ testFindStatic(Example.class, Object.class, "s2", int.class);
+ testFindStatic(Example.class, Object.class, "s3", long.class);
+ testFindStatic(Example.class, Object.class, "s4", int.class, int.class);
+ testFindStatic(Example.class, Object.class, "s5", long.class, int.class);
+ testFindStatic(Example.class, Object.class, "s6", int.class, long.class);
+ testFindStatic(Example.class, Object.class, "s7", float.class, double.class);
+
+ testFindStatic(false, PRIVATE, Example.class, void.class, "bogus");
+ }
+
+ void testFindStatic(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ for (Object[] ac : accessCases(defc, name)) {
+ testFindStatic((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params);
+ }
+ }
+ void testFindStatic(Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ testFindStatic(true, lookup, defc, ret, name, params);
+ }
+ void testFindStatic(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ countTest(positive);
+ MethodType type = MethodType.methodType(ret, params);
+ MethodHandle target = null;
+ Exception noAccess = null;
+ try {
+ if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
+ target = lookup.in(defc).findStatic(defc, name, type);
+ } catch (ReflectiveOperationException ex) {
+ noAccess = ex;
+ if (name.contains("bogus"))
+ assertTrue(noAccess instanceof NoSuchMethodException);
+ else
+ assertTrue(noAccess instanceof IllegalAccessException);
+ }
+ if (verbosity >= 3)
+ System.out.println("findStatic "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target
+ +(noAccess == null ? "" : " !! "+noAccess));
+ if (positive && noAccess != null) throw noAccess;
+ assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+ if (!positive) return; // negative test failed as expected
+ assertEquals(type, target.type());
+ assertNameStringContains(target, name);
+ if (!DO_MORE_CALLS && lookup != PRIVATE) return;
+ Object[] args = randomArgs(params);
+ printCalled(target, name, args);
+ target.invokeWithArguments(args);
+ assertCalled(name, args);
+ if (verbosity >= 1)
+ System.out.print(':');
+ }
+
+ // rough check of name string
+ static void assertNameStringContains(Object x, String s) {
+ if (x.toString().contains(s)) return;
+ assertEquals(s, x);
+ }
+
+ @Test
+ public void testFindVirtual() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("findVirtual");
+ testFindVirtual(Example.class, void.class, "v0");
+ testFindVirtual(Example.class, void.class, "pkg_v0");
+ testFindVirtual(Example.class, void.class, "pri_v0");
+ testFindVirtual(Example.class, Object.class, "v1", Object.class);
+ testFindVirtual(Example.class, Object.class, "v2", Object.class, Object.class);
+ testFindVirtual(Example.class, Object.class, "v2", Object.class, int.class);
+ testFindVirtual(Example.class, Object.class, "v2", int.class, Object.class);
+ testFindVirtual(Example.class, Object.class, "v2", int.class, int.class);
+ testFindVirtual(false, PRIVATE, Example.class, Example.class, void.class, "bogus");
+ // test dispatch
+ testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/v0");
+ testFindVirtual(SubExample.class, Example.class, void.class, "Sub/v0");
+ testFindVirtual(SubExample.class, IntExample.class, void.class, "Sub/v0");
+ testFindVirtual(SubExample.class, SubExample.class, void.class, "Sub/pkg_v0");
+ testFindVirtual(SubExample.class, Example.class, void.class, "Sub/pkg_v0");
+ testFindVirtual(Example.class, IntExample.class, void.class, "v0");
+ testFindVirtual(IntExample.Impl.class, IntExample.class, void.class, "Int/v0");
+ }
+
+ void testFindVirtual(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ Class<?> rcvc = defc;
+ testFindVirtual(rcvc, defc, ret, name, params);
+ }
+ void testFindVirtual(Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ for (Object[] ac : accessCases(defc, name)) {
+ testFindVirtual((Boolean)ac[0], (Lookup)ac[1], rcvc, defc, ret, name, params);
+ }
+ }
+ void testFindVirtual(Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ testFindVirtual(true, lookup, rcvc, defc, ret, name, params);
+ }
+ void testFindVirtual(boolean positive, Lookup lookup, Class<?> rcvc, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ countTest(positive);
+ String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo
+ MethodType type = MethodType.methodType(ret, params);
+ MethodHandle target = null;
+ Exception noAccess = null;
+ try {
+ if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
+ target = lookup.in(defc).findVirtual(defc, methodName, type);
+ } catch (ReflectiveOperationException ex) {
+ noAccess = ex;
+ if (name.contains("bogus"))
+ assertTrue(noAccess instanceof NoSuchMethodException);
+ else
+ assertTrue(noAccess instanceof IllegalAccessException);
+ }
+ if (verbosity >= 3)
+ System.out.println("findVirtual "+lookup+": "+defc.getName()+"."+name+"/"+type+" => "+target
+ +(noAccess == null ? "" : " !! "+noAccess));
+ if (positive && noAccess != null) throw noAccess;
+ assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+ if (!positive) return; // negative test failed as expected
+ Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
+ MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
+ assertEquals(typeWithSelf, target.type());
+ assertNameStringContains(target, methodName);
+ if (!DO_MORE_CALLS && lookup != PRIVATE) return;
+ Object[] argsWithSelf = randomArgs(paramsWithSelf);
+ if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc);
+ printCalled(target, name, argsWithSelf);
+ target.invokeWithArguments(argsWithSelf);
+ assertCalled(name, argsWithSelf);
+ if (verbosity >= 1)
+ System.out.print(':');
+ }
+
+ @Test
+ public void testFindSpecial() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("findSpecial");
+ testFindSpecial(SubExample.class, Example.class, void.class, "v0");
+ testFindSpecial(SubExample.class, Example.class, void.class, "pkg_v0");
+ // Do some negative testing:
+ testFindSpecial(false, EXAMPLE, SubExample.class, Example.class, void.class, "bogus");
+ testFindSpecial(false, PRIVATE, SubExample.class, Example.class, void.class, "bogus");
+ for (Lookup lookup : new Lookup[]{ PRIVATE, EXAMPLE, PACKAGE, PUBLIC }) {
+ testFindSpecial(false, lookup, Object.class, Example.class, void.class, "v0");
+ testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "<init>", int.class);
+ testFindSpecial(false, lookup, SubExample.class, Example.class, void.class, "s0");
+ }
+ }
+
+ void testFindSpecial(Class<?> specialCaller,
+ Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ testFindSpecial(true, EXAMPLE, specialCaller, defc, ret, name, params);
+ testFindSpecial(true, PRIVATE, specialCaller, defc, ret, name, params);
+ testFindSpecial(false, PACKAGE, specialCaller, defc, ret, name, params);
+ testFindSpecial(false, PUBLIC, specialCaller, defc, ret, name, params);
+ }
+ void testFindSpecial(boolean positive, Lookup lookup, Class<?> specialCaller,
+ Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ countTest(positive);
+ MethodType type = MethodType.methodType(ret, params);
+ MethodHandle target = null;
+ Exception noAccess = null;
+ try {
+ if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
+ if (verbosity >= 5) System.out.println(" lookup => "+lookup.in(specialCaller));
+ target = lookup.in(specialCaller).findSpecial(defc, name, type, specialCaller);
+ } catch (ReflectiveOperationException ex) {
+ noAccess = ex;
+ if (name.contains("bogus"))
+ assertTrue(noAccess instanceof NoSuchMethodException);
+ else
+ assertTrue(noAccess instanceof IllegalAccessException);
+ }
+ if (verbosity >= 3)
+ System.out.println("findSpecial from "+specialCaller.getName()+" to "+defc.getName()+"."+name+"/"+type+" => "+target
+ +(target == null ? "" : target.type())
+ +(noAccess == null ? "" : " !! "+noAccess));
+ if (positive && noAccess != null) throw noAccess;
+ assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+ if (!positive) return; // negative test failed as expected
+ assertEquals(specialCaller, target.type().parameterType(0));
+ assertEquals(type, target.type().dropParameterTypes(0,1));
+ Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params);
+ MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
+ assertNameStringContains(target, name);
+ if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE) return;
+ Object[] args = randomArgs(paramsWithSelf);
+ printCalled(target, name, args);
+ target.invokeWithArguments(args);
+ assertCalled(name, args);
+ }
+
+ @Test
+ public void testBind() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("bind");
+ testBind(Example.class, void.class, "v0");
+ testBind(Example.class, void.class, "pkg_v0");
+ testBind(Example.class, void.class, "pri_v0");
+ testBind(Example.class, Object.class, "v1", Object.class);
+ testBind(Example.class, Object.class, "v2", Object.class, Object.class);
+ testBind(Example.class, Object.class, "v2", Object.class, int.class);
+ testBind(Example.class, Object.class, "v2", int.class, Object.class);
+ testBind(Example.class, Object.class, "v2", int.class, int.class);
+ testBind(false, PRIVATE, Example.class, void.class, "bogus");
+ testBind(SubExample.class, void.class, "Sub/v0");
+ testBind(SubExample.class, void.class, "Sub/pkg_v0");
+ testBind(IntExample.Impl.class, void.class, "Int/v0");
+ }
+
+ void testBind(Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ for (Object[] ac : accessCases(defc, name)) {
+ testBind((Boolean)ac[0], (Lookup)ac[1], defc, ret, name, params);
+ }
+ }
+
+ void testBind(boolean positive, Lookup lookup, Class<?> defc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ countTest(positive);
+ String methodName = name.substring(1 + name.indexOf('/')); // foo/bar => foo
+ MethodType type = MethodType.methodType(ret, params);
+ Object receiver = randomArg(defc);
+ MethodHandle target = null;
+ Exception noAccess = null;
+ try {
+ if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
+ target = lookup.in(defc).bind(receiver, methodName, type);
+ } catch (ReflectiveOperationException ex) {
+ noAccess = ex;
+ if (name.contains("bogus"))
+ assertTrue(noAccess instanceof NoSuchMethodException);
+ else
+ assertTrue(noAccess instanceof IllegalAccessException);
+ }
+ if (verbosity >= 3)
+ System.out.println("bind "+receiver+"."+name+"/"+type+" => "+target
+ +(noAccess == null ? "" : " !! "+noAccess));
+ if (positive && noAccess != null) throw noAccess;
+ assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+ if (!positive) return; // negative test failed as expected
+ assertEquals(type, target.type());
+ Object[] args = randomArgs(params);
+ printCalled(target, name, args);
+ target.invokeWithArguments(args);
+ Object[] argsWithReceiver = cat(array(Object[].class, receiver), args);
+ assertCalled(name, argsWithReceiver);
+ if (verbosity >= 1)
+ System.out.print(':');
+ }
+
+ @Test
+ public void testUnreflect() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("unreflect");
+ testUnreflect(Example.class, true, void.class, "s0");
+ testUnreflect(Example.class, true, void.class, "pkg_s0");
+ testUnreflect(Example.class, true, void.class, "pri_s0");
+
+ testUnreflect(Example.class, true, Object.class, "s1", Object.class);
+ testUnreflect(Example.class, true, Object.class, "s2", int.class);
+ testUnreflect(Example.class, true, Object.class, "s3", long.class);
+ testUnreflect(Example.class, true, Object.class, "s4", int.class, int.class);
+ testUnreflect(Example.class, true, Object.class, "s5", long.class, int.class);
+ testUnreflect(Example.class, true, Object.class, "s6", int.class, long.class);
+
+ testUnreflect(Example.class, false, void.class, "v0");
+ testUnreflect(Example.class, false, void.class, "pkg_v0");
+ testUnreflect(Example.class, false, void.class, "pri_v0");
+ testUnreflect(Example.class, false, Object.class, "v1", Object.class);
+ testUnreflect(Example.class, false, Object.class, "v2", Object.class, Object.class);
+ testUnreflect(Example.class, false, Object.class, "v2", Object.class, int.class);
+ testUnreflect(Example.class, false, Object.class, "v2", int.class, Object.class);
+ testUnreflect(Example.class, false, Object.class, "v2", int.class, int.class);
+ }
+
+ void testUnreflect(Class<?> defc, boolean isStatic, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ for (Object[] ac : accessCases(defc, name)) {
+ testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, (isStatic ? null : defc), ret, name, params);
+ }
+ }
+ void testUnreflect(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ for (Object[] ac : accessCases(defc, name)) {
+ testUnreflectMaybeSpecial(null, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
+ }
+ }
+ void testUnreflectMaybeSpecial(Class<?> specialCaller,
+ boolean positive, Lookup lookup,
+ Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ countTest(positive);
+ MethodType type = MethodType.methodType(ret, params);
+ Method rmethod = defc.getDeclaredMethod(name, params);
+ MethodHandle target = null;
+ Exception noAccess = null;
+ boolean isStatic = (rcvc == null);
+ boolean isSpecial = (specialCaller != null);
+ try {
+ if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" "+name+type);
+ if (isSpecial)
+ target = lookup.in(specialCaller).unreflectSpecial(rmethod, specialCaller);
+ else
+ target = lookup.in(defc).unreflect(rmethod);
+ } catch (ReflectiveOperationException ex) {
+ noAccess = ex;
+ if (name.contains("bogus"))
+ assertTrue(noAccess instanceof NoSuchMethodException);
+ else
+ assertTrue(noAccess instanceof IllegalAccessException);
+ }
+ if (verbosity >= 3)
+ System.out.println("unreflect"+(isSpecial?"Special":"")+" "+defc.getName()+"."+name+"/"+type
+ +(!isSpecial ? "" : " specialCaller="+specialCaller)
+ +( isStatic ? "" : " receiver="+rcvc)
+ +" => "+target
+ +(noAccess == null ? "" : " !! "+noAccess));
+ if (positive && noAccess != null) throw noAccess;
+ assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+ if (!positive) return; // negative test failed as expected
+ assertEquals(isStatic, Modifier.isStatic(rmethod.getModifiers()));
+ Class<?>[] paramsMaybeWithSelf = params;
+ if (!isStatic) {
+ paramsMaybeWithSelf = cat(array(Class[].class, (Class)rcvc), params);
+ }
+ MethodType typeMaybeWithSelf = MethodType.methodType(ret, paramsMaybeWithSelf);
+ if (isStatic) {
+ assertEquals(typeMaybeWithSelf, target.type());
+ } else {
+ if (isSpecial)
+ assertEquals(specialCaller, target.type().parameterType(0));
+ else
+ assertEquals(defc, target.type().parameterType(0));
+ assertEquals(typeMaybeWithSelf, target.type().changeParameterType(0, rcvc));
+ }
+ Object[] argsMaybeWithSelf = randomArgs(paramsMaybeWithSelf);
+ printCalled(target, name, argsMaybeWithSelf);
+ target.invokeWithArguments(argsMaybeWithSelf);
+ assertCalled(name, argsMaybeWithSelf);
+ if (verbosity >= 1)
+ System.out.print(':');
+ }
+
+ void testUnreflectSpecial(Class<?> defc, Class<?> rcvc, Class<?> ret, String name, Class<?>... params) throws Throwable {
+ for (Object[] ac : accessCases(defc, name, true)) {
+ Class<?> specialCaller = rcvc;
+ testUnreflectMaybeSpecial(specialCaller, (Boolean)ac[0], (Lookup)ac[1], defc, rcvc, ret, name, params);
+ }
+ }
+
+ @Test
+ public void testUnreflectSpecial() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("unreflectSpecial");
+ testUnreflectSpecial(Example.class, Example.class, void.class, "v0");
+ testUnreflectSpecial(Example.class, SubExample.class, void.class, "v0");
+ testUnreflectSpecial(Example.class, Example.class, void.class, "pkg_v0");
+ testUnreflectSpecial(Example.class, SubExample.class, void.class, "pkg_v0");
+ testUnreflectSpecial(Example.class, Example.class, Object.class, "v2", int.class, int.class);
+ testUnreflectSpecial(Example.class, SubExample.class, Object.class, "v2", int.class, int.class);
+ testUnreflectMaybeSpecial(Example.class, false, PRIVATE, Example.class, Example.class, void.class, "s0");
+ }
+
+ public static class HasFields {
+ boolean fZ = false;
+ byte fB = (byte)'B';
+ short fS = (short)'S';
+ char fC = 'C';
+ int fI = 'I';
+ long fJ = 'J';
+ float fF = 'F';
+ double fD = 'D';
+ static boolean sZ = true;
+ static byte sB = 1+(byte)'B';
+ static short sS = 1+(short)'S';
+ static char sC = 1+'C';
+ static int sI = 1+'I';
+ static long sJ = 1+'J';
+ static float sF = 1+'F';
+ static double sD = 1+'D';
+
+ Object fL = 'L';
+ String fR = "R";
+ static Object sL = 'M';
+ static String sR = "S";
+
+ static final Object[][] CASES;
+ static {
+ ArrayList<Object[]> cases = new ArrayList<Object[]>();
+ Object types[][] = {
+ {'L',Object.class}, {'R',String.class},
+ {'I',int.class}, {'J',long.class},
+ {'F',float.class}, {'D',double.class},
+ {'Z',boolean.class}, {'B',byte.class},
+ {'S',short.class}, {'C',char.class},
+ };
+ HasFields fields = new HasFields();
+ for (Object[] t : types) {
+ for (int kind = 0; kind <= 1; kind++) {
+ boolean isStatic = (kind != 0);
+ char btc = (Character)t[0];
+ String name = (isStatic ? "s" : "f") + btc;
+ Class<?> type = (Class<?>) t[1];
+ Object value;
+ Field field;
+ try {
+ field = HasFields.class.getDeclaredField(name);
+ } catch (Exception ex) {
+ throw new InternalError("no field HasFields."+name);
+ }
+ try {
+ value = field.get(fields);
+ } catch (Exception ex) {
+ throw new InternalError("cannot fetch field HasFields."+name);
+ }
+ if (type == float.class) {
+ float v = 'F';
+ if (isStatic) v++;
+ assertTrue(value.equals(v));
+ }
+ assertTrue(name.equals(field.getName()));
+ assertTrue(type.equals(field.getType()));
+ assertTrue(isStatic == (Modifier.isStatic(field.getModifiers())));
+ cases.add(new Object[]{ field, value });
+ }
+ }
+ cases.add(new Object[]{ new Object[]{ false, HasFields.class, "bogus_fD", double.class }, Error.class });
+ cases.add(new Object[]{ new Object[]{ true, HasFields.class, "bogus_sL", Object.class }, Error.class });
+ CASES = cases.toArray(new Object[0][]);
+ }
+ }
+
+ static final int TEST_UNREFLECT = 1, TEST_FIND_FIELD = 2, TEST_FIND_STATIC = 3, TEST_SETTER = 0x10;
+ static boolean testModeMatches(int testMode, boolean isStatic) {
+ switch (testMode) {
+ case TEST_FIND_STATIC: return isStatic;
+ case TEST_FIND_FIELD: return !isStatic;
+ case TEST_UNREFLECT: return true; // unreflect matches both
+ }
+ throw new InternalError("testMode="+testMode);
+ }
+
+ @Test
+ public void testUnreflectGetter() throws Throwable {
+ startTest("unreflectGetter");
+ testGetter(TEST_UNREFLECT);
+ }
+ @Test
+ public void testFindGetter() throws Throwable {
+ startTest("findGetter");
+ testGetter(TEST_FIND_FIELD);
+ }
+ @Test
+ public void testFindStaticGetter() throws Throwable {
+ startTest("findStaticGetter");
+ testGetter(TEST_FIND_STATIC);
+ }
+ public void testGetter(int testMode) throws Throwable {
+ Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
+ for (Object[] c : HasFields.CASES) {
+ boolean positive = (c[1] != Error.class);
+ testGetter(positive, lookup, c[0], c[1], testMode);
+ }
+ testGetter(true, lookup,
+ new Object[]{ true, System.class, "out", java.io.PrintStream.class },
+ System.out, testMode);
+ for (int isStaticN = 0; isStaticN <= 1; isStaticN++) {
+ testGetter(false, lookup,
+ new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
+ null, testMode);
+ }
+ }
+ public void testGetter(boolean positive, MethodHandles.Lookup lookup,
+ Object fieldRef, Object value, int testMode) throws Throwable {
+ testAccessor(positive, lookup, fieldRef, value, testMode);
+ }
+
+ public void testAccessor(boolean positive, MethodHandles.Lookup lookup,
+ Object fieldRef, Object value, int testMode0) throws Throwable {
+ boolean isGetter = ((testMode0 & TEST_SETTER) == 0);
+ int testMode = testMode0 & ~TEST_SETTER;
+ boolean isStatic;
+ Class<?> fclass;
+ String fname;
+ Class<?> ftype;
+ Field f = (fieldRef instanceof Field ? (Field)fieldRef : null);
+ if (f != null) {
+ isStatic = Modifier.isStatic(f.getModifiers());
+ fclass = f.getDeclaringClass();
+ fname = f.getName();
+ ftype = f.getType();
+ } else {
+ Object[] scnt = (Object[]) fieldRef;
+ isStatic = (Boolean) scnt[0];
+ fclass = (Class<?>) scnt[1];
+ fname = (String) scnt[2];
+ ftype = (Class<?>) scnt[3];
+ try {
+ f = fclass.getDeclaredField(fname);
+ } catch (ReflectiveOperationException ex) {
+ f = null;
+ }
+ }
+ if (!testModeMatches(testMode, isStatic)) return;
+ if (f == null && testMode == TEST_UNREFLECT) return;
+ countTest(positive);
+ MethodType expType;
+ if (isGetter)
+ expType = MethodType.methodType(ftype, HasFields.class);
+ else
+ expType = MethodType.methodType(void.class, HasFields.class, ftype);
+ if (isStatic) expType = expType.dropParameterTypes(0, 1);
+ Exception noAccess = null;
+ MethodHandle mh;
+ try {
+ switch (testMode0) {
+ case TEST_UNREFLECT: mh = lookup.unreflectGetter(f); break;
+ case TEST_FIND_FIELD: mh = lookup.findGetter(fclass, fname, ftype); break;
+ case TEST_FIND_STATIC: mh = lookup.findStaticGetter(fclass, fname, ftype); break;
+ case TEST_SETTER|
+ TEST_UNREFLECT: mh = lookup.unreflectSetter(f); break;
+ case TEST_SETTER|
+ TEST_FIND_FIELD: mh = lookup.findSetter(fclass, fname, ftype); break;
+ case TEST_SETTER|
+ TEST_FIND_STATIC: mh = lookup.findStaticSetter(fclass, fname, ftype); break;
+ default:
+ throw new InternalError("testMode="+testMode);
+ }
+ } catch (ReflectiveOperationException ex) {
+ mh = null;
+ noAccess = ex;
+ if (fname.contains("bogus"))
+ assertTrue(noAccess instanceof NoSuchFieldException);
+ else
+ assertTrue(noAccess instanceof IllegalAccessException);
+ }
+ if (verbosity >= 3)
+ System.out.println("find"+(isStatic?"Static":"")+(isGetter?"Getter":"Setter")+" "+fclass.getName()+"."+fname+"/"+ftype
+ +" => "+mh
+ +(noAccess == null ? "" : " !! "+noAccess));
+ if (positive && noAccess != null) throw new RuntimeException(noAccess);
+ assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, mh != null);
+ if (!positive) return; // negative test failed as expected
+ assertEquals((isStatic ? 0 : 1)+(isGetter ? 0 : 1), mh.type().parameterCount());
+
+
+ assertSame(mh.type(), expType);
+ assertNameStringContains(mh, fname);
+ HasFields fields = new HasFields();
+ Object sawValue;
+ Class<?> vtype = ftype;
+ if (ftype != int.class) vtype = Object.class;
+ if (isGetter) {
+ mh = MethodHandles.convertArguments(mh, mh.type().generic()
+ .changeReturnType(vtype));
+ } else {
+ int last = mh.type().parameterCount() - 1;
+ mh = MethodHandles.convertArguments(mh, mh.type().generic()
+ .changeReturnType(void.class)
+ .changeParameterType(last, vtype));
+ }
+ if (f != null && f.getDeclaringClass() == HasFields.class) {
+ assertEquals(f.get(fields), value); // clean to start with
+ }
+ if (isGetter) {
+ Object expValue = value;
+ for (int i = 0; i <= 1; i++) {
+ if (isStatic) {
+ if (ftype == int.class)
+ sawValue = (int) mh.invokeExact(); // do these exactly
+ else
+ sawValue = mh.invokeExact();
+ } else {
+ if (ftype == int.class)
+ sawValue = (int) mh.invokeExact((Object) fields);
+ else
+ sawValue = mh.invokeExact((Object) fields);
+ }
+ assertEquals(sawValue, expValue);
+ if (f != null && f.getDeclaringClass() == HasFields.class
+ && !Modifier.isFinal(f.getModifiers())) {
+ Object random = randomArg(ftype);
+ f.set(fields, random);
+ expValue = random;
+ } else {
+ break;
+ }
+ }
+ } else {
+ for (int i = 0; i <= 1; i++) {
+ Object putValue = randomArg(ftype);
+ if (isStatic) {
+ if (ftype == int.class)
+ mh.invokeExact((int)putValue); // do these exactly
+ else
+ mh.invokeExact(putValue);
+ } else {
+ if (ftype == int.class)
+ mh.invokeExact((Object) fields, (int)putValue);
+ else
+ mh.invokeExact((Object) fields, putValue);
+ }
+ if (f != null && f.getDeclaringClass() == HasFields.class) {
+ assertEquals(f.get(fields), putValue);
+ }
+ }
+ }
+ if (f != null && f.getDeclaringClass() == HasFields.class) {
+ f.set(fields, value); // put it back
+ }
+ }
+
+
+ @Test
+ public void testUnreflectSetter() throws Throwable {
+ startTest("unreflectSetter");
+ testSetter(TEST_UNREFLECT);
+ }
+ @Test
+ public void testFindSetter() throws Throwable {
+ startTest("findSetter");
+ testSetter(TEST_FIND_FIELD);
+ }
+ @Test
+ public void testFindStaticSetter() throws Throwable {
+ startTest("findStaticSetter");
+ testSetter(TEST_FIND_STATIC);
+ }
+ public void testSetter(int testMode) throws Throwable {
+ Lookup lookup = PRIVATE; // FIXME: test more lookups than this one
+ startTest("unreflectSetter");
+ for (Object[] c : HasFields.CASES) {
+ boolean positive = (c[1] != Error.class);
+ testSetter(positive, lookup, c[0], c[1], testMode);
+ }
+ for (int isStaticN = 0; isStaticN <= 1; isStaticN++) {
+ testSetter(false, lookup,
+ new Object[]{ (isStaticN != 0), System.class, "bogus", char.class },
+ null, testMode);
+ }
+ }
+ public void testSetter(boolean positive, MethodHandles.Lookup lookup,
+ Object fieldRef, Object value, int testMode) throws Throwable {
+ testAccessor(positive, lookup, fieldRef, value, testMode | TEST_SETTER);
+ }
+
+ @Test
+ public void testArrayElementGetter() throws Throwable {
+ startTest("arrayElementGetter");
+ testArrayElementGetterSetter(false);
+ }
+
+ @Test
+ public void testArrayElementSetter() throws Throwable {
+ startTest("arrayElementSetter");
+ testArrayElementGetterSetter(true);
+ }
+
+ public void testArrayElementGetterSetter(boolean testSetter) throws Throwable {
+ testArrayElementGetterSetter(new Object[10], testSetter);
+ testArrayElementGetterSetter(new String[10], testSetter);
+ testArrayElementGetterSetter(new boolean[10], testSetter);
+ testArrayElementGetterSetter(new byte[10], testSetter);
+ testArrayElementGetterSetter(new char[10], testSetter);
+ testArrayElementGetterSetter(new short[10], testSetter);
+ testArrayElementGetterSetter(new int[10], testSetter);
+ testArrayElementGetterSetter(new float[10], testSetter);
+ testArrayElementGetterSetter(new long[10], testSetter);
+ testArrayElementGetterSetter(new double[10], testSetter);
+ }
+
+ public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable {
+ countTest(true);
+ if (verbosity >= 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]");
+ Class<?> arrayType = array.getClass();
+ Class<?> elemType = arrayType.getComponentType();
+ MethodType expType = !testSetter
+ ? MethodType.methodType(elemType, arrayType, int.class)
+ : MethodType.methodType(void.class, arrayType, int.class, elemType);
+ MethodHandle mh = !testSetter
+ ? MethodHandles.arrayElementGetter(arrayType)
+ : MethodHandles.arrayElementSetter(arrayType);
+ assertSame(mh.type(), expType);
+ if (elemType != int.class && elemType != boolean.class) {
+ MethodType gtype;
+ if (true) { // FIXME: remove this path (and remove <void> below in the mh.invokes)
+ gtype = mh.type().changeParameterType(0, Object.class);
+ if (testSetter)
+ gtype = gtype.changeParameterType(2, Object.class);
+ else
+ gtype = gtype.changeReturnType(Object.class);
+ } else
+ // FIXME: This simpler path hits a bug in convertArguments => ToGeneric
+ gtype = mh.type().generic().changeParameterType(1, int.class);
+ mh = MethodHandles.convertArguments(mh, gtype);
+ }
+ Object sawValue, expValue;
+ List<Object> model = array2list(array);
+ int length = Array.getLength(array);
+ for (int i = 0; i < length; i++) {
+ // update array element
+ Object random = randomArg(elemType);
+ model.set(i, random);
+ if (testSetter) {
+ if (elemType == int.class)
+ mh.invokeExact((int[]) array, i, (int)random);
+ else if (elemType == boolean.class)
+ mh.invokeExact((boolean[]) array, i, (boolean)random);
+ else
+ mh.invokeExact(array, i, random);
+ assertEquals(model, array2list(array));
+ } else {
+ Array.set(array, i, random);
+ }
+ if (verbosity >= 5) {
+ List<Object> array2list = array2list(array);
+ System.out.println("a["+i+"]="+random+" => "+array2list);
+ if (!array2list.equals(model))
+ System.out.println("*** != "+model);
+ }
+ // observe array element
+ sawValue = Array.get(array, i);
+ if (!testSetter) {
+ expValue = sawValue;
+ if (elemType == int.class)
+ sawValue = (int) mh.invokeExact((int[]) array, i);
+ else if (elemType == boolean.class)
+ sawValue = (boolean) mh.invokeExact((boolean[]) array, i);
+ else
+ sawValue = mh.invokeExact(array, i);
+ assertEquals(sawValue, expValue);
+ assertEquals(model, array2list(array));
+ }
+ }
+ }
+
+ List<Object> array2list(Object array) {
+ int length = Array.getLength(array);
+ ArrayList<Object> model = new ArrayList<Object>(length);
+ for (int i = 0; i < length; i++)
+ model.add(Array.get(array, i));
+ return model;
+ }
+
+ static class Callee {
+ static Object id() { return called("id"); }
+ static Object id(Object x) { return called("id", x); }
+ static Object id(Object x, Object y) { return called("id", x, y); }
+ static Object id(Object x, Object y, Object z) { return called("id", x, y, z); }
+ static Object id(Object... vx) { return called("id", vx); }
+ static MethodHandle ofType(int n) {
+ return ofType(Object.class, n);
+ }
+ static MethodHandle ofType(Class<?> rtype, int n) {
+ if (n == -1)
+ return ofType(MethodType.methodType(rtype, Object[].class));
+ return ofType(MethodType.genericMethodType(n).changeReturnType(rtype));
+ }
+ static MethodHandle ofType(Class<?> rtype, Class<?>... ptypes) {
+ return ofType(MethodType.methodType(rtype, ptypes));
+ }
+ static MethodHandle ofType(MethodType type) {
+ Class<?> rtype = type.returnType();
+ String pfx = "";
+ if (rtype != Object.class)
+ pfx = rtype.getSimpleName().substring(0, 1).toLowerCase();
+ String name = pfx+"id";
+ try {
+ return PRIVATE.findStatic(Callee.class, name, type);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ @Test
+ public void testConvertArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("convertArguments");
+ testConvert(Callee.ofType(1), null, "id", int.class);
+ testConvert(Callee.ofType(1), null, "id", String.class);
+ testConvert(Callee.ofType(1), null, "id", Integer.class);
+ testConvert(Callee.ofType(1), null, "id", short.class);
+ testConvert(Callee.ofType(1), null, "id", char.class);
+ testConvert(Callee.ofType(1), null, "id", byte.class);
+ }
+
+ void testConvert(MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
+ testConvert(true, false, id, rtype, name, params);
+ testConvert(true, true, id, rtype, name, params);
+ }
+
+ void testConvert(boolean positive, boolean useAsType,
+ MethodHandle id, Class<?> rtype, String name, Class<?>... params) throws Throwable {
+ countTest(positive);
+ MethodType idType = id.type();
+ if (rtype == null) rtype = idType.returnType();
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] == null) params[i] = idType.parameterType(i);
+ }
+ // simulate the pairwise conversion
+ MethodType newType = MethodType.methodType(rtype, params);
+ Object[] args = randomArgs(newType.parameterArray());
+ Object[] convArgs = args.clone();
+ for (int i = 0; i < args.length; i++) {
+ Class<?> src = newType.parameterType(i);
+ Class<?> dst = idType.parameterType(i);
+ if (src != dst)
+ convArgs[i] = castToWrapper(convArgs[i], dst);
+ }
+ Object convResult = id.invokeWithArguments(convArgs);
+ {
+ Class<?> dst = newType.returnType();
+ Class<?> src = idType.returnType();
+ if (src != dst)
+ convResult = castToWrapper(convResult, dst);
+ }
+ MethodHandle target = null;
+ RuntimeException error = null;
+ try {
+ if (useAsType)
+ target = id.asType(newType);
+ else
+ target = MethodHandles.convertArguments(id, newType);
+ } catch (RuntimeException ex) {
+ error = ex;
+ }
+ if (verbosity >= 3)
+ System.out.println("convert "+id+ " to "+newType+" => "+target
+ +(error == null ? "" : " !! "+error));
+ if (positive && error != null) throw error;
+ assertEquals(positive ? "positive test" : "negative test erroneously passed", positive, target != null);
+ if (!positive) return; // negative test failed as expected
+ assertEquals(newType, target.type());
+ printCalled(target, id.toString(), args);
+ Object result = target.invokeWithArguments(args);
+ assertCalled(name, convArgs);
+ assertEquals(convResult, result);
+ if (verbosity >= 1)
+ System.out.print(':');
+ }
+
+ @Test
+ public void testVarargsCollector() throws Throwable {
+ MethodHandle vac0 = PRIVATE.findStatic(MethodHandlesTest.class, "called",
+ MethodType.methodType(Object.class, String.class, Object[].class));
+ vac0 = vac0.bindTo("vac");
+ MethodHandle vac = vac0.asVarargsCollector(Object[].class);
+ testConvert(true, true, vac.asType(MethodType.genericMethodType(0)), null, "vac");
+ testConvert(true, true, vac.asType(MethodType.genericMethodType(0)), null, "vac");
+ for (Class<?> at : new Class[] { Object.class, String.class, Integer.class }) {
+ testConvert(true, true, vac.asType(MethodType.genericMethodType(1)), null, "vac", at);
+ testConvert(true, true, vac.asType(MethodType.genericMethodType(2)), null, "vac", at, at);
+ }
+ }
+
+ @Test
+ public void testPermuteArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("permuteArguments");
+ testPermuteArguments(4, Integer.class, 2, String.class, 0);
+ //testPermuteArguments(6, Integer.class, 0, null, 30);
+ //testPermuteArguments(4, Integer.class, 1, int.class, 6);
+ }
+ public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
+ if (verbosity >= 2)
+ System.out.println("permuteArguments "+max+"*"+type1.getName()
+ +(t2c==0?"":"/"+t2c+"*"+type2.getName())
+ +(dilution > 0 ? " with dilution "+dilution : ""));
+ int t2pos = t2c == 0 ? 0 : 1;
+ for (int inargs = t2pos+1; inargs <= max; inargs++) {
+ Class<?>[] types = new Class<?>[inargs];
+ Arrays.fill(types, type1);
+ if (t2c != 0) {
+ // Fill in a middle range with type2:
+ Arrays.fill(types, t2pos, Math.min(t2pos+t2c, inargs), type2);
+ }
+ Object[] args = randomArgs(types);
+ int numcases = 1;
+ for (int outargs = 0; outargs <= max; outargs++) {
+ if (outargs - inargs >= MAX_ARG_INCREASE) continue;
+ int[] reorder = new int[outargs];
+ int casStep = dilution + 1;
+ // Avoid some common factors:
+ while ((casStep > 2 && casStep % 2 == 0 && inargs % 2 == 0) ||
+ (casStep > 3 && casStep % 3 == 0 && inargs % 3 == 0))
+ casStep++;
+ for (int cas = 0; cas < numcases; cas += casStep) {
+ for (int i = 0, c = cas; i < outargs; i++) {
+ reorder[i] = c % inargs;
+ c /= inargs;
+ }
+ testPermuteArguments(args, types, reorder);
+ }
+ numcases *= inargs;
+ if (dilution > 10 && outargs >= 4) {
+ // Do some special patterns, which we probably missed.
+ // Replication of a single argument or argument pair.
+ for (int i = 0; i < inargs; i++) {
+ Arrays.fill(reorder, i);
+ testPermuteArguments(args, types, reorder);
+ for (int d = 1; d <= 2; d++) {
+ if (i + d >= inargs) continue;
+ for (int j = 1; j < outargs; j += 2)
+ reorder[j] += 1;
+ testPermuteArguments(args, types, reorder);
+ testPermuteArguments(args, types, reverse(reorder));
+ }
+ }
+ // Repetition of a sequence of 3 or more arguments.
+ for (int i = 1; i < inargs; i++) {
+ for (int len = 3; len <= inargs; len++) {
+ for (int j = 0; j < outargs; j++)
+ reorder[j] = (i + (j % len)) % inargs;
+ testPermuteArguments(args, types, reorder);
+ testPermuteArguments(args, types, reverse(reorder));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static int[] reverse(int[] reorder) {
+ reorder = reorder.clone();
+ for (int i = 0, imax = reorder.length / 2; i < imax; i++) {
+ int j = reorder.length - 1 - i;
+ int tem = reorder[i];
+ reorder[i] = reorder[j];
+ reorder[j] = tem;
+ }
+ return reorder;
+ }
+
+ void testPermuteArguments(Object[] args, Class<?>[] types, int[] reorder) throws Throwable {
+ countTest();
+ if (args == null && types == null) {
+ int max = 0;
+ for (int j : reorder) {
+ if (max < j) max = j;
+ }
+ args = randomArgs(max+1, Integer.class);
+ }
+ if (args == null) {
+ args = randomArgs(types);
+ }
+ if (types == null) {
+ types = new Class<?>[args.length];
+ for (int i = 0; i < args.length; i++)
+ types[i] = args[i].getClass();
+ }
+ int inargs = args.length, outargs = reorder.length;
+ assertTrue(inargs == types.length);
+ if (verbosity >= 3)
+ System.out.println("permuteArguments "+Arrays.toString(reorder));
+ Object[] permArgs = new Object[outargs];
+ Class<?>[] permTypes = new Class<?>[outargs];
+ for (int i = 0; i < outargs; i++) {
+ permArgs[i] = args[reorder[i]];
+ permTypes[i] = types[reorder[i]];
+ }
+ if (verbosity >= 4) {
+ System.out.println("in args: "+Arrays.asList(args));
+ System.out.println("out args: "+Arrays.asList(permArgs));
+ System.out.println("in types: "+Arrays.asList(types));
+ System.out.println("out types: "+Arrays.asList(permTypes));
+ }
+ MethodType inType = MethodType.methodType(Object.class, types);
+ MethodType outType = MethodType.methodType(Object.class, permTypes);
+ MethodHandle target = MethodHandles.convertArguments(varargsList(outargs), outType);
+ MethodHandle newTarget = MethodHandles.permuteArguments(target, inType, reorder);
+ Object result = newTarget.invokeWithArguments(args);
+ Object expected = Arrays.asList(permArgs);
+ assertEquals(expected, result);
+ }
+
+
+ @Test
+ public void testSpreadArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("spreadArguments");
+ for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
+ if (verbosity >= 3)
+ System.out.println("spreadArguments "+argType);
+ // FIXME: enable _adapter_spread_args and fix Fail_2
+ for (int nargs = 0; nargs < 10; nargs++) {
+ if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1
+ for (int pos = 0; pos < nargs; pos++) {
+ if (argType == int.class && pos > 0) continue; // FIXME Fail_3
+ testSpreadArguments(argType, pos, nargs);
+ }
+ }
+ }
+ }
+ public void testSpreadArguments(Class<?> argType, int pos, int nargs) throws Throwable {
+ countTest();
+ MethodHandle target = varargsArray(nargs);
+ MethodHandle target2 = changeArgTypes(target, argType);
+ if (verbosity >= 3)
+ System.out.println("spread into "+target2+" ["+pos+".."+nargs+"]");
+ Object[] args = randomArgs(target2.type().parameterArray());
+ // make sure the target does what we think it does:
+ if (pos == 0 && nargs < 5) {
+ Object[] check = (Object[]) target.invokeWithArguments(args);
+ assertArrayEquals(args, check);
+ switch (nargs) {
+ case 0:
+ check = (Object[]) target.invokeExact();
+ assertArrayEquals(args, check);
+ break;
+ case 1:
+ check = (Object[]) target.invokeExact(args[0]);
+ assertArrayEquals(args, check);
+ break;
+ case 2:
+ check = (Object[]) target.invokeExact(args[0], args[1]);
+ assertArrayEquals(args, check);
+ break;
+ }
+ }
+ List<Class<?>> newParams = new ArrayList<Class<?>>(target2.type().parameterList());
+ { // modify newParams in place
+ List<Class<?>> spreadParams = newParams.subList(pos, nargs);
+ spreadParams.clear(); spreadParams.add(Object[].class);
+ }
+ MethodType newType = MethodType.methodType(Object.class, newParams);
+ MethodHandle result = target2.asSpreader(Object[].class, nargs-pos).asType(newType);
+ Object[] returnValue;
+ if (pos == 0) {
+ // In the following line, the first cast implies
+ // normal Object return value for the MH call (Object[])->Object,
+ // while the second cast dynamically converts to an Object array.
+ // Such a double cast is typical of MH.invokeExact.
+ returnValue = (Object[]) (Object) result.invokeExact(args);
+ } else {
+ Object[] args1 = Arrays.copyOfRange(args, 0, pos+1);
+ args1[pos] = Arrays.copyOfRange(args, pos, args.length);
+ returnValue = (Object[]) result.invokeWithArguments(args1);
+ }
+ assertArrayEquals(args, returnValue);
+ }
+
+ @Test
+ public void testCollectArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("collectArguments");
+ for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
+ if (verbosity >= 3)
+ System.out.println("collectArguments "+argType);
+ for (int nargs = 0; nargs < 10; nargs++) {
+ for (int pos = 0; pos < nargs; pos++) {
+ if (argType == int.class) continue; // FIXME Fail_4
+ testCollectArguments(argType, pos, nargs);
+ }
+ }
+ }
+ }
+ public void testCollectArguments(Class<?> argType, int pos, int nargs) throws Throwable {
+ countTest();
+ // fake up a MH with the same type as the desired adapter:
+ MethodHandle fake = varargsArray(nargs);
+ fake = changeArgTypes(fake, argType);
+ MethodType newType = fake.type();
+ Object[] args = randomArgs(newType.parameterArray());
+ // here is what should happen:
+ Object[] collectedArgs = Arrays.copyOfRange(args, 0, pos+1);
+ collectedArgs[pos] = Arrays.copyOfRange(args, pos, args.length);
+ // here is the MH which will witness the collected argument tail:
+ MethodHandle target = varargsArray(pos+1);
+ target = changeArgTypes(target, 0, pos, argType);
+ target = changeArgTypes(target, pos, pos+1, Object[].class);
+ if (verbosity >= 3)
+ System.out.println("collect from "+Arrays.asList(args)+" ["+pos+".."+nargs+"]");
+ MethodHandle result = target.asCollector(Object[].class, nargs-pos).asType(newType);
+ Object[] returnValue = (Object[]) result.invokeWithArguments(args);
+// assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
+// returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
+// collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]);
+ assertArrayEquals(collectedArgs, returnValue);
+ }
+
+ @Test
+ public void testInsertArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("insertArguments");
+ for (int nargs = 0; nargs <= 4; nargs++) {
+ for (int ins = 0; ins <= 4; ins++) {
+ if (ins > MAX_ARG_INCREASE) continue; // FIXME Fail_6
+ for (int pos = 0; pos <= nargs; pos++) {
+ testInsertArguments(nargs, pos, ins);
+ }
+ }
+ }
+ }
+
+ void testInsertArguments(int nargs, int pos, int ins) throws Throwable {
+ countTest();
+ MethodHandle target = varargsArray(nargs + ins);
+ Object[] args = randomArgs(target.type().parameterArray());
+ List<Object> resList = Arrays.asList(args);
+ List<Object> argsToPass = new ArrayList<Object>(resList);
+ List<Object> argsToInsert = argsToPass.subList(pos, pos + ins);
+ if (verbosity >= 3)
+ System.out.println("insert: "+argsToInsert+" into "+target);
+ MethodHandle target2 = MethodHandles.insertArguments(target, pos,
+ (Object[]) argsToInsert.toArray());
+ argsToInsert.clear(); // remove from argsToInsert
+ Object res2 = target2.invokeWithArguments(argsToPass);
+ Object res2List = Arrays.asList((Object[])res2);
+ if (verbosity >= 3)
+ System.out.println("result: "+res2List);
+ //if (!resList.equals(res2List))
+ // System.out.println("*** fail at n/p/i = "+nargs+"/"+pos+"/"+ins+": "+resList+" => "+res2List);
+ assertEquals(resList, res2List);
+ }
+
+ @Test
+ public void testFilterReturnValue() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("filterReturnValue");
+ Class<?> classOfVCList = varargsList(1).invokeWithArguments(0).getClass();
+ assertTrue(List.class.isAssignableFrom(classOfVCList));
+ for (int nargs = 0; nargs <= 3; nargs++) {
+ for (Class<?> rtype : new Class[] { Object.class,
+ List.class,
+ int.class,
+ //byte.class, //FIXME: add this
+ //long.class, //FIXME: add this
+ CharSequence.class,
+ String.class }) {
+ testFilterReturnValue(nargs, rtype);
+ }
+ }
+ }
+
+ void testFilterReturnValue(int nargs, Class<?> rtype) throws Throwable {
+ countTest();
+ MethodHandle target = varargsList(nargs, rtype);
+ MethodHandle filter;
+ if (List.class.isAssignableFrom(rtype) || rtype.isAssignableFrom(List.class))
+ filter = varargsList(1); // add another layer of list-ness
+ else
+ filter = MethodHandles.identity(rtype);
+ filter = filter.asType(MethodType.methodType(target.type().returnType(), rtype));
+ Object[] argsToPass = randomArgs(nargs, Object.class);
+ if (verbosity >= 3)
+ System.out.println("filter "+target+" to "+rtype.getSimpleName()+" with "+filter);
+ MethodHandle target2 = MethodHandles.filterReturnValue(target, filter);
+ if (verbosity >= 4)
+ System.out.println("filtered target: "+target2);
+ // Simulate expected effect of filter on return value:
+ Object unfiltered = target.invokeWithArguments(argsToPass);
+ Object expected = filter.invokeWithArguments(unfiltered);
+ if (verbosity >= 4)
+ System.out.println("unfiltered: "+unfiltered+" : "+unfiltered.getClass().getSimpleName());
+ if (verbosity >= 4)
+ System.out.println("expected: "+expected+" : "+expected.getClass().getSimpleName());
+ Object result = target2.invokeWithArguments(argsToPass);
+ if (verbosity >= 3)
+ System.out.println("result: "+result+" : "+result.getClass().getSimpleName());
+ if (!expected.equals(result))
+ System.out.println("*** fail at n/rt = "+nargs+"/"+rtype.getSimpleName()+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void testFilterArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("filterArguments");
+ for (int nargs = 1; nargs <= 6; nargs++) {
+ for (int pos = 0; pos < nargs; pos++) {
+ testFilterArguments(nargs, pos);
+ }
+ }
+ }
+
+ void testFilterArguments(int nargs, int pos) throws Throwable {
+ countTest();
+ MethodHandle target = varargsList(nargs);
+ MethodHandle filter = varargsList(1);
+ filter = MethodHandles.convertArguments(filter, filter.type().generic());
+ Object[] argsToPass = randomArgs(nargs, Object.class);
+ if (verbosity >= 3)
+ System.out.println("filter "+target+" at "+pos+" with "+filter);
+ MethodHandle target2 = MethodHandles.filterArguments(target, pos, filter);
+ // Simulate expected effect of filter on arglist:
+ Object[] filteredArgs = argsToPass.clone();
+ filteredArgs[pos] = filter.invokeExact(filteredArgs[pos]);
+ List<Object> expected = Arrays.asList(filteredArgs);
+ Object result = target2.invokeWithArguments(argsToPass);
+ if (verbosity >= 3)
+ System.out.println("result: "+result);
+ if (!expected.equals(result))
+ System.out.println("*** fail at n/p = "+nargs+"/"+pos+": "+Arrays.asList(argsToPass)+" => "+result+" != "+expected);
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void testFoldArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("foldArguments");
+ for (int nargs = 0; nargs <= 4; nargs++) {
+ for (int fold = 0; fold <= nargs; fold++) {
+ for (int pos = 0; pos <= nargs; pos++) {
+ testFoldArguments(nargs, pos, fold);
+ }
+ }
+ }
+ }
+
+ void testFoldArguments(int nargs, int pos, int fold) throws Throwable {
+ if (pos != 0) return; // can fold only at pos=0 for now
+ countTest();
+ MethodHandle target = varargsList(1 + nargs);
+ MethodHandle combine = varargsList(fold).asType(MethodType.genericMethodType(fold));
+ List<Object> argsToPass = Arrays.asList(randomArgs(nargs, Object.class));
+ if (verbosity >= 3)
+ System.out.println("fold "+target+" with "+combine);
+ MethodHandle target2 = MethodHandles.foldArguments(target, combine);
+ // Simulate expected effect of combiner on arglist:
+ List<Object> expected = new ArrayList<Object>(argsToPass);
+ List<Object> argsToFold = expected.subList(pos, pos + fold);
+ if (verbosity >= 3)
+ System.out.println("fold: "+argsToFold+" into "+target2);
+ Object foldedArgs = combine.invokeWithArguments(argsToFold);
+ argsToFold.add(0, foldedArgs);
+ Object result = target2.invokeWithArguments(argsToPass);
+ if (verbosity >= 3)
+ System.out.println("result: "+result);
+ if (!expected.equals(result))
+ System.out.println("*** fail at n/p/f = "+nargs+"/"+pos+"/"+fold+": "+argsToPass+" => "+result+" != "+expected);
+ assertEquals(expected, result);
+ }
+
+ @Test
+ public void testDropArguments() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("dropArguments");
+ for (int nargs = 0; nargs <= 4; nargs++) {
+ for (int drop = 1; drop <= 4; drop++) {
+ for (int pos = 0; pos <= nargs; pos++) {
+ testDropArguments(nargs, pos, drop);
+ }
+ }
+ }
+ }
+
+ void testDropArguments(int nargs, int pos, int drop) throws Throwable {
+ countTest();
+ MethodHandle target = varargsArray(nargs);
+ Object[] args = randomArgs(target.type().parameterArray());
+ MethodHandle target2 = MethodHandles.dropArguments(target, pos,
+ Collections.nCopies(drop, Object.class).toArray(new Class[0]));
+ List<Object> resList = Arrays.asList(args);
+ List<Object> argsToDrop = new ArrayList<Object>(resList);
+ for (int i = drop; i > 0; i--) {
+ argsToDrop.add(pos, "blort#"+i);
+ }
+ Object res2 = target2.invokeWithArguments(argsToDrop);
+ Object res2List = Arrays.asList((Object[])res2);
+ //if (!resList.equals(res2List))
+ // System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
+ assertEquals(resList, res2List);
+ }
+
+ @Test
+ public void testInvokers() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("exactInvoker, genericInvoker, varargsInvoker, dynamicInvoker");
+ // exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker
+ Set<MethodType> done = new HashSet<MethodType>();
+ for (int i = 0; i <= 6; i++) {
+ MethodType gtype = MethodType.genericMethodType(i);
+ for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
+ for (int j = -1; j < i; j++) {
+ MethodType type = gtype;
+ if (j < 0)
+ type = type.changeReturnType(argType);
+ else if (argType == void.class)
+ continue;
+ else
+ type = type.changeParameterType(j, argType);
+ if (argType.isPrimitive() && j != i-1) continue; // FIXME Fail_5
+ if (done.add(type))
+ testInvokers(type);
+ MethodType vtype = type.changeReturnType(void.class);
+ if (done.add(vtype))
+ testInvokers(vtype);
+ }
+ }
+ }
+ }
+
+ public void testInvokers(MethodType type) throws Throwable {
+ if (verbosity >= 3)
+ System.out.println("test invokers for "+type);
+ int nargs = type.parameterCount();
+ boolean testRetCode = type.returnType() != void.class;
+ MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "invokee",
+ MethodType.genericMethodType(0, true));
+ assertTrue(target.isVarargsCollector());
+ target = target.asType(type);
+ Object[] args = randomArgs(type.parameterArray());
+ List<Object> targetPlusArgs = new ArrayList<Object>(Arrays.asList(args));
+ targetPlusArgs.add(0, target);
+ int code = (Integer) invokee(args);
+ Object log = logEntry("invokee", args);
+ assertEquals(log.hashCode(), code);
+ assertCalled("invokee", args);
+ MethodHandle inv;
+ Object result;
+ // exact invoker
+ countTest();
+ calledLog.clear();
+ inv = MethodHandles.exactInvoker(type);
+ result = inv.invokeWithArguments(targetPlusArgs);
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ // generic invoker
+ countTest();
+ inv = MethodHandles.genericInvoker(type);
+ if (nargs <= 3) {
+ calledLog.clear();
+ switch (nargs) {
+ case 0:
+ result = inv.invokeExact(target);
+ break;
+ case 1:
+ result = inv.invokeExact(target, args[0]);
+ break;
+ case 2:
+ result = inv.invokeExact(target, args[0], args[1]);
+ break;
+ case 3:
+ result = inv.invokeExact(target, args[0], args[1], args[2]);
+ break;
+ }
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+ calledLog.clear();
+ result = inv.invokeWithArguments(targetPlusArgs);
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ // varargs invoker #0
+ calledLog.clear();
+ inv = MethodHandles.spreadInvoker(type, 0);
+ result = inv.invokeExact(target, args);
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ if (nargs >= 1) {
+ // varargs invoker #1
+ calledLog.clear();
+ inv = MethodHandles.spreadInvoker(type, 1);
+ result = inv.invokeExact(target, args[0], Arrays.copyOfRange(args, 1, nargs));
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+ if (nargs >= 2) {
+ // varargs invoker #2
+ calledLog.clear();
+ inv = MethodHandles.spreadInvoker(type, 2);
+ result = inv.invokeExact(target, args[0], args[1], Arrays.copyOfRange(args, 2, nargs));
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+ if (nargs >= 3) {
+ // varargs invoker #3
+ calledLog.clear();
+ inv = MethodHandles.spreadInvoker(type, 3);
+ result = inv.invokeExact(target, args[0], args[1], args[2], Arrays.copyOfRange(args, 3, nargs));
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+ for (int k = 0; k <= nargs; k++) {
+ // varargs invoker #0..N
+ countTest();
+ calledLog.clear();
+ inv = MethodHandles.spreadInvoker(type, k);
+ List<Object> targetPlusVarArgs = new ArrayList<Object>(targetPlusArgs);
+ List<Object> tailList = targetPlusVarArgs.subList(1+k, 1+nargs);
+ Object[] tail = tailList.toArray();
+ tailList.clear(); tailList.add(tail);
+ result = inv.invokeWithArguments(targetPlusVarArgs);
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+
+ // dynamic invoker
+ countTest();
+ CallSite site = new MutableCallSite(type);
+ inv = site.dynamicInvoker();
+
+ // see if we get the result of the original target:
+ try {
+ result = inv.invokeWithArguments(args);
+ assertTrue("should not reach here", false);
+ } catch (IllegalStateException ex) {
+ String msg = ex.getMessage();
+ assertTrue(msg, msg.contains("site"));
+ }
+
+ // set new target after invoker is created, to make sure we track target
+ site.setTarget(target);
+ calledLog.clear();
+ result = inv.invokeWithArguments(args);
+ if (testRetCode) assertEquals(code, result);
+ assertCalled("invokee", args);
+ }
+
+ static Object invokee(Object... args) {
+ return called("invokee", args).hashCode();
+ }
+
+ private static final String MISSING_ARG = "missingArg";
+ static Object targetIfEquals() {
+ return called("targetIfEquals");
+ }
+ static Object fallbackIfNotEquals() {
+ return called("fallbackIfNotEquals");
+ }
+ static Object targetIfEquals(Object x) {
+ assertEquals(x, MISSING_ARG);
+ return called("targetIfEquals", x);
+ }
+ static Object fallbackIfNotEquals(Object x) {
+ assertFalse(x.toString(), x.equals(MISSING_ARG));
+ return called("fallbackIfNotEquals", x);
+ }
+ static Object targetIfEquals(Object x, Object y) {
+ assertEquals(x, y);
+ return called("targetIfEquals", x, y);
+ }
+ static Object fallbackIfNotEquals(Object x, Object y) {
+ assertFalse(x.toString(), x.equals(y));
+ return called("fallbackIfNotEquals", x, y);
+ }
+ static Object targetIfEquals(Object x, Object y, Object z) {
+ assertEquals(x, y);
+ return called("targetIfEquals", x, y, z);
+ }
+ static Object fallbackIfNotEquals(Object x, Object y, Object z) {
+ assertFalse(x.toString(), x.equals(y));
+ return called("fallbackIfNotEquals", x, y, z);
+ }
+
+ @Test
+ public void testGuardWithTest() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("guardWithTest");
+ for (int nargs = 0; nargs <= 3; nargs++) {
+ if (nargs != 2) continue; // FIXME: test more later
+ testGuardWithTest(nargs, Object.class);
+ testGuardWithTest(nargs, String.class);
+ }
+ }
+ void testGuardWithTest(int nargs, Class<?> argClass) throws Throwable {
+ countTest();
+ MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class));
+ MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs));
+ MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs));
+ while (test.type().parameterCount() < nargs)
+ test = MethodHandles.dropArguments(test, test.type().parameterCount()-1, Object.class);
+ while (test.type().parameterCount() > nargs)
+ test = MethodHandles.insertArguments(test, 0, MISSING_ARG);
+ if (argClass != Object.class) {
+ test = changeArgTypes(test, argClass);
+ target = changeArgTypes(target, argClass);
+ fallback = changeArgTypes(fallback, argClass);
+ }
+ MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback);
+ assertEquals(target.type(), mh.type());
+ Object[][] argLists = {
+ { },
+ { "foo" }, { MISSING_ARG },
+ { "foo", "foo" }, { "foo", "bar" },
+ { "foo", "foo", "baz" }, { "foo", "bar", "baz" }
+ };
+ for (Object[] argList : argLists) {
+ if (argList.length != nargs) continue;
+ boolean equals;
+ switch (nargs) {
+ case 0: equals = true; break;
+ case 1: equals = MISSING_ARG.equals(argList[0]); break;
+ default: equals = argList[0].equals(argList[1]); break;
+ }
+ String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
+ if (verbosity >= 3)
+ System.out.println(logEntry(willCall, argList));
+ Object result = mh.invokeWithArguments(argList);
+ assertCalled(willCall, argList);
+ }
+ }
+
+ @Test
+ public void testCatchException() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("catchException");
+ for (int nargs = 2; nargs <= 6; nargs++) {
+ for (int ti = 0; ti <= 1; ti++) {
+ boolean throwIt = (ti != 0);
+ testCatchException(int.class, new ClassCastException("testing"), throwIt, nargs);
+ testCatchException(void.class, new java.io.IOException("testing"), throwIt, nargs);
+ testCatchException(String.class, new LinkageError("testing"), throwIt, nargs);
+ }
+ }
+ }
+
+ private static <T extends Throwable>
+ Object throwOrReturn(Object normal, T exception) throws T {
+ if (exception != null) throw exception;
+ return normal;
+ }
+
+ void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable {
+ countTest();
+ if (verbosity >= 3)
+ System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs);
+ Class<? extends Throwable> exType = thrown.getClass();
+ MethodHandle throwOrReturn
+ = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
+ MethodType.methodType(Object.class, Object.class, Throwable.class));
+ MethodHandle thrower = throwOrReturn.asType(MethodType.genericMethodType(2));
+ while (thrower.type().parameterCount() < nargs)
+ thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class);
+ MethodHandle catcher = varargsList(1+nargs).asType(MethodType.genericMethodType(1+nargs));
+ MethodHandle target = MethodHandles.catchException(thrower,
+ thrown.getClass(), catcher);
+ assertEquals(thrower.type(), target.type());
+ //System.out.println("catching with "+target+" : "+throwOrReturn);
+ Object[] args = randomArgs(nargs, Object.class);
+ args[1] = (throwIt ? thrown : null);
+ Object returned = target.invokeWithArguments(args);
+ //System.out.println("return from "+target+" : "+returned);
+ if (!throwIt) {
+ assertSame(args[0], returned);
+ } else {
+ List<Object> catchArgs = new ArrayList<Object>(Arrays.asList(args));
+ catchArgs.add(0, thrown);
+ assertEquals(catchArgs, returned);
+ }
+ }
+
+ @Test
+ public void testThrowException() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("throwException");
+ testThrowException(int.class, new ClassCastException("testing"));
+ testThrowException(void.class, new java.io.IOException("testing"));
+ testThrowException(String.class, new LinkageError("testing"));
+ }
+
+ void testThrowException(Class<?> returnType, Throwable thrown) throws Throwable {
+ countTest();
+ Class<? extends Throwable> exType = thrown.getClass();
+ MethodHandle target = MethodHandles.throwException(returnType, exType);
+ //System.out.println("throwing with "+target+" : "+thrown);
+ MethodType expectedType = MethodType.methodType(returnType, exType);
+ assertEquals(expectedType, target.type());
+ target = MethodHandles.convertArguments(target, target.type().generic());
+ Throwable caught = null;
+ try {
+ Object res = target.invokeExact((Object) thrown);
+ fail("got "+res+" instead of throwing "+thrown);
+ } catch (Throwable ex) {
+ if (ex != thrown) {
+ if (ex instanceof Error) throw (Error)ex;
+ if (ex instanceof RuntimeException) throw (RuntimeException)ex;
+ }
+ caught = ex;
+ }
+ assertSame(thrown, caught);
+ }
+
+ @Test
+ public void testCastFailure() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("testCastFailure");
+ testCastFailure("cast/argument", 11000);
+ testCastFailure("unbox/argument", 11000);
+ testCastFailure("cast/return", 11000);
+ testCastFailure("unbox/return", 11000);
+ }
+
+ static class Surprise {
+ public MethodHandle asMethodHandle() {
+ return VALUE.bindTo(this);
+ }
+ Object value(Object x) {
+ trace("value", x);
+ if (boo != null) return boo;
+ return x;
+ }
+ Object boo;
+ void boo(Object x) { boo = x; }
+
+ static void trace(String x, Object y) {
+ if (verbosity > 8) System.out.println(x+"="+y);
+ }
+ static Object refIdentity(Object x) { trace("ref.x", x); return x; }
+ static Integer boxIdentity(Integer x) { trace("box.x", x); return x; }
+ static int intIdentity(int x) { trace("int.x", x); return x; }
+ static MethodHandle VALUE, REF_IDENTITY, BOX_IDENTITY, INT_IDENTITY;
+ static {
+ try {
+ VALUE = PRIVATE.findVirtual(
+ Surprise.class, "value",
+ MethodType.methodType(Object.class, Object.class));
+ REF_IDENTITY = PRIVATE.findStatic(
+ Surprise.class, "refIdentity",
+ MethodType.methodType(Object.class, Object.class));
+ BOX_IDENTITY = PRIVATE.findStatic(
+ Surprise.class, "boxIdentity",
+ MethodType.methodType(Integer.class, Integer.class));
+ INT_IDENTITY = PRIVATE.findStatic(
+ Surprise.class, "intIdentity",
+ MethodType.methodType(int.class, int.class));
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ void testCastFailure(String mode, int okCount) throws Throwable {
+ countTest(false);
+ if (verbosity > 2) System.out.println("mode="+mode);
+ Surprise boo = new Surprise();
+ MethodHandle identity = Surprise.REF_IDENTITY, surprise0 = boo.asMethodHandle(), surprise = surprise0;
+ if (mode.endsWith("/return")) {
+ if (mode.equals("unbox/return")) {
+ // fail on return to ((Integer)surprise).intValue
+ surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(int.class, Object.class));
+ identity = MethodHandles.convertArguments(identity, MethodType.methodType(int.class, Object.class));
+ } else if (mode.equals("cast/return")) {
+ // fail on return to (Integer)surprise
+ surprise = MethodHandles.convertArguments(surprise, MethodType.methodType(Integer.class, Object.class));
+ identity = MethodHandles.convertArguments(identity, MethodType.methodType(Integer.class, Object.class));
+ }
+ } else if (mode.endsWith("/argument")) {
+ MethodHandle callee = null;
+ if (mode.equals("unbox/argument")) {
+ // fail on handing surprise to int argument
+ callee = Surprise.INT_IDENTITY;
+ } else if (mode.equals("cast/argument")) {
+ // fail on handing surprise to Integer argument
+ callee = Surprise.BOX_IDENTITY;
+ }
+ if (callee != null) {
+ callee = MethodHandles.convertArguments(callee, MethodType.genericMethodType(1));
+ surprise = MethodHandles.filterArguments(callee, 0, surprise);
+ identity = MethodHandles.filterArguments(callee, 0, identity);
+ }
+ }
+ assertNotSame(mode, surprise, surprise0);
+ identity = MethodHandles.convertArguments(identity, MethodType.genericMethodType(1));
+ surprise = MethodHandles.convertArguments(surprise, MethodType.genericMethodType(1));
+ Object x = 42;
+ for (int i = 0; i < okCount; i++) {
+ Object y = identity.invokeExact(x);
+ assertEquals(x, y);
+ Object z = surprise.invokeExact(x);
+ assertEquals(x, z);
+ }
+ boo.boo("Boo!");
+ Object y = identity.invokeExact(x);
+ assertEquals(x, y);
+ try {
+ Object z = surprise.invokeExact(x);
+ System.out.println("Failed to throw; got z="+z);
+ assertTrue(false);
+ } catch (Exception ex) {
+ if (verbosity > 2)
+ System.out.println("caught "+ex);
+ if (verbosity > 3)
+ ex.printStackTrace();
+ assertTrue(ex instanceof ClassCastException
+ // FIXME: accept only one of the two for any given unit test
+ || ex instanceof WrongMethodTypeException
+ );
+ }
+ }
+
+ static Example userMethod(Object o, String s, int i) {
+ called("userMethod", o, s, i);
+ return null;
+ }
+
+ @Test
+ public void testUserClassInSignature() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ startTest("testUserClassInSignature");
+ Lookup lookup = MethodHandles.lookup();
+ String name; MethodType mt; MethodHandle mh;
+ Object[] args;
+
+ // Try a static method.
+ name = "userMethod";
+ mt = MethodType.methodType(Example.class, Object.class, String.class, int.class);
+ mh = lookup.findStatic(lookup.lookupClass(), name, mt);
+ assertEquals(mt, mh.type());
+ assertEquals(Example.class, mh.type().returnType());
+ args = randomArgs(mh.type().parameterArray());
+ mh.invokeWithArguments(args);
+ assertCalled(name, args);
+
+ // Try a virtual method.
+ name = "v2";
+ mt = MethodType.methodType(Object.class, Object.class, int.class);
+ mh = lookup.findVirtual(Example.class, name, mt);
+ assertEquals(mt, mh.type().dropParameterTypes(0,1));
+ assertTrue(mh.type().parameterList().contains(Example.class));
+ args = randomArgs(mh.type().parameterArray());
+ mh.invokeWithArguments(args);
+ assertCalled(name, args);
+ }
+
+ static void runForRunnable() {
+ called("runForRunnable");
+ }
+ private interface Fooable {
+ Object foo(Fooable x, Object y);
+ // this is for randomArg:
+ public class Impl implements Fooable {
+ public Object foo(Fooable x, Object y) {
+ throw new RuntimeException("do not call");
+ }
+ final String name;
+ public Impl() { name = "Fooable#"+nextArg(); }
+ @Override public String toString() { return name; }
+ }
+ }
+ static Object fooForFooable(Fooable x, Object y) {
+ return called("fooForFooable", x, y);
+ }
+ private static class MyCheckedException extends Exception {
+ }
+ private interface WillThrow {
+ void willThrow() throws MyCheckedException;
+ }
+
+ @Test
+ public void testAsInstance() throws Throwable {
+ if (CAN_SKIP_WORKING) return;
+ Lookup lookup = MethodHandles.lookup();
+ {
+ MethodType mt = MethodType.methodType(void.class);
+ MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt);
+ Runnable proxy = MethodHandles.asInstance(mh, Runnable.class);
+ proxy.run();
+ assertCalled("runForRunnable");
+ }
+ {
+ MethodType mt = MethodType.methodType(Object.class, Fooable.class, Object.class);
+ MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable", mt);
+ Fooable proxy = MethodHandles.asInstance(mh, Fooable.class);
+ Object[] args = randomArgs(mt.parameterArray());
+ Object result = proxy.foo((Fooable) args[0], args[1]);
+ assertCalled("fooForFooable", args);
+ assertEquals(result, logEntry("fooForFooable", args));
+ }
+ for (Throwable ex : new Throwable[] { new NullPointerException("ok"),
+ new InternalError("ok"),
+ new Throwable("fail"),
+ new Exception("fail"),
+ new MyCheckedException()
+ }) {
+ MethodHandle mh = MethodHandles.throwException(void.class, Throwable.class);
+ mh = MethodHandles.insertArguments(mh, 0, ex);
+ WillThrow proxy = MethodHandles.asInstance(mh, WillThrow.class);
+ try {
+ proxy.willThrow();
+ System.out.println("Failed to throw: "+ex);
+ assertTrue(false);
+ } catch (Throwable ex1) {
+ if (verbosity > 2) {
+ System.out.println("throw "+ex);
+ System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1));
+ }
+ if (ex instanceof RuntimeException ||
+ ex instanceof Error) {
+ assertSame("must pass unchecked exception out without wrapping", ex, ex1);
+ } else if (ex instanceof MyCheckedException) {
+ assertSame("must pass declared exception out without wrapping", ex, ex1);
+ } else {
+ assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1);
+ UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1;
+ assertSame(ex, utex.getCause());
+ }
+ }
+ }
+ // Test error checking:
+ for (Class<?> nonSAM : new Class[] { Object.class,
+ String.class,
+ CharSequence.class,
+ Example.class }) {
+ try {
+ MethodHandles.asInstance(varargsArray(0), nonSAM);
+ System.out.println("Failed to throw");
+ assertTrue(false);
+ } catch (IllegalArgumentException ex) {
+ }
+ }
+ }
+}
+// Local abbreviated copy of sun.invoke.util.ValueConversions
+class ValueConversions {
+ private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
+ private static final Object[] NO_ARGS_ARRAY = {};
+ private static Object[] makeArray(Object... args) { return args; }
+ private static Object[] array() { return NO_ARGS_ARRAY; }
+ private static Object[] array(Object a0)
+ { return makeArray(a0); }
+ private static Object[] array(Object a0, Object a1)
+ { return makeArray(a0, a1); }
+ private static Object[] array(Object a0, Object a1, Object a2)
+ { return makeArray(a0, a1, a2); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3)
+ { return makeArray(a0, a1, a2, a3); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4)
+ { return makeArray(a0, a1, a2, a3, a4); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5)
+ { return makeArray(a0, a1, a2, a3, a4, a5); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6)
+ { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7)
+ { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8)
+ { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ private static Object[] array(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9)
+ { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ static MethodHandle[] makeArrays() {
+ ArrayList<MethodHandle> arrays = new ArrayList<MethodHandle>();
+ MethodHandles.Lookup lookup = IMPL_LOOKUP;
+ for (;;) {
+ int nargs = arrays.size();
+ MethodType type = MethodType.genericMethodType(nargs).changeReturnType(Object[].class);
+ String name = "array";
+ MethodHandle array = null;
+ try {
+ array = lookup.findStatic(ValueConversions.class, name, type);
+ } catch (ReflectiveOperationException ex) {
+ // break from loop!
+ }
+ if (array == null) break;
+ arrays.add(array);
+ }
+ assertTrue(arrays.size() == 11); // current number of methods
+ return arrays.toArray(new MethodHandle[0]);
+ }
+ static final MethodHandle[] ARRAYS = makeArrays();
+
+ /** Return a method handle that takes the indicated number of Object
+ * arguments and returns an Object array of them, as if for varargs.
+ */
+ public static MethodHandle varargsArray(int nargs) {
+ if (nargs < ARRAYS.length)
+ return ARRAYS[nargs];
+ // else need to spin bytecode or do something else fancy
+ throw new UnsupportedOperationException("NYI: cannot form a varargs array of length "+nargs);
+ }
+
+ private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
+ private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
+ private static List<Object> list() { return NO_ARGS_LIST; }
+ private static List<Object> list(Object a0)
+ { return makeList(a0); }
+ private static List<Object> list(Object a0, Object a1)
+ { return makeList(a0, a1); }
+ private static List<Object> list(Object a0, Object a1, Object a2)
+ { return makeList(a0, a1, a2); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
+ { return makeList(a0, a1, a2, a3); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4)
+ { return makeList(a0, a1, a2, a3, a4); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5)
+ { return makeList(a0, a1, a2, a3, a4, a5); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6)
+ { return makeList(a0, a1, a2, a3, a4, a5, a6); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7)
+ { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8)
+ { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
+ private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
+ Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9)
+ { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
+ static MethodHandle[] makeLists() {
+ ArrayList<MethodHandle> lists = new ArrayList<MethodHandle>();
+ MethodHandles.Lookup lookup = IMPL_LOOKUP;
+ for (;;) {
+ int nargs = lists.size();
+ MethodType type = MethodType.genericMethodType(nargs).changeReturnType(List.class);
+ String name = "list";
+ MethodHandle list = null;
+ try {
+ list = lookup.findStatic(ValueConversions.class, name, type);
+ } catch (ReflectiveOperationException ex) {
+ // break from loop!
+ }
+ if (list == null) break;
+ lists.add(list);
+ }
+ assertTrue(lists.size() == 11); // current number of methods
+ return lists.toArray(new MethodHandle[0]);
+ }
+ static final MethodHandle[] LISTS = makeLists();
+
+ /** Return a method handle that takes the indicated number of Object
+ * arguments and returns List.
+ */
+ public static MethodHandle varargsList(int nargs) {
+ if (nargs < LISTS.length)
+ return LISTS[nargs];
+ // else need to spin bytecode or do something else fancy
+ throw new UnsupportedOperationException("NYI");
+ }
+}
+// This guy tests access from outside the same package member, but inside
+// the package itself.
+class PackageSibling {
+ static Lookup lookup() {
+ return MethodHandles.lookup();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/MethodTypeTest.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,567 @@
+/*
+ * Copyright 2008, 2011 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @summary unit tests for java.lang.invoke.MethodType
+ * @compile MethodTypeTest.java
+ * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.lang.invoke.MethodTypeTest
+ */
+
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+
+import java.util.*;
+import org.junit.*;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author jrose
+ */
+public class MethodTypeTest {
+
+ private Class<?> rtype;
+ private Class<?>[] ptypes;
+ private MethodType mt_viS, mt_OO, mt_OO2, mt_vv, mt_Vv, mt_Ov;
+ private MethodType mt_iSI, mt_ISi, mt_ISI, mt_iSi;
+ private MethodType mt_viO, mt_iO2, mt_OOi, mt_iOi;
+ private MethodType mt_VIO, mt_IO2, mt_OOI, mt_IOI, mt_VIS;
+ private MethodType mt_vOiSzA, mt_OO99;
+ private MethodType[] GALLERY;
+ private Method compareTo;
+
+ @Before
+ public void setUp() throws Exception {
+ rtype = void.class;
+ ptypes = new Class<?>[] { int.class, String.class };
+
+ mt_viS = MethodType.methodType(void.class, int.class, String.class);
+ mt_OO = MethodType.methodType(Object.class, Object.class);
+ mt_OO2 = MethodType.methodType(Object.class, Object.class, Object.class);
+ mt_vv = MethodType.methodType(void.class);
+ mt_Vv = MethodType.methodType(Void.class);
+ mt_Ov = MethodType.methodType(Object.class);
+ mt_iSI = MethodType.methodType(int.class, String.class, Integer.class);
+ mt_ISi = MethodType.methodType(Integer.class, String.class, int.class);
+ mt_ISI = MethodType.methodType(Integer.class, String.class, Integer.class);
+ mt_iSi = MethodType.methodType(int.class, String.class, int.class);
+
+ compareTo = String.class.getDeclaredMethod("compareTo", String.class);
+
+ mt_viO = MethodType.methodType(void.class, int.class, Object.class);
+ mt_iO2 = MethodType.methodType(int.class, Object.class, Object.class);
+ mt_OOi = MethodType.methodType(Object.class, Object.class, int.class);
+ mt_iOi = MethodType.methodType(int.class, Object.class, int.class);
+
+ mt_VIO = MethodType.methodType(Void.class, Integer.class, Object.class);
+ mt_IO2 = MethodType.methodType(Integer.class, Object.class, Object.class);
+ mt_OOI = MethodType.methodType(Object.class, Object.class, Integer.class);
+ mt_IOI = MethodType.methodType(Integer.class, Object.class, Integer.class);
+ mt_VIS = MethodType.methodType(Void.class, Integer.class, String.class);
+
+ mt_vOiSzA = MethodType.methodType(void.class, Object.class, int.class, String.class, boolean.class, Object[].class);
+ mt_OO99 = MethodType.genericMethodType(99);
+
+ GALLERY = new MethodType[] {
+ mt_viS, mt_OO, mt_OO2, mt_vv, mt_Vv, mt_Ov,
+ mt_iSI, mt_ISi, mt_ISI, mt_iSi,
+ mt_viO, mt_iO2, mt_OOi, mt_iOi,
+ mt_VIO, mt_IO2, mt_OOI, mt_IOI,
+ mt_VIS, mt_vOiSzA, mt_OO99
+ };
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ /** Make sure the method types are all distinct. */
+ @Test
+ public void testDistinct() {
+ List<MethodType> gallery2 = new ArrayList<>();
+ for (MethodType mt : GALLERY) {
+ assertFalse(mt.toString(), gallery2.contains(mt));
+ gallery2.add(mt);
+ }
+ // check self-equality also:
+ assertEquals(Arrays.asList(GALLERY), gallery2);
+ }
+
+ /**
+ * Test of make method, of class MethodType.
+ */
+ @Test
+ public void testMake_Class_ClassArr() {
+ System.out.println("make (from type array)");
+ MethodType result = MethodType.methodType(rtype, ptypes);
+ assertSame(mt_viS, result);
+ }
+
+ /**
+ * Test of make method, of class MethodType.
+ */
+ @Test
+ public void testMake_Class_List() {
+ System.out.println("make (from type list)");
+ MethodType result = MethodType.methodType(rtype, Arrays.asList(ptypes));
+ assertSame(mt_viS, result);
+ }
+
+ /**
+ * Test of make method, of class MethodType.
+ */
+ @Test
+ public void testMake_3args() {
+ System.out.println("make (from type with varargs)");
+ MethodType result = MethodType.methodType(rtype, ptypes[0], ptypes[1]);
+ assertSame(mt_viS, result);
+ }
+
+ /**
+ * Test of make method, of class MethodType.
+ */
+ @Test
+ public void testMake_Class() {
+ System.out.println("make (from single type)");
+ Class<?> rt = Integer.class;
+ MethodType expResult = MethodType.methodType(rt, new Class<?>[0]);
+ MethodType result = MethodType.methodType(rt);
+ assertSame(expResult, result);
+ }
+
+ @Test
+ public void testMakeGeneric() {
+ System.out.println("makeGeneric");
+ int objectArgCount = 2;
+ MethodType expResult = mt_OO2;
+ MethodType result = MethodType.genericMethodType(objectArgCount);
+ assertSame(expResult, result);
+ }
+
+ /**
+ * Test of make method, of class MethodType.
+ */
+ @Test
+ public void testMake_MethodType() {
+ System.out.println("make (from rtype, MethodType)");
+ MethodType expResult = mt_iO2;
+ MethodType result = MethodType.methodType(int.class, mt_IO2);
+ assertSame(expResult, result);
+ }
+
+ /**
+ * Test of make method, of class MethodType.
+ */
+ @Test
+ public void testMake_String_ClassLoader() {
+ System.out.println("make (from bytecode signature)");
+ ClassLoader loader = null;
+ MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+ String obj = "Ljava/lang/Object;";
+ assertEquals(obj, concat(Object.class));
+ String[] expResults = {
+ "(ILjava/lang/String;)V",
+ concat("(", obj, 2, ")", Object.class),
+ "()V", "()"+obj,
+ concat("(", String.class, Integer.class, ")I"),
+ concat("(", String.class, "I)", Integer.class),
+ concat("(", String.class, Integer.class, ")", Integer.class),
+ concat("(", String.class, "I)I")
+ };
+ for (int i = 0; i < instances.length; i++) {
+ MethodType instance = instances[i];
+ String result = instance.toMethodDescriptorString();
+ assertEquals("#"+i, expResults[i], result);
+ MethodType parsed = MethodType.fromMethodDescriptorString(result, loader);
+ assertSame("--#"+i, instance, parsed);
+ }
+ }
+ private static String concat(Object... parts) {
+ StringBuilder sb = new StringBuilder();
+ Object prevPart = "";
+ for (Object part : parts) {
+ if (part instanceof Class) {
+ part = "L"+((Class)part).getName()+";";
+ }
+ if (part instanceof Integer) {
+ for (int n = (Integer) part; n > 1; n--)
+ sb.append(prevPart);
+ part = "";
+ }
+ sb.append(part);
+ prevPart = part;
+ }
+ return sb.toString().replace('.', '/');
+ }
+
+ @Test
+ public void testHasPrimitives() {
+ System.out.println("hasPrimitives");
+ MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+ boolean[] expResults = {true, false, true, false, true, true, false, true};
+ for (int i = 0; i < instances.length; i++) {
+ boolean result = instances[i].hasPrimitives();
+ assertEquals("#"+i, expResults[i], result);
+ }
+ }
+
+ @Test
+ public void testHasWrappers() {
+ System.out.println("hasWrappers");
+ MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+ boolean[] expResults = {false, false, false, false, true, true, true, false};
+ for (int i = 0; i < instances.length; i++) {
+ System.out.println(" hasWrappers "+instances[i]);
+ boolean result = instances[i].hasWrappers();
+ assertEquals("#"+i, expResults[i], result);
+ }
+ }
+
+ @Test
+ public void testErase() {
+ System.out.println("erase");
+ MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+ MethodType[] expResults = {mt_viO, mt_OO2, mt_vv, mt_Ov, mt_iO2, mt_OOi, mt_OO2, mt_iOi};
+ for (int i = 0; i < instances.length; i++) {
+ MethodType result = instances[i].erase();
+ assertSame("#"+i, expResults[i], result);
+ }
+ }
+
+ @Test
+ public void testGeneric() {
+ System.out.println("generic");
+ MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+ MethodType[] expResults = {mt_OO2, mt_OO2, mt_Ov, mt_Ov, mt_OO2, mt_OO2, mt_OO2, mt_OO2};
+ for (int i = 0; i < instances.length; i++) {
+ MethodType result = instances[i].generic();
+ assertSame("#"+i, expResults[i], result);
+ }
+ }
+
+ @Test
+ public void testWrap() {
+ System.out.println("wrap");
+ MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+ MethodType[] expResults = {mt_VIS, mt_OO2, mt_Vv, mt_Ov, mt_ISI, mt_ISI, mt_ISI, mt_ISI};
+ for (int i = 0; i < instances.length; i++) {
+ MethodType result = instances[i].wrap();
+ assertSame("#"+i, expResults[i], result);
+ }
+ }
+
+ @Test
+ public void testUnwrap() {
+ System.out.println("unwrap");
+ MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+ MethodType[] expResults = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSi, mt_iSi, mt_iSi, mt_iSi};
+ for (int i = 0; i < instances.length; i++) {
+ MethodType result = instances[i].unwrap();
+ assertSame("#"+i, expResults[i], result);
+ }
+ }
+
+ /**
+ * Test of parameterType method, of class MethodType.
+ */
+ @Test
+ public void testParameterType() {
+ System.out.println("parameterType");
+ for (int num = 0; num < ptypes.length; num++) {
+ MethodType instance = mt_viS;
+ Class<?> expResult = ptypes[num];
+ Class<?> result = instance.parameterType(num);
+ assertSame(expResult, result);
+ }
+ }
+
+ /**
+ * Test of parameterCount method, of class MethodType.
+ */
+ @Test
+ public void testParameterCount() {
+ System.out.println("parameterCount");
+ MethodType instance = mt_viS;
+ int expResult = 2;
+ int result = instance.parameterCount();
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of returnType method, of class MethodType.
+ */
+ @Test
+ public void testReturnType() {
+ System.out.println("returnType");
+ MethodType instance = mt_viS;
+ Class<?> expResult = void.class;
+ Class<?> result = instance.returnType();
+ assertSame(expResult, result);
+ }
+
+ /**
+ * Test of parameterList method, of class MethodType.
+ */
+ @Test
+ public void testParameterList() {
+ System.out.println("parameterList");
+ MethodType instance = mt_viS;
+ List<Class<?>> expResult = Arrays.asList(ptypes);
+ List<Class<?>> result = instance.parameterList();
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of parameterArray method, of class MethodType.
+ */
+ @Test
+ public void testParameterArray() {
+ System.out.println("parameterArray");
+ MethodType instance = mt_viS;
+ Class<?>[] expResult = ptypes;
+ Class<?>[] result = instance.parameterArray();
+ assertEquals(Arrays.asList(expResult), Arrays.asList(result));
+ }
+
+ /**
+ * Test of equals method, of class MethodType.
+ */
+ @Test
+ public void testEquals_Object() {
+ System.out.println("equals");
+ Object x = null;
+ MethodType instance = mt_viS;
+ boolean expResult = false;
+ boolean result = instance.equals(x);
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of equals method, of class MethodType.
+ */
+ @Test
+ public void testEquals_MethodType() {
+ System.out.println("equals");
+ MethodType that = mt_viS;
+ MethodType instance = mt_viS;
+ boolean expResult = true;
+ boolean result = instance.equals(that);
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of hashCode method, of class MethodType.
+ */
+ @Test
+ public void testHashCode() {
+ System.out.println("hashCode");
+ MethodType instance = mt_viS;
+ ArrayList<Class<?>> types = new ArrayList<Class<?>>();
+ types.add(instance.returnType());
+ types.addAll(instance.parameterList());
+ int expResult = types.hashCode();
+ int result = instance.hashCode();
+ assertEquals(expResult, result);
+ }
+
+ /**
+ * Test of toString method, of class MethodType.
+ */
+ @Test
+ public void testToString() {
+ System.out.println("toString");
+ MethodType[] instances = {mt_viS, mt_OO2, mt_vv, mt_Ov, mt_iSI, mt_ISi, mt_ISI, mt_iSi};
+ //String expResult = "void[int, class java.lang.String]";
+ String[] expResults = {
+ "(int,String)void",
+ "(Object,Object)Object",
+ "()void",
+ "()Object",
+ "(String,Integer)int",
+ "(String,int)Integer",
+ "(String,Integer)Integer",
+ "(String,int)int"
+ };
+ for (int i = 0; i < instances.length; i++) {
+ MethodType instance = instances[i];
+ String result = instance.toString();
+ System.out.println("#"+i+":"+result);
+ assertEquals("#"+i, expResults[i], result);
+ }
+ }
+
+ private static byte[] writeSerial(Object x) throws java.io.IOException {
+ try (java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
+ java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(bout)
+ ) {
+ out.writeObject(x);
+ out.flush();
+ return bout.toByteArray();
+ }
+ }
+ private static Object readSerial(byte[] wire) throws java.io.IOException, ClassNotFoundException {
+ try (java.io.ByteArrayInputStream bin = new java.io.ByteArrayInputStream(wire);
+ java.io.ObjectInputStream in = new java.io.ObjectInputStream(bin)) {
+ return in.readObject();
+ }
+ }
+ private static void testSerializedEquality(Object x) throws java.io.IOException, ClassNotFoundException {
+ if (x instanceof Object[])
+ x = Arrays.asList((Object[]) x); // has proper equals method
+ byte[] wire = writeSerial(x);
+ Object y = readSerial(wire);
+ assertEquals(x, y);
+ }
+
+ /** Test (de-)serialization. */
+ @Test
+ public void testSerialization() throws Throwable {
+ System.out.println("serialization");
+ for (MethodType mt : GALLERY) {
+ testSerializedEquality(mt);
+ }
+ testSerializedEquality(GALLERY);
+
+ // Make a list of mixed objects:
+ List<Object> stuff = new ArrayList<>();
+ Collections.addAll(stuff, GALLERY); // copy #1
+ Object[] triples = Arrays.copyOfRange(GALLERY, 0, GALLERY.length/2);
+ Collections.addAll(stuff, triples); // copy #3 (partial)
+ for (MethodType mt : GALLERY) {
+ Collections.addAll(stuff, mt.parameterArray());
+ }
+ Collections.shuffle(stuff, new Random(292));
+ Collections.addAll(stuff, GALLERY); // copy #2
+ testSerializedEquality(stuff);
+ }
+
+ /** Test serialization formats. */
+ @Test
+ public void testPortableSerialFormat() throws Throwable {
+ System.out.println("portable serial format");
+ boolean generateData = false;
+ //generateData = true; // set this true to generate the following input data:
+ Object[][] cases = {
+ { mt_vv, new byte[] { // ()void
+ (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
+ (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
+ (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+ (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x6f, (byte)0x69, (byte)0x64,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00,
+ (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e,
+ (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61,
+ (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab, (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb,
+ (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
+ } },
+ { mt_OO, new byte[] { // (Object)Object
+ (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
+ (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
+ (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+ (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61,
+ (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62,
+ (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
+ (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00, (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a,
+ (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67,
+ (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61, (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab,
+ (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb, (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02,
+ (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01,
+ (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x03, (byte)0x78,
+ } },
+ { mt_vOiSzA, new byte[] { // (Object,int,String,boolean,Object[])void
+ (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x1b,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x69, (byte)0x6e, (byte)0x76, (byte)0x6f, (byte)0x6b, (byte)0x65,
+ (byte)0x2e, (byte)0x4d, (byte)0x65, (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x54,
+ (byte)0x79, (byte)0x70, (byte)0x65, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x01, (byte)0x24, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+ (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x6f, (byte)0x69, (byte)0x64,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00,
+ (byte)0x12, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e,
+ (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x43, (byte)0x6c, (byte)0x61,
+ (byte)0x73, (byte)0x73, (byte)0x3b, (byte)0xab, (byte)0x16, (byte)0xd7, (byte)0xae, (byte)0xcb,
+ (byte)0xcd, (byte)0x5a, (byte)0x99, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62, (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00,
+ (byte)0x03, (byte)0x69, (byte)0x6e, (byte)0x74, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78,
+ (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76,
+ (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x53,
+ (byte)0x74, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x67, (byte)0xa0, (byte)0xf0, (byte)0xa4,
+ (byte)0x38, (byte)0x7a, (byte)0x3b, (byte)0xb3, (byte)0x42, (byte)0x02, (byte)0x00, (byte)0x00,
+ (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x07, (byte)0x62, (byte)0x6f,
+ (byte)0x6f, (byte)0x6c, (byte)0x65, (byte)0x61, (byte)0x6e, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x78, (byte)0x70, (byte)0x76, (byte)0x72, (byte)0x00, (byte)0x13, (byte)0x5b, (byte)0x4c,
+ (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e,
+ (byte)0x67, (byte)0x2e, (byte)0x4f, (byte)0x62, (byte)0x6a, (byte)0x65, (byte)0x63, (byte)0x74,
+ (byte)0x3b, (byte)0x90, (byte)0xce, (byte)0x58, (byte)0x9f, (byte)0x10, (byte)0x73, (byte)0x29,
+ (byte)0x6c, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, (byte)0x78,
+ } },
+ };
+ for (Object[] c : cases) {
+ MethodType mt = (MethodType) c[0];
+ System.out.println("deserialize "+mt);
+ byte[] wire = (byte[]) c[1];
+ if (generateData) {
+ System.out.println("<generateData>");
+ wire = writeSerial(mt);
+ final String INDENT = " ";
+ System.out.print("{ // "+mt);
+ for (int i = 0; i < wire.length; i++) {
+ if (i % 8 == 0) { System.out.println(); System.out.print(INDENT+" "); }
+ String hex = Integer.toHexString(wire[i] & 0xFF);
+ if (hex.length() == 1) hex = "0"+hex;
+ System.out.print(" (byte)0x"+hex+",");
+ }
+ System.out.println();
+ System.out.println(INDENT+"}");
+ System.out.println("</generateData>");
+ System.out.flush();
+ }
+ Object decode;
+ try {
+ decode = readSerial(wire);
+ } catch (Exception ex) {
+ decode = ex; // oops!
+ }
+ assertEquals(mt, decode);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/indify/Indify.java Wed Mar 23 23:02:31 2011 -0700
@@ -0,0 +1,1906 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package indify;
+
+import java.util.*;
+import java.io.*;
+import java.lang.reflect.Modifier;
+import java.util.regex.*;
+
+/**
+ * Transform one or more class files to incorporate JSR 292 features,
+ * such as {@code invokedynamic}.
+ * <p>
+ * This is a standalone program in a single source file.
+ * In this form, it may be useful for test harnesses, small experiments, and javadoc examples.
+ * Copies of this file may show up in multiple locations for standalone usage.
+ * The primary maintained location of this file is as follows:
+ * <a href="http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java">
+ * http://kenai.com/projects/ninja/sources/indify-repo/content/src/indify/Indify.java</a>
+ * <p>
+ * Static private methods named MH_x and MT_x (where x is arbitrary)
+ * must be stereotyped generators of MethodHandle and MethodType
+ * constants. All calls to them are transformed to {@code CONSTANT_MethodHandle}
+ * and {@code CONSTANT_MethodType} "ldc" instructions.
+ * The stereotyped code must create method types by calls to {@code methodType} or
+ * {@code fromMethodDescriptorString}. The "lookup" argument must be created
+ * by calls to {@code java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
+ * The class and string arguments must be constant.
+ * The following methods of {@code java.lang.invoke.MethodHandle.Lookup Lookup} are
+ * allowed for method handle creation: {@code findStatic}, {@code findVirtual},
+ * {@code findConstructor}, {@code findSpecial},
+ * {@code findGetter}, {@code findSetter},
+ * {@code findStaticGetter}, or {@code findStaticSetter}.
+ * The call to one of these methods must be followed immediately
+ * by an {@code areturn} instruction.
+ * The net result of the call to the MH_x or MT_x method must be
+ * the creation of a constant method handle. Thus, replacing calls
+ * to MH_x or MT_x methods by {@code ldc} instructions should leave
+ * the meaning of the program unchanged.
+ * <p>
+ * Static private methods named INDY_x must be stereotyped generators
+ * of {@code invokedynamic} call sites.
+ * All calls to them must be immediately followed by
+ * {@code invokeExact} calls.
+ * All such pairs of calls are transformed to {@code invokedynamic}
+ * instructions. Each INDY_x method must begin with a call to a
+ * MH_x method, which is taken to be its bootstrap method.
+ * The method must be immediately invoked (via {@code invokeGeneric}
+ * on constant lookup, name, and type arguments. An object array of
+ * constants may also be appended to the {@code invokeGeneric call}.
+ * This call must be cast to {@code CallSite}, and the result must be
+ * immediately followed by a call to {@code dynamicInvoker}, with the
+ * resulting method handle returned.
+ * <p>
+ * The net result of all of these actions is equivalent to the JVM's
+ * execution of an {@code invokedynamic} instruction in the unlinked state.
+ * Running this code once should produce the same results as running
+ * the corresponding {@code invokedynamic} instruction.
+ * In order to model the caching behavior, the code of an INDY_x
+ * method is allowed to begin with getstatic, aaload, and if_acmpne
+ * instructions which load a static method handle value and return it
+ * if the value is non-null.
+ * <p>
+ * Example usage:
+ * <blockquote><pre>
+$ JAVA_HOME=(some recent OpenJDK 7 build)
+$ ant
+$ $JAVA_HOME/bin/java -cp build/classes indify.Indify --overwrite --dest build/testout build/classes/indify/Example.class
+$ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp build/classes indify.Example
+MT = (java.lang.Object)java.lang.Object
+MH = adder(int,int)java.lang.Integer
+adder(1,2) = 3
+calling indy: 42
+$ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+EnableInvokeDynamic -cp build/testout indify.Example
+(same output as above)
+ * </pre></blockquote>
+ * <p>
+ * Before OpenJDK build b123, the format of {@code CONSTANT_InvokeDynamic} is in transition,
+ * and the switch {@code --transitionalJSR292=yes} is recommended.
+ * It is turned <em>off</em> by default, but users of earlier builds may need to turn it on.
+ * <p>
+ * A version of this transformation built on top of <a href="http://asm.ow2.org/">http://asm.ow2.org/</a> would be welcome.
+ * @author John Rose
+ */
+public class Indify {
+ public static void main(String... av) throws IOException {
+ new Indify().run(av);
+ }
+
+ public File dest;
+ public String[] classpath = {"."};
+ public boolean keepgoing = false;
+ public boolean expandProperties = false;
+ public boolean overwrite = false;
+ public boolean quiet = false;
+ public boolean verbose = false;
+ public boolean transitionalJSR292 = false; // final version is distributed
+ public boolean all = false;
+ public int verifySpecifierCount = -1;
+
+ public void run(String... av) throws IOException {
+ List<String> avl = new ArrayList<>(Arrays.asList(av));
+ parseOptions(avl);
+ if (avl.isEmpty())
+ throw new IllegalArgumentException("Usage: indify [--dest dir] [option...] file...");
+ if ("--java".equals(avl.get(0))) {
+ avl.remove(0);
+ try {
+ runApplication(avl.toArray(new String[0]));
+ } catch (Exception ex) {
+ if (ex instanceof RuntimeException) throw (RuntimeException) ex;
+ throw new RuntimeException(ex);
+ }
+ return;
+ }
+ Exception err = null;
+ for (String a : avl) {
+ try {
+ indify(a);
+ } catch (Exception ex) {
+ if (err == null) err = ex;
+ System.err.println("failure on "+a);
+ if (!keepgoing) break;
+ }
+ }
+ if (err != null) {
+ if (err instanceof IOException) throw (IOException) err;
+ throw (RuntimeException) err;
+ }
+ }
+
+ /** Execute the given application under a class loader which indifies all application classes. */
+ public void runApplication(String... av) throws Exception {
+ List<String> avl = new ArrayList<>(Arrays.asList(av));
+ String mainClassName = avl.remove(0);
+ av = avl.toArray(new String[0]);
+ Class<?> mainClass = Class.forName(mainClassName, true, makeClassLoader());
+ java.lang.reflect.Method main = mainClass.getMethod("main", String[].class);
+ try { main.setAccessible(true); } catch (SecurityException ex) { }
+ main.invoke(null, (Object) av);
+ }
+
+ public void parseOptions(List<String> av) throws IOException {
+ for (; !av.isEmpty(); av.remove(0)) {
+ String a = av.get(0);
+ if (a.startsWith("-")) {
+ String a2 = null;
+ int eq = a.indexOf('=');
+ if (eq > 0) {
+ a2 = maybeExpandProperties(a.substring(eq+1));
+ a = a.substring(0, eq+1);
+ }
+ switch (a) {
+ case "--java":
+ return; // keep this argument
+ case "-d": case "--dest": case "-d=": case "--dest=":
+ dest = new File(a2 != null ? a2 : maybeExpandProperties(av.remove(1)));
+ break;
+ case "-cp": case "--classpath":
+ classpath = maybeExpandProperties(av.remove(1)).split("["+File.pathSeparatorChar+"]");
+ break;
+ case "-k": case "--keepgoing": case "--keepgoing=":
+ keepgoing = booleanOption(a2); // print errors but keep going
+ break;
+ case "--expand-properties": case "--expand-properties=":
+ expandProperties = booleanOption(a2); // expand property references in subsequent arguments
+ break;
+ case "--verify-specifier-count": case "--verify-specifier-count=":
+ verifySpecifierCount = Integer.valueOf(a2);
+ break;
+ case "--overwrite": case "--overwrite=":
+ overwrite = booleanOption(a2); // overwrite output files
+ break;
+ case "--all": case "--all=":
+ all = booleanOption(a2); // copy all classes, even if no patterns
+ break;
+ case "-q": case "--quiet": case "--quiet=":
+ quiet = booleanOption(a2); // less output
+ break;
+ case "-v": case "--verbose": case "--verbose=":
+ verbose = booleanOption(a2); // more output
+ break;
+ case "--transitionalJSR292": case "--transitionalJSR292=":
+ transitionalJSR292 = booleanOption(a2); // use older invokedynamic format
+ break;
+ default:
+ throw new IllegalArgumentException("unrecognized flag: "+a);
+ }
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (dest == null && !overwrite)
+ throw new RuntimeException("no output specified; need --dest d or --overwrite");
+ if (expandProperties) {
+ for (int i = 0; i < av.size(); i++)
+ av.set(i, maybeExpandProperties(av.get(i)));
+ }
+ }
+
+ private boolean booleanOption(String s) {
+ if (s == null) return true;
+ switch (s) {
+ case "true": case "yes": case "on": case "1": return true;
+ case "false": case "no": case "off": case "0": return false;
+ }
+ throw new IllegalArgumentException("unrecognized boolean flag="+s);
+ }
+
+ private String maybeExpandProperties(String s) {
+ if (!expandProperties) return s;
+ Set<String> propsDone = new HashSet<>();
+ while (s.contains("${")) {
+ int lbrk = s.indexOf("${");
+ int rbrk = s.indexOf('}', lbrk);
+ if (rbrk < 0) break;
+ String prop = s.substring(lbrk+2, rbrk);
+ if (!propsDone.add(prop)) break;
+ String value = System.getProperty(prop);
+ if (verbose) System.err.println("expanding ${"+prop+"} => "+value);
+ if (value == null) break;
+ s = s.substring(0, lbrk) + value + s.substring(rbrk+1);
+ }
+ return s;
+ }
+
+ public void indify(String a) throws IOException {
+ File f = new File(a);
+ String fn = f.getName();
+ if (fn.endsWith(".class") && f.isFile())
+ indifyFile(f, dest);
+ else if (fn.endsWith(".jar") && f.isFile())
+ indifyJar(f, dest);
+ else if (f.isDirectory())
+ indifyTree(f, dest);
+ else if (!keepgoing)
+ throw new RuntimeException("unrecognized file: "+a);
+ }
+
+ private void ensureDirectory(File dir) {
+ if (dir.mkdirs() && !quiet)
+ System.err.println("created "+dir);
+ }
+
+ public void indifyFile(File f, File dest) throws IOException {
+ if (verbose) System.err.println("reading "+f);
+ ClassFile cf = new ClassFile(f);
+ Logic logic = new Logic(cf);
+ boolean changed = logic.transform();
+ logic.reportPatternMethods(quiet, keepgoing);
+ if (changed || all) {
+ File outfile;
+ if (dest != null) {
+ ensureDirectory(dest);
+ outfile = classPathFile(dest, cf.nameString());
+ } else {
+ outfile = f; // overwrite input file, no matter where it is
+ }
+ cf.writeTo(outfile);
+ if (!quiet) System.err.println("wrote "+outfile);
+ }
+ }
+
+ File classPathFile(File pathDir, String className) {
+ String qualname = className.replace('.','/')+".class";
+ qualname = qualname.replace('/', File.separatorChar);
+ return new File(pathDir, qualname);
+ }
+
+ public void indifyJar(File f, Object dest) throws IOException {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void indifyTree(File f, File dest) throws IOException {
+ if (verbose) System.err.println("reading directory: "+f);
+ for (File f2 : f.listFiles(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ if (name.endsWith(".class")) return true;
+ if (name.contains(".")) return false;
+ // return true if it might be a package name:
+ return Character.isJavaIdentifierStart(name.charAt(0));
+ }})) {
+ if (f2.getName().endsWith(".class"))
+ indifyFile(f2, dest);
+ else if (f2.isDirectory())
+ indifyTree(f2, dest);
+ }
+ }
+
+ public ClassLoader makeClassLoader() {
+ return new Loader();
+ }
+ private class Loader extends ClassLoader {
+ Loader() {
+ this(Indify.class.getClassLoader());
+ }
+ Loader(ClassLoader parent) {
+ super(parent);
+ }
+ public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ File f = findClassInPath(name);
+ if (f != null) {
+ try {
+ Class<?> c = transformAndLoadClass(f);
+ if (c != null) {
+ if (resolve) resolveClass(c);
+ return c;
+ }
+ } catch (Exception ex) {
+ if (ex instanceof IllegalArgumentException)
+ // pass error from reportPatternMethods
+ throw (IllegalArgumentException) ex;
+ }
+ }
+ return super.loadClass(name, resolve);
+ }
+ private File findClassInPath(String name) {
+ for (String s : classpath) {
+ File f = classPathFile(new File(s), name);
+ //System.out.println("Checking for "+f);
+ if (f.exists() && f.canRead()) {
+ return f;
+ }
+ }
+ return null;
+ }
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ try {
+ File f = findClassInPath(name);
+ if (f != null) {
+ Class<?> c = transformAndLoadClass(f);
+ if (c != null) return c;
+ }
+ } catch (IOException ex) {
+ throw new ClassNotFoundException("IO error", ex);
+ }
+ throw new ClassNotFoundException();
+ }
+ private Class<?> transformAndLoadClass(File f) throws ClassNotFoundException, IOException {
+ if (verbose) System.err.println("Loading class from "+f);
+ ClassFile cf = new ClassFile(f);
+ Logic logic = new Logic(cf);
+ boolean changed = logic.transform();
+ if (verbose && !changed) System.err.println("(no change)");
+ logic.reportPatternMethods(!verbose, keepgoing);
+ byte[] bytes = cf.toByteArray();
+ return defineClass(null, bytes, 0, bytes.length);
+ }
+ }
+
+ private class Logic {
+ // Indify logic, per se.
+ ClassFile cf;
+ final char[] poolMarks;
+ final Map<Method,Constant> constants = new HashMap<>();
+ final Map<Method,String> indySignatures = new HashMap<>();
+ Logic(ClassFile cf) {
+ this.cf = cf;
+ poolMarks = new char[cf.pool.size()];
+ }
+ boolean transform() {
+ if (!initializeMarks()) return false;
+ if (!findPatternMethods()) return false;
+ Pool pool = cf.pool;
+ //for (Constant c : cp) System.out.println(" # "+c);
+ for (Method m : cf.methods) {
+ if (constants.containsKey(m)) continue; // don't bother
+ // Transform references.
+ int blab = 0;
+ for (Instruction i = m.instructions(); i != null; i = i.next()) {
+ if (i.bc != opc_invokestatic) continue;
+ int methi = i.u2At(1);
+ if (poolMarks[methi] == 0) continue;
+ Short[] ref = pool.getMemberRef((short)methi);
+ Method conm = findMember(cf.methods, ref[1], ref[2]);
+ if (conm == null) continue;
+ Constant con = constants.get(conm);
+ if (con == null) continue;
+ if (blab++ == 0 && !quiet)
+ System.err.println("patching "+cf.nameString()+"."+m);
+ //if (blab == 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println(" |"+j); }
+ if (con.tag == CONSTANT_InvokeDynamic ||
+ con.tag == CONSTANT_InvokeDynamic_17) {
+ // need to patch the following instruction too,
+ // but there are usually intervening argument pushes too
+ Instruction i2 = findPop(i);
+ Short[] ref2 = null;
+ short ref2i = 0;
+ if (i2 != null && i2.bc == opc_invokevirtual &&
+ poolMarks[(char)(ref2i = (short) i2.u2At(1))] == 'D')
+ ref2 = pool.getMemberRef(ref2i);
+ if (ref2 == null || !"invokeExact".equals(pool.getString(ref2[1]))) {
+ System.err.println(m+": failed to create invokedynamic at "+i.pc);
+ continue;
+ }
+ String invType = pool.getString(ref2[2]);
+ String bsmType = indySignatures.get(conm);
+ if (!invType.equals(bsmType)) {
+ System.err.println(m+": warning: "+conm+" call type and local invoke type differ: "
+ +bsmType+", "+invType);
+ }
+ assert(i.len == 3 || i2.len == 3);
+ if (!quiet) System.err.println(i+" "+conm+";...; "+i2+" => invokedynamic "+con);
+ int start = i.pc + 3, end = i2.pc;
+ System.arraycopy(i.codeBase, start, i.codeBase, i.pc, end-start);
+ i.forceNext(0); // force revisit of new instruction
+ i2.u1AtPut(-3, opc_invokedynamic);
+ i2.u2AtPut(-2, con.index);
+ i2.u2AtPut(0, (short)0);
+ i2.u1AtPut(2, opc_nop);
+ //System.out.println(new Instruction(i.codeBase, i2.pc-3));
+ } else {
+ if (!quiet) System.err.println(i+" "+conm+" => ldc "+con);
+ assert(i.len == 3);
+ i.u1AtPut(0, opc_ldc_w);
+ i.u2AtPut(1, con.index);
+ }
+ }
+ //if (blab >= 1) { for (Instruction j = m.instructions(); j != null; j = j.next()) System.out.println(" |"+j); }
+ }
+ cf.methods.removeAll(constants.keySet());
+ return true;
+ }
+
+ // Scan forward from the instruction to find where the stack p
+ // below the current sp at the instruction.
+ Instruction findPop(Instruction i) {
+ //System.out.println("findPop from "+i);
+ Pool pool = cf.pool;
+ JVMState jvm = new JVMState();
+ decode:
+ for (i = i.clone().next(); i != null; i = i.next()) {
+ String pops = INSTRUCTION_POPS[i.bc];
+ //System.out.println(" "+i+" "+jvm.stack+" : "+pops.replace("$", " => "));
+ if (pops == null) break;
+ if (jvm.stackMotion(i.bc)) continue decode;
+ if (pops.indexOf('Q') >= 0) {
+ Short[] ref = pool.getMemberRef((short) i.u2At(1));
+ String type = simplifyType(pool.getString(CONSTANT_Utf8, ref[2]));
+ switch (i.bc) {
+ case opc_getstatic:
+ case opc_getfield:
+ case opc_putstatic:
+ case opc_putfield:
+ pops = pops.replace("Q", type);
+ break;
+ default:
+ if (!type.startsWith("("))
+ throw new InternalError(i.toString());
+ pops = pops.replace("Q$Q", type.substring(1).replace(")","$"));
+ break;
+ }
+ //System.out.println("special type: "+type+" => "+pops);
+ }
+ int npops = pops.indexOf('$');
+ if (npops < 0) throw new InternalError();
+ if (npops > jvm.sp()) return i;
+ List<Object> args = jvm.args(npops);
+ int k = 0;
+ for (Object x : args) {
+ char have = (Character) x;
+ char want = pops.charAt(k++);
+ if (have == 'X' || want == 'X') continue;
+ if (have != want) break decode;
+ }
+ if (pops.charAt(k++) != '$') break decode;
+ args.clear();
+ while (k < pops.length())
+ args.add(pops.charAt(k++));
+ }
+ System.err.println("*** bailout on jvm: "+jvm.stack+" "+i);
+ return null;
+ }
+
+ boolean findPatternMethods() {
+ boolean found = false;
+ for (char mark : "THI".toCharArray()) {
+ for (Method m : cf.methods) {
+ if (!Modifier.isPrivate(m.access)) continue;
+ if (!Modifier.isStatic(m.access)) continue;
+ if (nameAndTypeMark(m.name, m.type) == mark) {
+ Constant con = scanPattern(m, mark);
+ if (con == null) continue;
+ constants.put(m, con);
+ found = true;
+ }
+ }
+ }
+ return found;
+ }
+
+ void reportPatternMethods(boolean quietly, boolean allowMatchFailure) {
+ if (!quietly && !constants.keySet().isEmpty())
+ System.err.println("pattern methods removed: "+constants.keySet());
+ for (Method m : cf.methods) {
+ if (nameMark(cf.pool.getString(m.name)) != 0 &&
+ constants.get(m) == null) {
+ String failure = "method has special name but fails to match pattern: "+m;
+ if (!allowMatchFailure)
+ throw new IllegalArgumentException(failure);
+ else if (!quietly)
+ System.err.println("warning: "+failure);
+ }
+ }
+ if (verifySpecifierCount >= 0) {
+ List<Object[]> specs = bootstrapMethodSpecifiers(false);
+ int specsLen = (specs == null ? 0 : specs.size());
+ if (specsLen != verifySpecifierCount) {
+ throw new IllegalArgumentException("BootstrapMethods length is "+specsLen+" but should be "+verifySpecifierCount);
+ }
+ }
+ if (!quiet) System.err.flush();
+ }
+
+ // mark constant pool entries according to participation in patterns
+ boolean initializeMarks() {
+ boolean changed = false;
+ for (;;) {
+ boolean changed1 = false;
+ int cpindex = -1;
+ for (Constant e : cf.pool) {
+ ++cpindex;
+ if (e == null) continue;
+ char mark = poolMarks[cpindex];
+ if (mark != 0) continue;
+ switch (e.tag) {
+ case CONSTANT_Utf8:
+ mark = nameMark(e.itemString()); break;
+ case CONSTANT_NameAndType:
+ mark = nameAndTypeMark(e.itemIndexes()); break;
+ case CONSTANT_Class: {
+ int n1 = e.itemIndex();
+ char nmark = poolMarks[(char)n1];
+ if ("DJ".indexOf(nmark) >= 0)
+ mark = nmark;
+ break;
+ }
+ case CONSTANT_Field:
+ case CONSTANT_Method: {
+ Short[] n12 = e.itemIndexes();
+ short cl = n12[0];
+ short nt = n12[1];
+ char cmark = poolMarks[(char)cl];
+ if (cmark != 0) {
+ mark = cmark; // it is a java.dyn.* or java.lang.* method
+ break;
+ }
+ String cls = cf.pool.getString(CONSTANT_Class, cl);
+ if (cls.equals(cf.nameString())) {
+ switch (poolMarks[(char)nt]) {
+ // it is a private MH/MT/INDY method
+ case 'T': case 'H': case 'I':
+ mark = poolMarks[(char)nt];
+ break;
+ }
+ }
+ break;
+ }
+ default: break;
+ }
+ if (mark != 0) {
+ poolMarks[cpindex] = mark;
+ changed1 = true;
+ }
+ }
+ if (!changed1)
+ break;
+ changed = true;
+ }
+ return changed;
+ }
+ char nameMark(String s) {
+ if (s.startsWith("MT_")) return 'T';
+ else if (s.startsWith("MH_")) return 'H';
+ else if (s.startsWith("INDY_")) return 'I';
+ else if (transitionalJSR292 &&
+ s.startsWith("java/dyn/")) return 'D';
+ else if (s.startsWith("java/lang/invoke/")) return 'D';
+ else if (s.startsWith("java/lang/")) return 'J';
+ return 0;
+ }
+ char nameAndTypeMark(Short[] n12) {
+ return nameAndTypeMark(n12[0], n12[1]);
+ }
+ char nameAndTypeMark(short n1, short n2) {
+ char mark = poolMarks[(char)n1];
+ if (mark == 0) return 0;
+ String descr = cf.pool.getString(CONSTANT_Utf8, n2);
+ String requiredType;
+ switch (poolMarks[(char)n1]) {
+ case 'H': requiredType = "()Ljava/lang/invoke/MethodHandle;"; break;
+ case 'T': requiredType = "()Ljava/lang/invoke/MethodType;"; break;
+ case 'I': requiredType = "()Ljava/lang/invoke/MethodHandle;"; break;
+ default: return 0;
+ }
+ if (matchType(descr, requiredType)) return mark;
+ return 0;
+ }
+
+ boolean matchType(String descr, String requiredType) {
+ if (descr.equals(requiredType)) return true;
+ if (transitionalJSR292) {
+ String oldType = requiredType.replace("Ljava/lang/invoke/", "Ljava/dyn/");
+ if (descr.equals(oldType)) return true;
+ }
+ return false;
+ }
+
+ private class JVMState {
+ final List<Object> stack = new ArrayList<>();
+ int sp() { return stack.size(); }
+ void push(Object x) { stack.add(x); }
+ void push2(Object x) { stack.add(EMPTY_SLOT); stack.add(x); }
+ void pushAt(int pos, Object x) { stack.add(stack.size()+pos, x); }
+ Object pop() { return stack.remove(sp()-1); }
+ Object top() { return stack.get(sp()-1); }
+ List<Object> args(boolean hasRecv, String type) {
+ return args(argsize(type) + (hasRecv ? 1 : 0));
+ }
+ List<Object> args(int argsize) {
+ return stack.subList(sp()-argsize, sp());
+ }
+ boolean stackMotion(int bc) {
+ switch (bc) {
+ case opc_pop: pop(); break;
+ case opc_pop2: pop(); pop(); break;
+ case opc_swap: pushAt(-1, pop()); break;
+ case opc_dup: push(top()); break;
+ case opc_dup_x1: pushAt(-2, top()); break;
+ case opc_dup_x2: pushAt(-3, top()); break;
+ // ? also: dup2{,_x1,_x2}
+ default: return false;
+ }
+ return true;
+ }
+ }
+ private final String EMPTY_SLOT = "_";
+ private void removeEmptyJVMSlots(List<Object> args) {
+ for (;;) {
+ int i = args.indexOf(EMPTY_SLOT);
+ if (i >= 0 && i+1 < args.size()
+ && (isConstant(args.get(i+1), CONSTANT_Long) ||
+ isConstant(args.get(i+1), CONSTANT_Double)))
+ args.remove(i);
+ else break;
+ }
+ }
+
+ private Constant scanPattern(Method m, char patternMark) {
+ if (verbose) System.err.println("scan "+m+" for pattern="+patternMark);
+ int wantTag;
+ switch (patternMark) {
+ case 'T': wantTag = CONSTANT_MethodType; break;
+ case 'H': wantTag = CONSTANT_MethodHandle; break;
+ case 'I': wantTag = CONSTANT_InvokeDynamic; break;
+ default: throw new InternalError();
+ }
+ Instruction i = m.instructions();
+ JVMState jvm = new JVMState();
+ Pool pool = cf.pool;
+ int branchCount = 0;
+ Object arg;
+ List<Object> args;
+ List<Object> bsmArgs = null; // args to invokeGeneric
+ decode:
+ for (; i != null; i = i.next()) {
+ //System.out.println(jvm.stack+" "+i);
+ int bc = i.bc;
+ switch (bc) {
+ case opc_ldc: jvm.push(pool.get(i.u1At(1))); break;
+ case opc_ldc_w: jvm.push(pool.get(i.u2At(1))); break;
+ case opc_ldc2_w: jvm.push2(pool.get(i.u2At(1))); break;
+ case opc_aconst_null: jvm.push(null); break;
+ case opc_bipush: jvm.push((int)(byte) i.u1At(1)); break;
+ case opc_sipush: jvm.push((int)(short)i.u2At(1)); break;
+
+ // these support creation of a restarg array
+ case opc_anewarray:
+ arg = jvm.pop();
+ if (!(arg instanceof Integer)) break decode;
+ arg = Arrays.asList(new Object[(Integer)arg]);
+ jvm.push(arg);
+ break;
+ case opc_dup:
+ jvm.push(jvm.top()); break;
+ case opc_aastore:
+ args = jvm.args(3); // array, index, value
+ if (args.get(0) instanceof List &&
+ args.get(1) instanceof Integer) {
+ ((List<Object>)args.get(0)).set( (Integer)args.get(1), args.get(2) );
+ }
+ args.clear();
+ break;
+
+ case opc_new:
+ {
+ String type = pool.getString(CONSTANT_Class, (short)i.u2At(1));
+ //System.out.println("new "+type);
+ switch (type) {
+ case "java/lang/StringBuilder":
+ jvm.push("StringBuilder");
+ continue decode; // go to next instruction
+ }
+ break decode; // bail out
+ }
+
+ case opc_getstatic:
+ {
+ // int.class compiles to getstatic Integer.TYPE
+ int fieldi = i.u2At(1);
+ char mark = poolMarks[fieldi];
+ //System.err.println("getstatic "+fieldi+Arrays.asList(pool.getStrings(pool.getMemberRef((short)fieldi)))+mark);
+ if (mark == 'J') {
+ Short[] ref = pool.getMemberRef((short) fieldi);
+ String name = pool.getString(CONSTANT_Utf8, ref[1]);
+ if ("TYPE".equals(name)) {
+ String wrapperName = pool.getString(CONSTANT_Class, ref[0]).replace('/', '.');
+ // a primitive type descriptor
+ Class<?> primClass;
+ try {
+ primClass = (Class<?>) Class.forName(wrapperName).getField(name).get(null);
+ } catch (Exception ex) {
+ throw new InternalError("cannot load "+wrapperName+"."+name);
+ }
+ jvm.push(primClass);
+ break;
+ }
+ }
+ // unknown field; keep going...
+ jvm.push(UNKNOWN_CON);
+ break;
+ }
+ case opc_putstatic:
+ {
+ if (patternMark != 'I') break decode;
+ jvm.pop();
+ // unknown field; keep going...
+ break;
+ }
+
+ case opc_invokestatic:
+ case opc_invokevirtual:
+ case opc_invokespecial:
+ {
+ boolean hasRecv = (bc != opc_invokestatic);
+ int methi = i.u2At(1);
+ char mark = poolMarks[methi];
+ Short[] ref = pool.getMemberRef((short)methi);
+ String type = pool.getString(CONSTANT_Utf8, ref[2]);
+ //System.out.println("invoke "+pool.getString(CONSTANT_Utf8, ref[1])+" "+Arrays.asList(ref)+" : "+type);
+ args = jvm.args(hasRecv, type);
+ String intrinsic = null;
+ Constant con;
+ if (mark == 'D' || mark == 'J') {
+ intrinsic = pool.getString(CONSTANT_Utf8, ref[1]);
+ if (mark == 'J') {
+ String cls = pool.getString(CONSTANT_Class, ref[0]);
+ cls = cls.substring(1+cls.lastIndexOf('/'));
+ intrinsic = cls+"."+intrinsic;
+ }
+ //System.out.println("recognized intrinsic "+intrinsic);
+ byte refKind = -1;
+ switch (intrinsic) {
+ case "findGetter": refKind = REF_getField; break;
+ case "findStaticGetter": refKind = REF_getStatic; break;
+ case "findSetter": refKind = REF_putField; break;
+ case "findStaticSetter": refKind = REF_putStatic; break;
+ case "findVirtual": refKind = REF_invokeVirtual; break;
+ case "findStatic": refKind = REF_invokeStatic; break;
+ case "findSpecial": refKind = REF_invokeSpecial; break;
+ case "findConstructor": refKind = REF_newInvokeSpecial; break;
+ }
+ if (refKind >= 0 && (con = parseMemberLookup(refKind, args)) != null) {
+ args.clear(); args.add(con);
+ continue;
+ }
+ }
+ Method ownMethod = null;
+ if (mark == 'T' || mark == 'H' || mark == 'I') {
+ ownMethod = findMember(cf.methods, ref[1], ref[2]);
+ }
+ //if (intrinsic != null) System.out.println("intrinsic = "+intrinsic);
+ switch (intrinsic == null ? "" : intrinsic) {
+ case "fromMethodDescriptorString":
+ con = makeMethodTypeCon(args.get(0));
+ args.clear(); args.add(con);
+ continue;
+ case "methodType": {
+ flattenVarargs(args); // there are several overloadings, some with varargs
+ StringBuilder buf = new StringBuilder();
+ String rtype = null;
+ for (Object typeArg : args) {
+ if (typeArg instanceof Class) {
+ Class<?> argClass = (Class<?>) typeArg;
+ if (argClass.isPrimitive()) {
+ char tchar;
+ switch (argClass.getName()) {
+ case "void": tchar = 'V'; break;
+ case "boolean": tchar = 'Z'; break;
+ case "byte": tchar = 'B'; break;
+ case "char": tchar = 'C'; break;
+ case "short": tchar = 'S'; break;
+ case "int": tchar = 'I'; break;
+ case "long": tchar = 'J'; break;
+ case "float": tchar = 'F'; break;
+ case "double": tchar = 'D'; break;
+ default: throw new InternalError(argClass.toString());
+ }
+ buf.append(tchar);
+ } else {
+ // should not happen, but...
+ buf.append('L').append(argClass.getName().replace('.','/')).append(';');
+ }
+ } else if (typeArg instanceof Constant) {
+ Constant argCon = (Constant) typeArg;
+ if (argCon.tag == CONSTANT_Class) {
+ String cn = pool.get(argCon.itemIndex()).itemString();
+ if (cn.endsWith(";"))
+ buf.append(cn);
+ else
+ buf.append('L').append(cn).append(';');
+ } else {
+ break decode;
+ }
+ } else {
+ break decode;
+ }
+ if (rtype == null) {
+ // first arg is treated differently
+ rtype = buf.toString();
+ buf.setLength(0);
+ buf.append('(');
+ }
+ }
+ buf.append(')').append(rtype);
+ con = con = makeMethodTypeCon(buf.toString());
+ args.clear(); args.add(con);
+ continue;
+ }
+ case "lookup":
+ case "dynamicInvoker":
+ args.clear(); args.add(intrinsic);
+ continue;
+ case "lookupClass":
+ if (args.equals(Arrays.asList("lookup"))) {
+ // fold lookup().lookupClass() to the enclosing class
+ args.clear(); args.add(pool.get(cf.thisc));
+ continue;
+ }
+ break;
+ case "invokeGeneric":
+ case "invokeWithArguments":
+ if (patternMark != 'I') break decode;
+ if ("invokeWithArguments".equals(intrinsic))
+ flattenVarargs(args);
+ bsmArgs = new ArrayList(args);
+ args.clear(); args.add("invokeGeneric");
+ continue;
+ case "Integer.valueOf":
+ case "Float.valueOf":
+ case "Long.valueOf":
+ case "Double.valueOf":
+ removeEmptyJVMSlots(args);
+ if (args.size() == 1) {
+ arg = args.remove(0);
+ assert(3456 == (CONSTANT_Integer*1000 + CONSTANT_Float*100 + CONSTANT_Long*10 + CONSTANT_Double));
+ if (isConstant(arg, CONSTANT_Integer + "IFLD".indexOf(intrinsic.charAt(0)))
+ || arg instanceof Number) {
+ args.add(arg); continue;
+ }
+ }
+ break decode;
+ case "StringBuilder.append":
+ // allow calls like ("value = "+x)
+ removeEmptyJVMSlots(args);
+ args.subList(1, args.size()).clear();
+ continue;
+ case "StringBuilder.toString":
+ args.clear();
+ args.add(intrinsic);
+ continue;
+ }
+ if (!hasRecv && ownMethod != null && patternMark != 0) {
+ con = constants.get(ownMethod);
+ if (con == null) break decode;
+ args.clear(); args.add(con);
+ continue;
+ } else if (type.endsWith(")V")) {
+ // allow calls like println("reached the pattern method")
+ args.clear();
+ continue;
+ }
+ break decode; // bail out for most calls
+ }
+ case opc_areturn:
+ {
+ ++branchCount;
+ if (bsmArgs != null) {
+ // parse bsmArgs as (MH, lookup, String, MT, [extra])
+ Constant indyCon = makeInvokeDynamicCon(bsmArgs);
+ if (indyCon != null) {
+ Constant typeCon = (Constant) bsmArgs.get(3);
+ indySignatures.put(m, pool.getString(typeCon.itemIndex()));
+ return indyCon;
+ }
+ System.err.println(m+": inscrutable bsm arguments: "+bsmArgs);
+ break decode; // bail out
+ }
+ arg = jvm.pop();
+ if (branchCount == 2 && UNKNOWN_CON.equals(arg))
+ break; // merge to next path
+ if (isConstant(arg, wantTag))
+ return (Constant) arg;
+ break decode; // bail out
+ }
+ default:
+ if (jvm.stackMotion(i.bc)) break;
+ if (bc >= opc_nconst_MIN && bc <= opc_nconst_MAX)
+ { jvm.push(INSTRUCTION_CONSTANTS[bc - opc_nconst_MIN]); break; }
+ if (patternMark == 'I') {
+ // these support caching paths in INDY_x methods
+ if (bc == opc_aload || bc >= opc_aload_0 && bc <= opc_aload_MAX)
+ { jvm.push(UNKNOWN_CON); break; }
+ if (bc == opc_astore || bc >= opc_astore_0 && bc <= opc_astore_MAX)
+ { jvm.pop(); break; }
+ switch (bc) {
+ case opc_getfield:
+ case opc_aaload:
+ jvm.push(UNKNOWN_CON); break;
+ case opc_ifnull:
+ case opc_ifnonnull:
+ // ignore branch target
+ if (++branchCount != 1) break decode;
+ jvm.pop();
+ break;
+ case opc_checkcast:
+ arg = jvm.top();
+ if ("invokeWithArguments".equals(arg) ||
+ "invokeGeneric".equals(arg))
+ break; // assume it is a helpful cast
+ break decode;
+ default:
+ break decode; // bail out
+ }
+ continue decode; // go to next instruction
+ }
+ break decode; // bail out
+ } //end switch
+ }
+ System.err.println(m+": bailout on "+i+" jvm stack: "+jvm.stack);
+ return null;
+ }
+ private final String UNKNOWN_CON = "<unknown>";
+
+ private void flattenVarargs(List<Object> args) {
+ int size = args.size();
+ if (size > 0 && args.get(size-1) instanceof List)
+ args.addAll((List<Object>) args.remove(size-1));
+ }
+
+ private boolean isConstant(Object x, int tag) {
+ return x instanceof Constant && ((Constant)x).tag == tag;
+ }
+ private Constant makeMethodTypeCon(Object x) {
+ short utfIndex;
+ if (x instanceof String)
+ utfIndex = (short) cf.pool.addConstant(CONSTANT_Utf8, x).index;
+ else if (isConstant(x, CONSTANT_String))
+ utfIndex = ((Constant)x).itemIndex();
+ else return null;
+ return cf.pool.addConstant(CONSTANT_MethodType, utfIndex);
+ }
+ private Constant parseMemberLookup(byte refKind, List<Object> args) {
+ // E.g.: lookup().findStatic(Foo.class, "name", MethodType)
+ if (args.size() != 4) return null;
+ int argi = 0;
+ if (!"lookup".equals(args.get(argi++))) return null;
+ short refindex, cindex, ntindex, nindex, tindex;
+ Object con;
+ if (!isConstant(con = args.get(argi++), CONSTANT_Class)) return null;
+ cindex = (short)((Constant)con).index;
+ if (!isConstant(con = args.get(argi++), CONSTANT_String)) return null;
+ nindex = ((Constant)con).itemIndex();
+ if (isConstant(con = args.get(argi++), CONSTANT_MethodType) ||
+ isConstant(con, CONSTANT_Class)) {
+ tindex = ((Constant)con).itemIndex();
+ } else return null;
+ ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
+ new Short[]{ nindex, tindex }).index;
+ byte reftag = CONSTANT_Method;
+ if (refKind <= REF_putStatic)
+ reftag = CONSTANT_Field;
+ else if (refKind == REF_invokeInterface)
+ reftag = CONSTANT_InterfaceMethod;
+ Constant ref = cf.pool.addConstant(reftag, new Short[]{ cindex, ntindex });
+ return cf.pool.addConstant(CONSTANT_MethodHandle, new Object[]{ refKind, (short)ref.index });
+ }
+ private Constant makeInvokeDynamicCon(List<Object> args) {
+ // E.g.: MH_bsm.invokeGeneric(lookup(), "name", MethodType, "extraArg")
+ removeEmptyJVMSlots(args);
+ if (args.size() != 4 && args.size() != 5) return null;
+ int argi = 0;
+ short nindex, tindex, ntindex, bsmindex;
+ Object con;
+ if (!isConstant(con = args.get(argi++), CONSTANT_MethodHandle)) return null;
+ bsmindex = (short) ((Constant)con).index;
+ if (!"lookup".equals(args.get(argi++))) return null;
+ if (!isConstant(con = args.get(argi++), CONSTANT_String)) return null;
+ nindex = ((Constant)con).itemIndex();
+ if (!isConstant(con = args.get(argi++), CONSTANT_MethodType)) return null;
+ tindex = ((Constant)con).itemIndex();
+ ntindex = (short) cf.pool.addConstant(CONSTANT_NameAndType,
+ new Short[]{ nindex, tindex }).index;
+ if (transitionalJSR292) {
+ if (argi != args.size()) {
+ System.err.println("BSM specifier has extra arguments but transitionalJSR292=1");
+ return null;
+ }
+ return cf.pool.addConstant(CONSTANT_InvokeDynamic_17,
+ new Short[]{ bsmindex, ntindex });
+ }
+ List<Object> extraArgs = Collections.emptyList();
+ if (argi < args.size()) {
+ Object arg = args.get(argi);
+ if (arg instanceof List)
+ extraArgs = (List<Object>) arg;
+ else
+ extraArgs = Arrays.asList(arg);
+ removeEmptyJVMSlots(args);
+ }
+ List<Short> extraArgIndexes = new CountedList<>(Short.class);
+ for (Object x : extraArgs) {
+ if (x instanceof Number) {
+ Object num = null; byte numTag = 0;
+ if (x instanceof Integer) { num = x; numTag = CONSTANT_Integer; }
+ if (x instanceof Float) { num = Float.floatToRawIntBits((Float)x); numTag = CONSTANT_Float; }
+ if (x instanceof Long) { num = x; numTag = CONSTANT_Long; }
+ if (x instanceof Double) { num = Double.doubleToRawLongBits((Double)x); numTag = CONSTANT_Double; }
+ if (num != null) x = cf.pool.addConstant(numTag, x);
+ }
+ if (!(x instanceof Constant)) return null;
+ extraArgIndexes.add((short) ((Constant)x).index);
+ }
+ List<Object[]> specs = bootstrapMethodSpecifiers(true);
+ int specindex = -1;
+ Object[] spec = new Object[]{ bsmindex, extraArgIndexes };
+ for (Object[] spec1 : specs) {
+ if (Arrays.equals(spec1, spec)) {
+ specindex = specs.indexOf(spec1);
+ if (verbose) System.err.println("reusing BSM specifier: "+spec1[0]+spec1[1]);
+ break;
+ }
+ }
+ if (specindex == -1) {
+ specindex = (short) specs.size();
+ specs.add(spec);
+ if (verbose) System.err.println("adding BSM specifier: "+spec[0]+spec[1]);
+ }
+ return cf.pool.addConstant(CONSTANT_InvokeDynamic,
+ new Short[]{ (short)specindex, ntindex });
+ }
+
+ List<Object[]> bootstrapMethodSpecifiers(boolean createIfNotFound) {
+ Attr bsms = cf.findAttr("BootstrapMethods");
+ if (bsms == null) {
+ if (!createIfNotFound) return null;
+ bsms = new Attr(cf, "BootstrapMethods", new byte[]{0,0});
+ assert(bsms == cf.findAttr("BootstrapMethods"));
+ }
+ if (bsms.item instanceof byte[]) {
+ // unflatten
+ List<Object[]> specs = new CountedList<>(Object[].class);
+ DataInputStream in = new DataInputStream(new ByteArrayInputStream((byte[]) bsms.item));
+ try {
+ int len = (char) in.readShort();
+ for (int i = 0; i < len; i++) {
+ short bsm = in.readShort();
+ int argc = (char) in.readShort();
+ List<Short> argv = new CountedList<>(Short.class);
+ for (int j = 0; j < argc; j++)
+ argv.add(in.readShort());
+ specs.add(new Object[]{ bsm, argv });
+ }
+ } catch (IOException ex) { throw new InternalError(); }
+ bsms.item = specs;
+ }
+ return (List<Object[]>) bsms.item;
+ }
+ }
+
+ private DataInputStream openInput(File f) throws IOException {
+ return new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
+ }
+
+ private DataOutputStream openOutput(File f) throws IOException {
+ if (!overwrite && f.exists())
+ throw new IOException("file already exists: "+f);
+ ensureDirectory(f.getParentFile());
+ return new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
+ }
+
+ static byte[] readRawBytes(DataInputStream in, int size) throws IOException {
+ byte[] bytes = new byte[size];
+ int nr = in.read(bytes);
+ if (nr != size)
+ throw new InternalError("wrong size: "+nr);
+ return bytes;
+ }
+
+ private interface Chunk {
+ void readFrom(DataInputStream in) throws IOException;
+ void writeTo(DataOutputStream out) throws IOException;
+ }
+
+ private static class CountedList<T> extends ArrayList<T> implements Chunk {
+ final Class<? extends T> itemClass;
+ final int rowlen;
+ CountedList(Class<? extends T> itemClass, int rowlen) {
+ this.itemClass = itemClass;
+ this.rowlen = rowlen;
+ }
+ CountedList(Class<? extends T> itemClass) { this(itemClass, -1); }
+ public void readFrom(DataInputStream in) throws IOException {
+ int count = in.readUnsignedShort();
+ while (size() < count) {
+ if (rowlen < 0) {
+ add(readInput(in, itemClass));
+ } else {
+ Class<?> elemClass = itemClass.getComponentType();
+ Object[] row = (Object[]) java.lang.reflect.Array.newInstance(elemClass, rowlen);
+ for (int i = 0; i < rowlen; i++)
+ row[i] = readInput(in, elemClass);
+ add(itemClass.cast(row));
+ }
+ }
+ }
+ public void writeTo(DataOutputStream out) throws IOException {
+ out.writeShort((short)size());
+ for (T item : this) {
+ writeOutput(out, item);
+ }
+ }
+ }
+
+ private static <T> T readInput(DataInputStream in, Class<T> dataClass) throws IOException {
+ Object data;
+ if (dataClass == Integer.class) {
+ data = in.readInt();
+ } else if (dataClass == Short.class) {
+ data = in.readShort();
+ } else if (dataClass == Byte.class) {
+ data = in.readByte();
+ } else if (dataClass == String.class) {
+ data = in.readUTF();
+ } else if (Chunk.class.isAssignableFrom(dataClass)) {
+ T obj;
+ try { obj = dataClass.newInstance(); }
+ catch (Exception ex) { throw new RuntimeException(ex); }
+ ((Chunk)obj).readFrom(in);
+ data = obj;
+ } else {
+ throw new InternalError("bad input datum: "+dataClass);
+ }
+ return dataClass.cast(data);
+ }
+ private static <T> T readInput(byte[] bytes, Class<T> dataClass) {
+ try {
+ return readInput(new DataInputStream(new ByteArrayInputStream(bytes)), dataClass);
+ } catch (IOException ex) {
+ throw new InternalError();
+ }
+ }
+ private static void readInputs(DataInputStream in, Object... data) throws IOException {
+ for (Object x : data) ((Chunk)x).readFrom(in);
+ }
+
+ private static void writeOutput(DataOutputStream out, Object data) throws IOException {
+ if (data == null) {
+ return;
+ } if (data instanceof Integer) {
+ out.writeInt((Integer)data);
+ } else if (data instanceof Long) {
+ out.writeLong((Long)data);
+ } else if (data instanceof Short) {
+ out.writeShort((Short)data);
+ } else if (data instanceof Byte) {
+ out.writeByte((Byte)data);
+ } else if (data instanceof String) {
+ out.writeUTF((String)data);
+ } else if (data instanceof byte[]) {
+ out.write((byte[])data);
+ } else if (data instanceof Object[]) {
+ for (Object x : (Object[]) data)
+ writeOutput(out, x);
+ } else if (data instanceof Chunk) {
+ Chunk x = (Chunk) data;
+ x.writeTo(out);
+ } else if (data instanceof List) {
+ for (Object x : (List<?>) data)
+ writeOutput(out, x);
+ } else {
+ throw new InternalError("bad output datum: "+data+" : "+data.getClass().getName());
+ }
+ }
+ private static void writeOutputs(DataOutputStream out, Object... data) throws IOException {
+ for (Object x : data) writeOutput(out, x);
+ }
+
+ public static abstract class Outer {
+ public abstract List<? extends Inner> inners();
+ protected void linkInners() {
+ for (Inner i : inners()) {
+ i.linkOuter(this);
+ if (i instanceof Outer)
+ ((Outer)i).linkInners();
+ }
+ }
+ public <T extends Outer> T outer(Class<T> c) {
+ for (Outer walk = this;; walk = ((Inner)walk).outer()) {
+ if (c.isInstance(walk))
+ return c.cast(walk);
+ //if (!(walk instanceof Inner)) return null;
+ }
+ }
+
+ public abstract List<Attr> attrs();
+ public Attr findAttr(String name) {
+ return findAttr(outer(ClassFile.class).pool.stringIndex(name, false));
+ }
+ public Attr findAttr(int name) {
+ if (name == 0) return null;
+ for (Attr a : attrs()) {
+ if (a.name == name) return a;
+ }
+ return null;
+ }
+ }
+ public interface Inner { Outer outer(); void linkOuter(Outer o); }
+ public static abstract class InnerOuter extends Outer implements Inner {
+ public Outer outer;
+ public Outer outer() { return outer; }
+ public void linkOuter(Outer o) { assert(outer == null); outer = o; }
+ }
+ public static class Constant<T> implements Chunk {
+ public final byte tag;
+ public final T item;
+ public final int index;
+ public Constant(int index, byte tag, T item) {
+ this.index = index;
+ this.tag = tag;
+ this.item = item;
+ }
+ public Constant checkTag(byte tag) {
+ if (this.tag != tag) throw new InternalError(this.toString());
+ return this;
+ }
+ public String itemString() { return (String)item; }
+ public Short itemIndex() { return (Short)item; }
+ public Short[] itemIndexes() { return (Short[])item; }
+ public void readFrom(DataInputStream in) throws IOException {
+ throw new InternalError("do not call");
+ }
+ public void writeTo(DataOutputStream out) throws IOException {
+ writeOutputs(out, tag, item);
+ }
+ public boolean equals(Object x) { return (x instanceof Constant && equals((Constant)x)); }
+ public boolean equals(Constant that) {
+ return (this.tag == that.tag && this.itemAsComparable().equals(that.itemAsComparable()));
+ }
+ public int hashCode() { return (tag * 31) + this.itemAsComparable().hashCode(); }
+ public Object itemAsComparable() {
+ switch (tag) {
+ case CONSTANT_Double: return Double.longBitsToDouble((Long)item);
+ case CONSTANT_Float: return Float.intBitsToFloat((Integer)item);
+ }
+ return (item instanceof Object[] ? Arrays.asList((Object[])item) : item);
+ }
+ public String toString() {
+ String itstr = String.valueOf(itemAsComparable());
+ return (index + ":" + tagName(tag) + (itstr.startsWith("[")?"":"=") + itstr);
+ }
+ private static String[] TAG_NAMES;
+ public static String tagName(byte tag) { // used for error messages
+ if (TAG_NAMES == null)
+ TAG_NAMES = ("None Utf8 Unicode Integer Float Long Double Class String"
+ +" Fieldref Methodref InterfaceMethodref NameAndType #13 #14"
+ +" MethodHandle MethodType InvokeDynamic#17 InvokeDynamic").split(" ");
+ if ((tag & 0xFF) >= TAG_NAMES.length) return "#"+(tag & 0xFF);
+ return TAG_NAMES[tag & 0xFF];
+ }
+ }
+
+ public static class Pool extends CountedList<Constant> implements Chunk {
+ private Map<String,Short> strings = new TreeMap<>();
+
+ public Pool() {
+ super(Constant.class);
+ }
+ public void readFrom(DataInputStream in) throws IOException {
+ int count = in.readUnsignedShort();
+ add(null); // always ignore first item
+ while (size() < count) {
+ readConstant(in);
+ }
+ }
+ public <T> Constant<T> addConstant(byte tag, T item) {
+ Constant<T> con = new Constant<>(size(), tag, item);
+ int idx = indexOf(con);
+ if (idx >= 0) return get(idx);
+ add(con);
+ if (tag == CONSTANT_Utf8) strings.put((String)item, (short) con.index);
+ return con;
+ }
+ private void readConstant(DataInputStream in) throws IOException {
+ byte tag = in.readByte();
+ int index = size();
+ Object arg;
+ switch (tag) {
+ case CONSTANT_Utf8:
+ arg = in.readUTF();
+ strings.put((String) arg, (short) size());
+ break;
+ case CONSTANT_Integer:
+ case CONSTANT_Float:
+ arg = in.readInt(); break;
+ case CONSTANT_Long:
+ case CONSTANT_Double:
+ add(new Constant(index, tag, in.readLong()));
+ add(null);
+ return;
+ case CONSTANT_Class:
+ case CONSTANT_String:
+ arg = in.readShort(); break;
+ case CONSTANT_Field:
+ case CONSTANT_Method:
+ case CONSTANT_InterfaceMethod:
+ case CONSTANT_NameAndType:
+ case CONSTANT_InvokeDynamic_17:
+ case CONSTANT_InvokeDynamic:
+ // read an ordered pair
+ arg = new Short[] { in.readShort(), in.readShort() };
+ break;
+ case CONSTANT_MethodHandle:
+ // read an ordered pair; first part is a u1 (not u2)
+ arg = new Object[] { in.readByte(), in.readShort() };
+ break;
+ case CONSTANT_MethodType:
+ arg = in.readShort(); break;
+ default:
+ throw new InternalError("bad CP tag "+tag);
+ }
+ add(new Constant(index, tag, arg));
+ }
+
+ // Access:
+ public Constant get(int index) {
+ // extra 1-bits get into the shorts
+ return super.get((char) index);
+ }
+ String getString(byte tag, short index) {
+ get(index).checkTag(tag);
+ return getString(index);
+ }
+ String getString(short index) {
+ Object v = get(index).item;
+ if (v instanceof Short)
+ v = get((Short)v).checkTag(CONSTANT_Utf8).item;
+ return (String) v;
+ }
+ String[] getStrings(Short[] indexes) {
+ String[] res = new String[indexes.length];
+ for (int i = 0; i < indexes.length; i++)
+ res[i] = getString(indexes[i]);
+ return res;
+ }
+ int stringIndex(String name, boolean createIfNotFound) {
+ Short x = strings.get(name);
+ if (x != null) return (char)(int) x;
+ if (!createIfNotFound) return 0;
+ return addConstant(CONSTANT_Utf8, name).index;
+ }
+ Short[] getMemberRef(short index) {
+ Short[] cls_nnt = get(index).itemIndexes();
+ Short[] name_type = get(cls_nnt[1]).itemIndexes();
+ return new Short[]{ cls_nnt[0], name_type[0], name_type[1] };
+ }
+ }
+
+ public class ClassFile extends Outer implements Chunk {
+ ClassFile(File f) throws IOException {
+ DataInputStream in = openInput(f);
+ try {
+ readFrom(in);
+ } finally {
+ if (in != null) in.close();
+ }
+ }
+
+ public int magic, version; // <min:maj>
+ public final Pool pool = new Pool();
+ public short access, thisc, superc;
+ public final List<Short> interfaces = new CountedList<>(Short.class);
+ public final List<Field> fields = new CountedList<>(Field.class);
+ public final List<Method> methods = new CountedList<>(Method.class);
+ public final List<Attr> attrs = new CountedList<>(Attr.class);
+
+ public final void readFrom(DataInputStream in) throws IOException {
+ magic = in.readInt(); version = in.readInt();
+ if (magic != 0xCAFEBABE) throw new IOException("bad magic number");
+ pool.readFrom(in);
+ Code_index = pool.stringIndex("Code", false);
+ access = in.readShort(); thisc = in.readShort(); superc = in.readShort();
+ readInputs(in, interfaces, fields, methods, attrs);
+ if (in.read() >= 0) throw new IOException("junk after end of file");
+ linkInners();
+ }
+
+ void writeTo(File f) throws IOException {
+ DataOutputStream out = openOutput(f);
+ try {
+ writeTo(out);
+ } finally {
+ out.close();
+ }
+ }
+
+ public void writeTo(DataOutputStream out) throws IOException {
+ writeOutputs(out, magic, version, pool,
+ access, thisc, superc, interfaces,
+ fields, methods, attrs);
+ }
+
+ public byte[] toByteArray() {
+ try {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ writeTo(new DataOutputStream(buf));
+ return buf.toByteArray();
+ } catch (IOException ex) {
+ throw new InternalError();
+ }
+ }
+
+ public List<Inner> inners() {
+ List<Inner> inns = new ArrayList<>();
+ inns.addAll(fields); inns.addAll(methods); inns.addAll(attrs);
+ return inns;
+ }
+ public List<Attr> attrs() { return attrs; }
+
+ // derived stuff:
+ public String nameString() { return pool.getString(CONSTANT_Class, thisc); }
+ int Code_index;
+ }
+
+ private static <T extends Member> T findMember(List<T> mems, int name, int type) {
+ if (name == 0 || type == 0) return null;
+ for (T m : mems) {
+ if (m.name == name && m.type == type) return m;
+ }
+ return null;
+ }
+
+ public static class Member extends InnerOuter implements Chunk {
+ public short access, name, type;
+ public final List<Attr> attrs = new CountedList<>(Attr.class);
+ public void readFrom(DataInputStream in) throws IOException {
+ access = in.readShort(); name = in.readShort(); type = in.readShort();
+ readInputs(in, attrs);
+ }
+ public void writeTo(DataOutputStream out) throws IOException {
+ writeOutputs(out, access, name, type, attrs);
+ }
+ public List<Attr> inners() { return attrs; }
+ public List<Attr> attrs() { return attrs; }
+ public ClassFile outer() { return (ClassFile) outer; }
+ public String nameString() { return outer().pool.getString(CONSTANT_Utf8, name); }
+ public String typeString() { return outer().pool.getString(CONSTANT_Utf8, type); }
+ public String toString() {
+ if (outer == null) return super.toString();
+ return nameString() + (this instanceof Method ? "" : ":")
+ + simplifyType(typeString());
+ }
+ }
+ public static class Field extends Member {
+ }
+ public static class Method extends Member {
+ public Code code() {
+ Attr a = findAttr("Code");
+ if (a == null) return null;
+ return (Code) a.item;
+ }
+ public Instruction instructions() {
+ Code code = code();
+ if (code == null) return null;
+ return code.instructions();
+ }
+ }
+
+ public static class Attr extends InnerOuter implements Chunk {
+ public short name;
+ public int size = -1; // no pre-declared size
+ public Object item;
+
+ public Attr() {}
+ public Attr(Outer outer, String name, Object item) {
+ ClassFile cf = outer.outer(ClassFile.class);
+ linkOuter(outer);
+ this.name = (short) cf.pool.stringIndex(name, true);
+ this.item = item;
+ outer.attrs().add(this);
+ }
+ public void readFrom(DataInputStream in) throws IOException {
+ name = in.readShort();
+ size = in.readInt();
+ item = readRawBytes(in, size);
+ }
+ public void writeTo(DataOutputStream out) throws IOException {
+ out.writeShort(name);
+ // write the 4-byte size header and then the contents:
+ byte[] bytes;
+ int trueSize;
+ if (item instanceof byte[]) {
+ bytes = (byte[]) item;
+ out.writeInt(trueSize = bytes.length);
+ out.write(bytes);
+ } else {
+ trueSize = flatten(out);
+ //if (!(item instanceof Code)) System.err.println("wrote complex attr name="+(int)(char)name+" size="+trueSize+" data="+Arrays.toString(flatten()));
+ }
+ if (trueSize != size && size >= 0)
+ System.err.println("warning: attribute size changed "+size+" to "+trueSize);
+ }
+ public void linkOuter(Outer o) {
+ super.linkOuter(o);
+ if (item instanceof byte[] &&
+ outer instanceof Method &&
+ ((Method)outer).outer().Code_index == name) {
+ item = readInput((byte[])item, Code.class);
+ }
+ }
+ public List<Inner> inners() {
+ if (item instanceof Inner)
+ return Collections.nCopies(1, (Inner)item);
+ return Collections.emptyList();
+ }
+ public List<Attr> attrs() { return null; } // Code overrides this
+ public byte[] flatten() {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
+ flatten(buf);
+ return buf.toByteArray();
+ }
+ public int flatten(DataOutputStream out) throws IOException {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream(Math.max(20, size));
+ int trueSize = flatten(buf);
+ out.writeInt(trueSize);
+ buf.writeTo(out);
+ return trueSize;
+ }
+ private int flatten(ByteArrayOutputStream buf) {
+ try {
+ writeOutput(new DataOutputStream(buf), item);
+ return buf.size();
+ } catch (IOException ex) {
+ throw new InternalError();
+ }
+ }
+ public String nameString() {
+ ClassFile cf = outer(ClassFile.class);
+ if (cf == null) return "#"+name;
+ return cf.pool.getString(name);
+ }
+ public String toString() {
+ return nameString()+(size < 0 ? "=" : "["+size+"]=")+item;
+ }
+ }
+
+ public static class Code extends InnerOuter implements Chunk {
+ public short stacks, locals;
+ public byte[] bytes;
+ public final List<Short[]> etable = new CountedList<>(Short[].class, 4);
+ public final List<Attr> attrs = new CountedList<>(Attr.class);
+ // etable[N] = (N)*{ startpc, endpc, handlerpc, catchtype }
+ public void readFrom(DataInputStream in) throws IOException {
+ stacks = in.readShort(); locals = in.readShort();
+ bytes = readRawBytes(in, in.readInt());
+ readInputs(in, etable, attrs);
+ }
+ public void writeTo(DataOutputStream out) throws IOException {
+ writeOutputs(out, stacks, locals, bytes.length, bytes, etable, attrs);
+ }
+ public List<Attr> inners() { return attrs; }
+ public List<Attr> attrs() { return attrs; }
+ public Instruction instructions() {
+ return new Instruction(bytes, 0);
+ }
+ }
+
+ // lots of constants
+ private static final byte
+ CONSTANT_Utf8 = 1,
+ CONSTANT_Integer = 3,
+ CONSTANT_Float = 4,
+ CONSTANT_Long = 5,
+ CONSTANT_Double = 6,
+ CONSTANT_Class = 7,
+ CONSTANT_String = 8,
+ CONSTANT_Field = 9,
+ CONSTANT_Method = 10,
+ CONSTANT_InterfaceMethod = 11,
+ CONSTANT_NameAndType = 12,
+ CONSTANT_MethodHandle = 15, // JSR 292
+ CONSTANT_MethodType = 16, // JSR 292
+ CONSTANT_InvokeDynamic_17 = 17, // JSR 292, only occurs in old class files
+ CONSTANT_InvokeDynamic = 18; // JSR 292
+ private static final byte
+ REF_getField = 1,
+ REF_getStatic = 2,
+ REF_putField = 3,
+ REF_putStatic = 4,
+ REF_invokeVirtual = 5,
+ REF_invokeStatic = 6,
+ REF_invokeSpecial = 7,
+ REF_newInvokeSpecial = 8,
+ REF_invokeInterface = 9;
+
+ private static final int
+ opc_nop = 0,
+ opc_aconst_null = 1,
+ opc_nconst_MIN = 2, // iconst_m1
+ opc_nconst_MAX = 15, // dconst_1
+ opc_bipush = 16,
+ opc_sipush = 17,
+ opc_ldc = 18,
+ opc_ldc_w = 19,
+ opc_ldc2_w = 20,
+ opc_aload = 25,
+ opc_aload_0 = 42,
+ opc_aload_MAX = 45,
+ opc_aaload = 50,
+ opc_astore = 58,
+ opc_astore_0 = 75,
+ opc_astore_MAX = 78,
+ opc_aastore = 83,
+ opc_pop = 87,
+ opc_pop2 = 88,
+ opc_dup = 89,
+ opc_dup_x1 = 90,
+ opc_dup_x2 = 91,
+ opc_dup2 = 92,
+ opc_dup2_x1 = 93,
+ opc_dup2_x2 = 94,
+ opc_swap = 95,
+ opc_tableswitch = 170,
+ opc_lookupswitch = 171,
+ opc_areturn = 176,
+ opc_getstatic = 178,
+ opc_putstatic = 179,
+ opc_getfield = 180,
+ opc_putfield = 181,
+ opc_invokevirtual = 182,
+ opc_invokespecial = 183,
+ opc_invokestatic = 184,
+ opc_invokeinterface = 185,
+ opc_invokedynamic = 186,
+ opc_new = 187,
+ opc_anewarray = 189,
+ opc_checkcast = 192,
+ opc_ifnull = 198,
+ opc_ifnonnull = 199,
+ opc_wide = 196;
+
+ private static final Object[] INSTRUCTION_CONSTANTS = {
+ -1, 0, 1, 2, 3, 4, 5, 0L, 1L, 0.0F, 1.0F, 2.0F, 0.0D, 1.0D
+ };
+
+ private static final String INSTRUCTION_FORMATS =
+ "nop$ aconst_null$L iconst_m1$I iconst_0$I iconst_1$I "+
+ "iconst_2$I iconst_3$I iconst_4$I iconst_5$I lconst_0$J_ "+
+ "lconst_1$J_ fconst_0$F fconst_1$F fconst_2$F dconst_0$D_ "+
+ "dconst_1$D_ bipush=bx$I sipush=bxx$I ldc=bk$X ldc_w=bkk$X "+
+ "ldc2_w=bkk$X_ iload=bl/wbll$I lload=bl/wbll$J_ fload=bl/wbll$F "+
+ "dload=bl/wbll$D_ aload=bl/wbll$L iload_0$I iload_1$I "+
+ "iload_2$I iload_3$I lload_0$J_ lload_1$J_ lload_2$J_ "+
+ "lload_3$J_ fload_0$F fload_1$F fload_2$F fload_3$F dload_0$D_ "+
+ "dload_1$D_ dload_2$D_ dload_3$D_ aload_0$L aload_1$L "+
+ "aload_2$L aload_3$L iaload$LI$I laload$LI$J_ faload$LI$F "+
+ "daload$LI$D_ aaload$LI$L baload$LI$I caload$LI$I saload$LI$I "+
+ "istore=bl/wbll$I$ lstore=bl/wbll$J_$ fstore=bl/wbll$F$ "+
+ "dstore=bl/wbll$D_$ astore=bl/wbll$L$ istore_0$I$ istore_1$I$ "+
+ "istore_2$I$ istore_3$I$ lstore_0$J_$ lstore_1$J_$ "+
+ "lstore_2$J_$ lstore_3$J_$ fstore_0$F$ fstore_1$F$ fstore_2$F$ "+
+ "fstore_3$F$ dstore_0$D_$ dstore_1$D_$ dstore_2$D_$ "+
+ "dstore_3$D_$ astore_0$L$ astore_1$L$ astore_2$L$ astore_3$L$ "+
+ "iastore$LII$ lastore$LIJ_$ fastore$LIF$ dastore$LID_$ "+
+ "aastore$LIL$ bastore$LII$ castore$LII$ sastore$LII$ pop$X$ "+
+ "pop2$XX$ dup$X$XX dup_x1$XX$XXX dup_x2$XXX$XXXX dup2$XX$XXXX "+
+ "dup2_x1$XXX$XXXXX dup2_x2$XXXX$XXXXXX swap$XX$XX "+
+ "iadd$II$I ladd$J_J_$J_ fadd$FF$F dadd$D_D_$D_ isub$II$I "+
+ "lsub$J_J_$J_ fsub$FF$F dsub$D_D_$D_ imul$II$I lmul$J_J_$J_ "+
+ "fmul$FF$F dmul$D_D_$D_ idiv$II$I ldiv$J_J_$J_ fdiv$FF$F "+
+ "ddiv$D_D_$D_ irem$II$I lrem$J_J_$J_ frem$FF$F drem$D_D_$D_ "+
+ "ineg$I$I lneg$J_$J_ fneg$F$F dneg$D_$D_ ishl$II$I lshl$J_I$J_ "+
+ "ishr$II$I lshr$J_I$J_ iushr$II$I lushr$J_I$J_ iand$II$I "+
+ "land$J_J_$J_ ior$II$I lor$J_J_$J_ ixor$II$I lxor$J_J_$J_ "+
+ "iinc=blx/wbllxx$ i2l$I$J_ i2f$I$F i2d$I$D_ l2i$J_$I l2f$J_$F "+
+ "l2d$J_$D_ f2i$F$I f2l$F$J_ f2d$F$D_ d2i$D_$I d2l$D_$J_ "+
+ "d2f$D_$F i2b$I$I i2c$I$I i2s$I$I lcmp fcmpl fcmpg dcmpl dcmpg "+
+ "ifeq=boo ifne=boo iflt=boo ifge=boo ifgt=boo ifle=boo "+
+ "if_icmpeq=boo if_icmpne=boo if_icmplt=boo if_icmpge=boo "+
+ "if_icmpgt=boo if_icmple=boo if_acmpeq=boo if_acmpne=boo "+
+ "goto=boo jsr=boo ret=bl/wbll tableswitch=* lookupswitch=* "+
+ "ireturn lreturn freturn dreturn areturn return "+
+ "getstatic=bkf$Q putstatic=bkf$Q$ getfield=bkf$L$Q "+
+ "putfield=bkf$LQ$ invokevirtual=bkm$LQ$Q "+
+ "invokespecial=bkm$LQ$Q invokestatic=bkm$Q$Q "+
+ "invokeinterface=bkixx$LQ$Q invokedynamic=bkd__$Q$Q new=bkc$L "+
+ "newarray=bx$I$L anewarray=bkc$I$L arraylength$L$I athrow "+
+ "checkcast=bkc$L$L instanceof=bkc$L$I monitorenter$L "+
+ "monitorexit$L wide=* multianewarray=bkcx ifnull=boo "+
+ "ifnonnull=boo goto_w=boooo jsr_w=boooo ";
+ private static final String[] INSTRUCTION_NAMES;
+ private static final String[] INSTRUCTION_POPS;
+ private static final int[] INSTRUCTION_INFO;
+ static {
+ String[] insns = INSTRUCTION_FORMATS.split(" ");
+ assert(insns[opc_lookupswitch].startsWith("lookupswitch"));
+ assert(insns[opc_tableswitch].startsWith("tableswitch"));
+ assert(insns[opc_wide].startsWith("wide"));
+ assert(insns[opc_invokedynamic].startsWith("invokedynamic"));
+ int[] info = new int[256];
+ String[] names = new String[256];
+ String[] pops = new String[256];
+ for (int i = 0; i < insns.length; i++) {
+ String insn = insns[i];
+ int dl = insn.indexOf('$');
+ if (dl > 0) {
+ String p = insn.substring(dl+1);
+ if (p.indexOf('$') < 0) p = "$" + p;
+ pops[i] = p;
+ insn = insn.substring(0, dl);
+ }
+ int eq = insn.indexOf('=');
+ if (eq < 0) {
+ info[i] = 1;
+ names[i] = insn;
+ continue;
+ }
+ names[i] = insn.substring(0, eq);
+ String fmt = insn.substring(eq+1);
+ if (fmt.equals("*")) {
+ info[i] = 0;
+ continue;
+ }
+ int sl = fmt.indexOf('/');
+ if (sl < 0) {
+ info[i] = (char) fmt.length();
+ } else {
+ String wfmt = fmt.substring(sl+1);
+ fmt = fmt.substring(0, sl);
+ info[i] = (char)( fmt.length() + (wfmt.length() * 16) );
+ }
+ }
+ INSTRUCTION_INFO = info;
+ INSTRUCTION_NAMES = names;
+ INSTRUCTION_POPS = pops;
+ }
+
+ public static class Instruction implements Cloneable {
+ byte[] codeBase;
+ int pc;
+ int bc;
+ int info;
+ int wide;
+ int len;
+ Instruction(byte[] codeBase, int pc) {
+ this.codeBase = codeBase;
+ init(pc);
+ }
+ public Instruction clone() {
+ try {
+ return (Instruction) super.clone();
+ } catch (CloneNotSupportedException ex) {
+ throw new InternalError();
+ }
+ }
+ private Instruction init(int pc) {
+ this.pc = pc;
+ this.bc = codeBase[pc] & 0xFF;
+ this.info = INSTRUCTION_INFO[bc];
+ this.wide = 0;
+ this.len = (info & 0x0F);
+ if (len == 0)
+ computeLength();
+ return this;
+ }
+ Instruction next() {
+ if (len == 0 && bc != 0) throw new InternalError();
+ int npc = pc + len;
+ if (npc == codeBase.length)
+ return null;
+ return init(npc);
+ }
+ void forceNext(int newLen) {
+ bc = opc_nop;
+ len = newLen;
+ }
+
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(pc).append(":").append(INSTRUCTION_NAMES[bc]);
+ switch (len) {
+ case 3: buf.append(" ").append(u2At(1)); break;
+ case 5: buf.append(" ").append(u2At(1)).append(" ").append(u2At(3)); break;
+ default: for (int i = 1; i < len; i++) buf.append(" ").append(u1At(1));
+ }
+ return buf.toString();
+ }
+
+ // these are the hard parts
+ private void computeLength() {
+ int cases;
+ switch (bc) {
+ case opc_wide:
+ bc = codeBase[pc + 1];
+ info = INSTRUCTION_INFO[bc];
+ len = ((info >> 4) & 0x0F);
+ if (len == 0) throw new RuntimeException("misplaced wide bytecode: "+bc);
+ return;
+
+ case opc_tableswitch:
+ cases = (u4At(alignedIntOffset(2)) - u4At(alignedIntOffset(1)) + 1);
+ len = alignedIntOffset(3 + cases*1);
+ return;
+
+ case opc_lookupswitch:
+ cases = u4At(alignedIntOffset(1));
+ len = alignedIntOffset(2 + cases*2);
+ return;
+
+ default:
+ throw new RuntimeException("unknown bytecode: "+bc);
+ }
+ }
+ // switch code
+ // clget the Nth int (where 0 is the first after the opcode itself)
+ public int alignedIntOffset(int n) {
+ int pos = pc + 1;
+ pos += ((-pos) & 0x03); // align it
+ pos += (n * 4);
+ return pos - pc;
+ }
+ public int u1At(int pos) {
+ return (codeBase[pc+pos] & 0xFF);
+ }
+ public int u2At(int pos) {
+ return (u1At(pos+0)<<8) + u1At(pos+1);
+ }
+ public int u4At(int pos) {
+ return (u2At(pos+0)<<16) + u2At(pos+2);
+ }
+ public void u1AtPut(int pos, int x) {
+ codeBase[pc+pos] = (byte)x;
+ }
+ public void u2AtPut(int pos, int x) {
+ codeBase[pc+pos+0] = (byte)(x >> 8);
+ codeBase[pc+pos+1] = (byte)(x >> 0);
+ }
+ }
+
+ static String simplifyType(String type) {
+ String simpleType = OBJ_SIGNATURE.matcher(type).replaceAll("L");
+ assert(simpleType.matches("^\\([A-Z]*\\)[A-Z]$"));
+ // change (DD)D to (D_D_)D_
+ simpleType = WIDE_SIGNATURE.matcher(simpleType).replaceAll("\\0_");
+ return simpleType;
+ }
+ static int argsize(String type) {
+ return simplifyType(type).length()-3;
+ }
+ private static final Pattern OBJ_SIGNATURE = Pattern.compile("\\[*L[^;]*;|\\[+[A-Z]");
+ private static final Pattern WIDE_SIGNATURE = Pattern.compile("[JD]");
+}