提交 c345ae6c 编写于 作者: L lana

Merge

...@@ -247,10 +247,6 @@ class AdapterMethodHandle extends BoundMethodHandle { ...@@ -247,10 +247,6 @@ class AdapterMethodHandle extends BoundMethodHandle {
MethodType needConversion = MethodType.methodType(needReturn, haveReturn); MethodType needConversion = MethodType.methodType(needReturn, haveReturn);
adjustReturn = MethodHandles.identity(needReturn).asType(needConversion); adjustReturn = MethodHandles.identity(needReturn).asType(needConversion);
} }
if (!canCollectArguments(adjustReturn.type(), target.type(), 0, false)) {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
throw new InternalError("NYI");
}
return makeCollectArguments(adjustReturn, target, 0, false); return makeCollectArguments(adjustReturn, target, 0, false);
} }
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
/*
* 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
String debugString() {
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;
}
static {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
}
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);
// }
}
/*
* 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);
}
static {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
}
/**
* 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);
} else {
assert(tret == double.class ? iret == long.class : iret == int.class);
return ValueConversions.boxRaw(wrap);
}
}
/**
* 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(), 0);
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 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 "+internalType);
}
/**
* 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
String debugString() {
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)); }
}
}
...@@ -102,7 +102,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -102,7 +102,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MethodType rawConType = rawConstructor.type(); MethodType rawConType = rawConstructor.type();
Class<?> allocateClass = rawConType.parameterType(0); Class<?> allocateClass = rawConType.parameterType(0);
// Wrap the raw (unsafe) constructor with the allocation of a suitable object. // Wrap the raw (unsafe) constructor with the allocation of a suitable object.
if (AdapterMethodHandle.canCollectArguments(rawConType, MethodType.methodType(allocateClass), 0, true)) { assert(AdapterMethodHandle.canCollectArguments(rawConType, MethodType.methodType(allocateClass), 0, true));
// allocator(arg...) // allocator(arg...)
// [fold]=> cookedConstructor(obj=allocate(C), arg...) // [fold]=> cookedConstructor(obj=allocate(C), arg...)
// [dup,collect]=> identity(obj, void=rawConstructor(obj, arg...)) // [dup,collect]=> identity(obj, void=rawConstructor(obj, arg...))
...@@ -119,155 +119,29 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -119,155 +119,29 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MethodHandle fold = foldArguments(cookedConstructor, ctype, 0, allocator); MethodHandle fold = foldArguments(cookedConstructor, ctype, 0, allocator);
return fold; return fold;
} }
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
MethodHandle allocator
= AllocateObject.make(allocateClass, rawConstructor);
assert(allocator.type()
.equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
return allocator;
}
static final class AllocateObject<C> extends BoundMethodHandle { static final class AllocateObject<C> extends BoundMethodHandle {
private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final Unsafe unsafe = Unsafe.getUnsafe();
private final Class<C> allocateClass; 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;
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
}
// for allocation only: // for allocation only:
private AllocateObject(Class<C> allocateClass) { private AllocateObject(Class<C> allocateClass) {
super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class))); super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class)));
this.allocateClass = allocateClass; this.allocateClass = allocateClass;
this.rawConstructor = null;
}
static MethodHandle make(Class<?> allocateClass, MethodHandle rawConstructor) {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
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, 0);
if (gcon == null) return null;
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
assert(galloc.type() == newType.generic());
return convertArguments(galloc, newType, galloc.type(), 0);
} else {
MethodHandle invoke = VARARGS_INVOKE;
MethodType conType = CON_TYPES[nargs];
MethodHandle gcon = spreadArgumentsFromPos(rawConstructor, conType, 1);
if (gcon == null) return null;
MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
return collectArguments(galloc, newType, 1, null);
}
}
@Override
String debugString() {
return addTypeString(allocateClass.getSimpleName(), this);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private C allocate() throws InstantiationException { private C allocate() throws InstantiationException {
return (C) unsafe.allocateInstance(allocateClass); 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 final MethodHandle ALLOCATE; static final MethodHandle ALLOCATE;
static { static {
try { try {
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
ALLOCATE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "allocate", MethodType.genericMethodType(0)); ALLOCATE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "allocate", MethodType.genericMethodType(0));
} catch (ReflectiveOperationException ex) { } catch (ReflectiveOperationException ex) {
throw uncaughtException(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 static
...@@ -757,26 +631,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -757,26 +631,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
return target; return target;
if (oldType.parameterCount() != newType.parameterCount()) if (oldType.parameterCount() != newType.parameterCount())
throw newIllegalArgumentException("mismatched parameter count", oldType, newType); throw newIllegalArgumentException("mismatched parameter count", oldType, newType);
MethodHandle res = AdapterMethodHandle.makePairwiseConvert(newType, target, level); return AdapterMethodHandle.makePairwiseConvert(newType, target, level);
if (res != null)
return res;
// We can come here in the case of target(int)void => (Object)void,
// because the unboxing logic for Object => int is complex.
int argc = oldType.parameterCount();
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
// 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, level);
if (objTarget == null)
objTarget = FromGeneric.make(target);
res = AdapterMethodHandle.makePairwiseConvert(newType, objTarget, level);
if (res != null)
return res;
return ToGeneric.make(newType, objTarget);
} }
static MethodHandle spreadArguments(MethodHandle target, Class<?> arrayType, int arrayLength) { static MethodHandle spreadArguments(MethodHandle target, Class<?> arrayType, int arrayLength) {
...@@ -829,19 +684,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -829,19 +684,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
// oldType // (a..., b...)=>r // oldType // (a..., b...)=>r
assert(newType.parameterCount() == collectArg + colType.parameterCount()); assert(newType.parameterCount() == collectArg + colType.parameterCount());
assert(oldType.parameterCount() == collectArg + 1); assert(oldType.parameterCount() == collectArg + 1);
MethodHandle result = null; assert(AdapterMethodHandle.canCollectArguments(oldType, colType, collectArg, false));
if (AdapterMethodHandle.canCollectArguments(oldType, colType, collectArg, false)) { return AdapterMethodHandle.makeCollectArguments(target, collector, collectArg, false);
result = AdapterMethodHandle.makeCollectArguments(target, collector, collectArg, false);
}
if (result == null) {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, 0);
MethodHandle gcollector = convertArguments(collector, colType.generic(), colType, 0);
if (gtarget == null || gcollector == null) return null;
MethodHandle gresult = FilterGeneric.makeArgumentCollector(gcollector, gtarget);
result = convertArguments(gresult, newType, gresult.type(), 0);
}
return result;
} }
static MethodHandle filterArgument(MethodHandle target, static MethodHandle filterArgument(MethodHandle target,
...@@ -850,32 +694,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -850,32 +694,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MethodType ttype = target.type(); MethodType ttype = target.type();
MethodType ftype = filter.type(); MethodType ftype = filter.type();
assert(ftype.parameterCount() == 1); assert(ftype.parameterCount() == 1);
MethodHandle result = null; return AdapterMethodHandle.makeCollectArguments(target, filter, pos, false);
if (AdapterMethodHandle.canCollectArguments(ttype, ftype, pos, false)) {
result = AdapterMethodHandle.makeCollectArguments(target, filter, pos, false);
if (result != null) return result;
}
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
MethodType rtype = ttype.changeParameterType(pos, ftype.parameterType(0));
MethodType gttype = ttype.generic();
if (ttype != gttype) {
target = convertArguments(target, gttype, ttype, 0);
ttype = gttype;
}
MethodType gftype = ftype.generic();
if (ftype != gftype) {
filter = convertArguments(filter, gftype, ftype, 0);
ftype = gftype;
}
if (ftype == ttype) {
// simple unary case
result = FilterOneArgument.make(filter, target);
} else {
result = FilterGeneric.makeArgumentFilter(pos, filter, target);
}
if (result.type() != rtype)
result = result.asType(rtype);
return result;
} }
static MethodHandle foldArguments(MethodHandle target, static MethodHandle foldArguments(MethodHandle target,
...@@ -884,155 +703,15 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -884,155 +703,15 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MethodHandle combiner) { MethodHandle combiner) {
MethodType oldType = target.type(); MethodType oldType = target.type();
MethodType ctype = combiner.type(); MethodType ctype = combiner.type();
if (AdapterMethodHandle.canCollectArguments(oldType, ctype, foldPos, true)) { assert(AdapterMethodHandle.canCollectArguments(oldType, ctype, foldPos, true));
MethodHandle res = AdapterMethodHandle.makeCollectArguments(target, combiner, foldPos, true); return AdapterMethodHandle.makeCollectArguments(target, combiner, foldPos, true);
if (res != null) return res;
}
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
if (foldPos != 0) return null;
MethodHandle gtarget = convertArguments(target, oldType.generic(), oldType, 0);
MethodHandle gcombiner = convertArguments(combiner, ctype.generic(), ctype, 0);
if (ctype.returnType() == void.class) {
gtarget = dropArguments(gtarget, oldType.generic().insertParameterTypes(foldPos, Object.class), foldPos);
}
if (gtarget == null || gcombiner == null) return null;
MethodHandle gresult = FilterGeneric.makeArgumentFolder(gcombiner, gtarget);
return convertArguments(gresult, newType, gresult.type(), 0);
} }
static static
MethodHandle dropArguments(MethodHandle target, MethodHandle dropArguments(MethodHandle target,
MethodType newType, int argnum) { MethodType newType, int argnum) {
int drops = newType.parameterCount() - target.type().parameterCount(); int drops = newType.parameterCount() - target.type().parameterCount();
MethodHandle res = AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops); return 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 boolean preferRicochetFrame(MethodType type) {
return true; // always use RF if available
}
static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) {
MethodType type = target.type();
int nargs = type.parameterCount();
if (nargs < INVOKES.length) {
if (preferRicochetFrame(type))
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
MethodHandle invoke = INVOKES[nargs];
MethodType gtype = type.generic();
assert(invoke.type().dropParameterTypes(0,1) == gtype);
// Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
MethodHandle gtest = convertArguments(test, gtype.changeReturnType(boolean.class), test.type(), 2);
MethodHandle gtarget = convertArguments(target, gtype, type, 2);
MethodHandle gfallback = convertArguments(fallback, gtype, type, 2);
if (gtest == null || gtarget == null || gfallback == null) return null;
MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
return convertArguments(gguard, type, gtype, 2);
} else {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
MethodHandle invoke = VARARGS_INVOKE;
MethodType gtype = MethodType.genericMethodType(1);
assert(invoke.type().dropParameterTypes(0,1) == gtype);
MethodHandle gtest = spreadArgumentsFromPos(test, gtype.changeReturnType(boolean.class), 0);
MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0);
MethodHandle gfallback = spreadArgumentsFromPos(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
String debugString() {
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 static
...@@ -1065,8 +744,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -1065,8 +744,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
assert(test.type().returnType() == boolean.class); assert(test.type().returnType() == boolean.class);
MethodType targetType = target.type(); MethodType targetType = target.type();
MethodType foldTargetType = targetType.insertParameterTypes(0, boolean.class); MethodType foldTargetType = targetType.insertParameterTypes(0, boolean.class);
if (AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true) assert(AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true));
&& GuardWithTest.preferRicochetFrame(targetType)) {
// working backwards, as usual: // working backwards, as usual:
assert(target.type().equals(fallback.type())); assert(target.type().equals(fallback.type()));
MethodHandle tailcall = MethodHandles.exactInvoker(target.type()); MethodHandle tailcall = MethodHandles.exactInvoker(target.type());
...@@ -1079,8 +757,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -1079,8 +757,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test); MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test);
return fold; return fold;
} }
return GuardWithTest.make(test, target, fallback);
}
private static class GuardWithCatch extends BoundMethodHandle { private static class GuardWithCatch extends BoundMethodHandle {
private final MethodHandle target; private final MethodHandle target;
......
...@@ -391,13 +391,4 @@ class MethodHandleNatives { ...@@ -391,13 +391,4 @@ class MethodHandleNatives {
throw err; throw err;
} }
} }
/**
* This assertion marks code which was written before ricochet frames were implemented.
* Such code will go away when the ports catch up.
*/
static boolean workaroundWithoutRicochetFrames() {
assert(!HAVE_RICOCHET_FRAMES) : "this code should not be executed if `-XX:+UseRicochetFrames is enabled";
return true;
}
} }
...@@ -27,6 +27,7 @@ package java.lang.invoke; ...@@ -27,6 +27,7 @@ package java.lang.invoke;
import java.lang.reflect.*; import java.lang.reflect.*;
import sun.invoke.WrapperInstance; import sun.invoke.WrapperInstance;
import java.util.ArrayList;
/** /**
* This class consists exclusively of static methods that help adapt * This class consists exclusively of static methods that help adapt
...@@ -134,14 +135,19 @@ public class MethodHandleProxies { ...@@ -134,14 +135,19 @@ public class MethodHandleProxies {
// //
public static public static
<T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) { <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
// POC implementation only; violates the above contract several ways if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
final Method sm = getSingleMethod(intfc); throw new IllegalArgumentException("not a public interface: "+intfc.getName());
if (sm == null) final Method[] methods = getSingleNameMethods(intfc);
if (methods == null)
throw new IllegalArgumentException("not a single-method interface: "+intfc.getName()); throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
final MethodHandle[] vaTargets = new MethodHandle[methods.length];
for (int i = 0; i < methods.length; i++) {
Method sm = methods[i];
MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes()); MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
MethodHandle checkTarget = target.asType(smMT); // make throw WMT MethodHandle checkTarget = target.asType(smMT); // make throw WMT
checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class)); checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
final MethodHandle vaTarget = checkTarget.asSpreader(Object[].class, smMT.parameterCount()); vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
}
return intfc.cast(Proxy.newProxyInstance( return intfc.cast(Proxy.newProxyInstance(
intfc.getClassLoader(), intfc.getClassLoader(),
new Class[]{ intfc, WrapperInstance.class }, new Class[]{ intfc, WrapperInstance.class },
...@@ -152,13 +158,15 @@ public class MethodHandleProxies { ...@@ -152,13 +158,15 @@ public class MethodHandleProxies {
throw new AssertionError(); throw new AssertionError();
} }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
for (int i = 0; i < methods.length; i++) {
if (method.equals(methods[i]))
return vaTargets[i].invokeExact(args);
}
if (method.getDeclaringClass() == WrapperInstance.class) if (method.getDeclaringClass() == WrapperInstance.class)
return getArg(method.getName()); return getArg(method.getName());
if (method.equals(sm))
return vaTarget.invokeExact(args);
if (isObjectMethod(method)) if (isObjectMethod(method))
return callObjectMethod(this, method, args); return callObjectMethod(proxy, method, args);
throw new InternalError(); throw new InternalError("bad proxy method: "+method);
} }
})); }));
} }
...@@ -241,17 +249,20 @@ public class MethodHandleProxies { ...@@ -241,17 +249,20 @@ public class MethodHandleProxies {
} }
private static private static
Method getSingleMethod(Class<?> intfc) { Method[] getSingleNameMethods(Class<?> intfc) {
if (!intfc.isInterface()) return null; ArrayList<Method> methods = new ArrayList<Method>();
Method sm = null; String uniqueName = null;
for (Method m : intfc.getMethods()) { for (Method m : intfc.getMethods()) {
int mod = m.getModifiers(); if (isObjectMethod(m)) continue;
if (Modifier.isAbstract(mod)) { if (!Modifier.isAbstract(m.getModifiers())) continue;
if (sm != null && !isObjectMethod(sm)) String mname = m.getName();
if (uniqueName == null)
uniqueName = mname;
else if (!uniqueName.equals(mname))
return null; // too many abstract methods return null; // too many abstract methods
sm = m; methods.add(m);
}
} }
return sm; if (uniqueName == null) return null;
return methods.toArray(new Method[methods.size()]);
} }
} }
...@@ -1995,16 +1995,8 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2 ...@@ -1995,16 +1995,8 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
// lambda( arg...) { target(arg...) } ) // lambda( arg...) { target(arg...) } )
MethodType newType = targetType.changeReturnType(filterType.returnType()); MethodType newType = targetType.changeReturnType(filterType.returnType());
MethodHandle result = null; MethodHandle result = null;
if (AdapterMethodHandle.canCollectArguments(filterType, targetType, 0, false)) { assert(AdapterMethodHandle.canCollectArguments(filterType, targetType, 0, false));
result = AdapterMethodHandle.makeCollectArguments(filter, target, 0, false); return AdapterMethodHandle.makeCollectArguments(filter, target, 0, false);
if (result != null) return result;
}
// FIXME: Too many nodes here.
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
MethodHandle returner = dropArguments(filter, filterValues, targetType.parameterList());
result = foldArguments(returner, target);
assert(result.type().equals(newType));
return result;
} }
/** /**
......
...@@ -56,10 +56,6 @@ class MethodTypeForm { ...@@ -56,10 +56,6 @@ class MethodTypeForm {
/*lazy*/ MethodType primsAtEnd; // reorder primitives to the end /*lazy*/ MethodType primsAtEnd; // reorder primitives to the end
// Cached adapter information: // 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 inexact invoke /*lazy*/ MethodHandle genericInvoker; // hook for inexact invoke
public MethodType erasedType() { public MethodType erasedType() {
......
/*
* 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];
}
static {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
}
/** 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;
}
String debugString() {
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
String debugString() {
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)); }
}
}
/*
* 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.permuteArguments(
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, 0);
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);
}
static {
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this class is deprecated
}
/** 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);
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);
} else if (tret == rret) {
return ValueConversions.unbox(tret);
} else {
assert(rret.isPrimitive());
assert(tret == double.class ? rret == long.class : rret == int.class);
return ValueConversions.unboxRaw(tret);
}
}
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;
}
String debugString() {
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: "+entryPointType);
}
/**
* 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
String debugString() {
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)); }
}
}
...@@ -127,12 +127,8 @@ public abstract class RenderingEngine { ...@@ -127,12 +127,8 @@ public abstract class RenderingEngine {
try { try {
Class cls = Class.forName(ductusREClass); Class cls = Class.forName(ductusREClass);
return cls.newInstance(); return cls.newInstance();
} catch (ClassNotFoundException x) { } catch (ReflectiveOperationException ignored) {
// not found // not found
} catch (IllegalAccessException x) {
// should not reach here
} catch (InstantiationException x) {
// should not reach here
} }
} }
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
extern "C" { extern "C" {
#endif #endif
#include <stddef.h>
#include "java_awt_AlphaComposite.h" #include "java_awt_AlphaComposite.h"
#include "SurfaceData.h" #include "SurfaceData.h"
...@@ -484,7 +486,9 @@ extern struct _CompositeTypes { ...@@ -484,7 +486,9 @@ extern struct _CompositeTypes {
#define ArraySize(A) (sizeof(A) / sizeof(A[0])) #define ArraySize(A) (sizeof(A) / sizeof(A[0]))
#define PtrAddBytes(p, b) ((void *) (((intptr_t) (p)) + (b))) #define PtrAddBytes(p, b) ((void *) (((intptr_t) (p)) + (b)))
#define PtrCoord(p, x, xinc, y, yinc) PtrAddBytes(p, (y)*(yinc) + (x)*(xinc)) #define PtrCoord(p, x, xinc, y, yinc) PtrAddBytes(p, \
((ptrdiff_t)(y))*(yinc) + \
((ptrdiff_t)(x))*(xinc))
/* /*
* The function to call with an array of NativePrimitive structures * The function to call with an array of NativePrimitive structures
......
...@@ -347,6 +347,11 @@ public class FontConfigManager { ...@@ -347,6 +347,11 @@ public class FontConfigManager {
name = name.toLowerCase(); name = name.toLowerCase();
initFontConfigFonts(false); initFontConfigFonts(false);
if (fontConfigFonts == null) {
// This avoids an immediate NPE if fontconfig look up failed
// but doesn't guarantee this is a recoverable situation.
return null;
}
FcCompFont fcInfo = null; FcCompFont fcInfo = null;
for (int i=0; i<fontConfigFonts.length; i++) { for (int i=0; i<fontConfigFonts.length; i++) {
......
...@@ -69,6 +69,7 @@ public class JavaDocExamplesTest { ...@@ -69,6 +69,7 @@ public class JavaDocExamplesTest {
testDropArguments(); testDropArguments();
testFilterArguments(); testFilterArguments();
testFoldArguments(); testFoldArguments();
testFoldArguments2();
testMethodHandlesSummary(); testMethodHandlesSummary();
testAsSpreader(); testAsSpreader();
testAsCollector(); testAsCollector();
...@@ -490,6 +491,47 @@ assertEquals("hodmet", (String) worker.invokeExact("met", "hod")); ...@@ -490,6 +491,47 @@ assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
}} }}
} }
@Test public void testFoldArguments2() throws Throwable {
{{
{} /// JAVADOC
// argument-based dispatch for methods of the form boolean x.___(y: String)
Lookup lookup = publicLookup();
// first, a tracing hack:
MethodHandle println = lookup.findVirtual(java.io.PrintStream.class, "println", methodType(void.class, String.class));
MethodHandle arrayToString = lookup.findStatic(Arrays.class, "toString", methodType(String.class, Object[].class));
MethodHandle concat = lookup.findVirtual(String.class, "concat", methodType(String.class, String.class));
MethodHandle arrayToString_DIS = filterReturnValue(arrayToString, concat.bindTo("DIS:"));
MethodHandle arrayToString_INV = filterReturnValue(arrayToString, concat.bindTo("INV:"));
MethodHandle printArgs_DIS = filterReturnValue(arrayToString_DIS, println.bindTo(System.out)).asVarargsCollector(Object[].class);
MethodHandle printArgs_INV = filterReturnValue(arrayToString_INV, println.bindTo(System.out)).asVarargsCollector(Object[].class);
// metaobject protocol:
MethodType mtype = methodType(boolean.class, String.class);
MethodHandle findVirtual = lookup.findVirtual(Lookup.class,
"findVirtual", methodType(MethodHandle.class, Class.class, String.class, MethodType.class));
MethodHandle getClass = lookup.findVirtual(Object.class,
"getClass", methodType(Class.class));
MethodHandle dispatch = findVirtual;
dispatch = filterArguments(dispatch, 1, getClass);
dispatch = insertArguments(dispatch, 3, mtype);
dispatch = dispatch.bindTo(lookup);
assertEquals(methodType(MethodHandle.class, Object.class, String.class), dispatch.type());
MethodHandle invoker = invoker(mtype.insertParameterTypes(0, Object.class));
// wrap tracing around the dispatch and invoke steps:
dispatch = foldArguments(dispatch, printArgs_DIS.asType(dispatch.type().changeReturnType(void.class)));
invoker = foldArguments(invoker, printArgs_INV.asType(invoker.type().changeReturnType(void.class)));
invoker = dropArguments(invoker, 2, String.class); // ignore selector
// compose the dispatcher and the invoker:
MethodHandle invokeDispatched = foldArguments(invoker, dispatch);
Object x = "football", y = new java.util.Scanner("bar");
assert( (boolean) invokeDispatched.invokeExact(x, "startsWith", "foo"));
assert(!(boolean) invokeDispatched.invokeExact(x, "startsWith", "#"));
assert( (boolean) invokeDispatched.invokeExact(x, "endsWith", "all"));
assert(!(boolean) invokeDispatched.invokeExact(x, "endsWith", "foo"));
assert( (boolean) invokeDispatched.invokeExact(y, "hasNext", "[abc]+[rst]"));
assert(!(boolean) invokeDispatched.invokeExact(y, "hasNext", "[123]+[789]"));
}}
}
/* ---- TEMPLATE ---- /* ---- TEMPLATE ----
@Test public void testFoo() throws Throwable { @Test public void testFoo() throws Throwable {
{{ {{
......
...@@ -37,7 +37,6 @@ import java.lang.reflect.*; ...@@ -37,7 +37,6 @@ import java.lang.reflect.*;
import java.util.*; import java.util.*;
import org.junit.*; import org.junit.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.junit.Assume.*;
/** /**
...@@ -45,10 +44,13 @@ import static org.junit.Assume.*; ...@@ -45,10 +44,13 @@ import static org.junit.Assume.*;
* @author jrose * @author jrose
*/ */
public class MethodHandlesTest { public class MethodHandlesTest {
static final Class<?> THIS_CLASS = MethodHandlesTest.class;
// How much output? // How much output?
static int verbosity = 0; static int verbosity = 0;
static { static {
String vstr = System.getProperty("test.java.lang.invoke.MethodHandlesTest.verbosity"); String vstr = System.getProperty(THIS_CLASS.getSimpleName()+".verbosity");
if (vstr == null)
vstr = System.getProperty(THIS_CLASS.getName()+".verbosity");
if (vstr != null) verbosity = Integer.parseInt(vstr); if (vstr != null) verbosity = Integer.parseInt(vstr);
} }
...@@ -58,9 +60,9 @@ public class MethodHandlesTest { ...@@ -58,9 +60,9 @@ public class MethodHandlesTest {
static boolean CAN_SKIP_WORKING = false; static boolean CAN_SKIP_WORKING = false;
//static { CAN_SKIP_WORKING = true; } //static { CAN_SKIP_WORKING = true; }
// Set true to test more calls. If false, some tests are just // Set 'true' to do about 15x fewer tests, especially those redundant with RicochetTest.
// lookups, without exercising the actual method handle. // This might be useful with -Xcomp stress tests that compile all method handles.
static boolean DO_MORE_CALLS = true; static boolean CAN_TEST_LIGHTLY = Boolean.getBoolean(THIS_CLASS.getName()+".CAN_TEST_LIGHTLY");
@Test @Test
public void testFirst() throws Throwable { public void testFirst() throws Throwable {
...@@ -70,37 +72,37 @@ public class MethodHandlesTest { ...@@ -70,37 +72,37 @@ public class MethodHandlesTest {
} }
// current failures // current failures
@Test @Ignore("failure in call to makeRawRetypeOnly in ToGeneric") @Test //@Ignore("failure in call to makeRawRetypeOnly in ToGeneric")
public void testFail_1() throws Throwable { public void testFail_1() throws Throwable {
// AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters // AMH.<init>: IllegalArgumentException: bad adapter (conversion=0xfffab300): adapter pushes too many parameters
testSpreadArguments(int.class, 0, 6); testSpreadArguments(int.class, 0, 6);
} }
@Test @Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args") @Test //@Ignore("failure in JVM when expanding the stack using asm stub for _adapter_spread_args")
public void testFail_2() throws Throwable { public void testFail_2() throws Throwable {
// if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes: // if CONV_OP_IMPLEMENTED_MASK includes OP_SPREAD_ARGS, this crashes:
testSpreadArguments(Object.class, 0, 2); testSpreadArguments(Object.class, 0, 2);
} }
@Test @Ignore("IllArgEx failure in call to ToGeneric.make") @Test //@Ignore("IllArgEx failure in call to ToGeneric.make")
public void testFail_3() throws Throwable { public void testFail_3() throws Throwable {
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
testSpreadArguments(int.class, 1, 2); testSpreadArguments(int.class, 1, 2);
} }
@Test @Ignore("IllArgEx failure in call to ToGeneric.make") @Test //@Ignore("IllArgEx failure in call to ToGeneric.make")
public void testFail_4() throws Throwable { public void testFail_4() throws Throwable {
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object // ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object
testCollectArguments(int.class, 1, 2); testCollectArguments(int.class, 1, 2);
} }
@Test @Ignore("cannot collect leading primitive types") @Test //@Ignore("cannot collect leading primitive types")
public void testFail_5() throws Throwable { public void testFail_5() throws Throwable {
// ToGeneric.<init>: UnsupportedOperationException: NYI: primitive parameters must follow references; entryType = (int,java.lang.Object)java.lang.Object // 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)); testInvokers(MethodType.genericMethodType(2).changeParameterType(0, int.class));
} }
@Test @Ignore("should not insert arguments beyond MethodHandlePushLimit") @Test //@Ignore("should not insert arguments beyond MethodHandlePushLimit")
public void testFail_6() throws Throwable { public void testFail_6() throws Throwable {
// ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13 // ValueConversions.varargsArray: UnsupportedOperationException: NYI: cannot form a varargs array of length 13
testInsertArguments(0, 0, MAX_ARG_INCREASE+10); testInsertArguments(0, 0, MAX_ARG_INCREASE+10);
} }
@Test @Ignore("permuteArguments has trouble with double slots") @Test //@Ignore("permuteArguments has trouble with double slots")
public void testFail_7() throws Throwable { public void testFail_7() throws Throwable {
testPermuteArguments(new Object[]{10, 200L}, testPermuteArguments(new Object[]{10, 200L},
new Class<?>[]{Integer.class, long.class}, new Class<?>[]{Integer.class, long.class},
...@@ -123,7 +125,7 @@ public class MethodHandlesTest { ...@@ -123,7 +125,7 @@ public class MethodHandlesTest {
testPermuteArguments(new Object[]{10, 200L, 5000L}, testPermuteArguments(new Object[]{10, 200L, 5000L},
new Class<?>[]{Integer.class, long.class, long.class}, new Class<?>[]{Integer.class, long.class, long.class},
new int[]{2,2,0,1}); new int[]{2,2,0,1});
testPermuteArguments(4, Integer.class, 2, long.class, 6); //testPermuteArguments(4, Integer.class, 2, long.class, 6);
} }
static final int MAX_ARG_INCREASE = 3; static final int MAX_ARG_INCREASE = 3;
...@@ -167,7 +169,7 @@ public class MethodHandlesTest { ...@@ -167,7 +169,7 @@ public class MethodHandlesTest {
@AfterClass @AfterClass
public static void tearDownClass() throws Exception { public static void tearDownClass() throws Exception {
int posTests = allPosTests, negTests = allNegTests; int posTests = allPosTests, negTests = allNegTests;
if (verbosity >= 2 && (posTests | negTests) != 0) { if (verbosity >= 0 && (posTests | negTests) != 0) {
System.out.println(); System.out.println();
if (posTests != 0) System.out.println("=== "+posTests+" total positive test cases"); if (posTests != 0) System.out.println("=== "+posTests+" total positive test cases");
if (negTests != 0) System.out.println("=== "+negTests+" total negative test cases"); if (negTests != 0) System.out.println("=== "+negTests+" total negative test cases");
...@@ -383,6 +385,13 @@ public class MethodHandlesTest { ...@@ -383,6 +385,13 @@ public class MethodHandlesTest {
MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes); MethodType ttype2 = MethodType.methodType(targetType.returnType(), argTypes);
return target.asType(ttype2); return target.asType(ttype2);
} }
static MethodHandle addTrailingArgs(MethodHandle target, int nargs, Class<?> argClass) {
int targetLen = target.type().parameterCount();
int extra = (nargs - targetLen);
if (extra <= 0) return target;
List<Class<?>> fakeArgs = Collections.<Class<?>>nCopies(extra, argClass);
return MethodHandles.dropArguments(target, targetLen, fakeArgs);
}
// This lookup is good for all members in and under MethodHandlesTest. // This lookup is good for all members in and under MethodHandlesTest.
static final Lookup PRIVATE = MethodHandles.lookup(); static final Lookup PRIVATE = MethodHandles.lookup();
...@@ -419,6 +428,10 @@ public class MethodHandlesTest { ...@@ -419,6 +428,10 @@ public class MethodHandlesTest {
public static Object s6(int x, long y) { return called("s6", 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); } public static Object s7(float x, double y) { return called("s7", x, y); }
// for testing findConstructor:
public Example(String x, int y) { this.name = x+y; called("Example.<init>", x, y); }
public Example(int x, String y) { this.name = x+y; called("Example.<init>", x, y); }
static final Lookup EXAMPLE = MethodHandles.lookup(); // for testing findSpecial static final Lookup EXAMPLE = MethodHandles.lookup(); // for testing findSpecial
} }
static final Lookup EXAMPLE = Example.EXAMPLE; static final Lookup EXAMPLE = Example.EXAMPLE;
...@@ -521,7 +534,6 @@ public class MethodHandlesTest { ...@@ -521,7 +534,6 @@ public class MethodHandlesTest {
if (!positive) return; // negative test failed as expected if (!positive) return; // negative test failed as expected
assertEquals(type, target.type()); assertEquals(type, target.type());
assertNameStringContains(target, name); assertNameStringContains(target, name);
if (!DO_MORE_CALLS && lookup != PRIVATE) return;
Object[] args = randomArgs(params); Object[] args = randomArgs(params);
printCalled(target, name, args); printCalled(target, name, args);
target.invokeWithArguments(args); target.invokeWithArguments(args);
...@@ -604,7 +616,6 @@ public class MethodHandlesTest { ...@@ -604,7 +616,6 @@ public class MethodHandlesTest {
MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
assertEquals(typeWithSelf, target.type()); assertEquals(typeWithSelf, target.type());
assertNameStringContains(target, methodName); assertNameStringContains(target, methodName);
if (!DO_MORE_CALLS && lookup != PRIVATE) return;
Object[] argsWithSelf = randomArgs(paramsWithSelf); Object[] argsWithSelf = randomArgs(paramsWithSelf);
if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc); if (rcvc != defc) argsWithSelf[0] = randomArg(rcvc);
printCalled(target, name, argsWithSelf); printCalled(target, name, argsWithSelf);
...@@ -666,13 +677,49 @@ public class MethodHandlesTest { ...@@ -666,13 +677,49 @@ public class MethodHandlesTest {
Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params); Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)specialCaller), params);
MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
assertNameStringContains(target, name); assertNameStringContains(target, name);
if (!DO_MORE_CALLS && lookup != PRIVATE && lookup != EXAMPLE) return;
Object[] args = randomArgs(paramsWithSelf); Object[] args = randomArgs(paramsWithSelf);
printCalled(target, name, args); printCalled(target, name, args);
target.invokeWithArguments(args); target.invokeWithArguments(args);
assertCalled(name, args); assertCalled(name, args);
} }
@Test
public void testFindConstructor() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("findConstructor");
testFindConstructor(true, EXAMPLE, Example.class);
testFindConstructor(true, EXAMPLE, Example.class, int.class);
testFindConstructor(true, EXAMPLE, Example.class, String.class);
}
void testFindConstructor(boolean positive, Lookup lookup,
Class<?> defc, Class<?>... params) throws Throwable {
countTest(positive);
MethodType type = MethodType.methodType(void.class, params);
MethodHandle target = null;
Exception noAccess = null;
try {
if (verbosity >= 4) System.out.println("lookup via "+lookup+" of "+defc+" <init>"+type);
target = lookup.findConstructor(defc, type);
} catch (ReflectiveOperationException ex) {
noAccess = ex;
assertTrue(noAccess instanceof IllegalAccessException);
}
if (verbosity >= 3)
System.out.println("findConstructor "+defc.getName()+".<init>/"+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(type.changeReturnType(defc), target.type());
Object[] args = randomArgs(params);
printCalled(target, defc.getSimpleName(), args);
Object obj = target.invokeWithArguments(args);
if (!(defc == Example.class && params.length < 2))
assertCalled(defc.getSimpleName()+".<init>", args);
assertTrue("instance of "+defc.getName(), defc.isInstance(obj));
}
@Test @Test
public void testBind() throws Throwable { public void testBind() throws Throwable {
if (CAN_SKIP_WORKING) return; if (CAN_SKIP_WORKING) return;
...@@ -956,6 +1003,8 @@ public class MethodHandlesTest { ...@@ -956,6 +1003,8 @@ public class MethodHandlesTest {
public void testAccessor(boolean positive, MethodHandles.Lookup lookup, public void testAccessor(boolean positive, MethodHandles.Lookup lookup,
Object fieldRef, Object value, int testMode0) throws Throwable { Object fieldRef, Object value, int testMode0) throws Throwable {
if (verbosity >= 4)
System.out.println("testAccessor"+Arrays.asList(positive, lookup, fieldRef, value, testMode0));
boolean isGetter = ((testMode0 & TEST_SETTER) == 0); boolean isGetter = ((testMode0 & TEST_SETTER) == 0);
int testMode = testMode0 & ~TEST_SETTER; int testMode = testMode0 & ~TEST_SETTER;
boolean isStatic; boolean isStatic;
...@@ -1150,7 +1199,7 @@ public class MethodHandlesTest { ...@@ -1150,7 +1199,7 @@ public class MethodHandlesTest {
public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable { public void testArrayElementGetterSetter(Object array, boolean testSetter) throws Throwable {
countTest(true); countTest(true);
if (verbosity >= 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]"); if (verbosity > 2) System.out.println("array type = "+array.getClass().getComponentType().getName()+"["+Array.getLength(array)+"]");
Class<?> arrayType = array.getClass(); Class<?> arrayType = array.getClass();
Class<?> elemType = arrayType.getComponentType(); Class<?> elemType = arrayType.getComponentType();
MethodType expType = !testSetter MethodType expType = !testSetter
...@@ -1326,9 +1375,10 @@ public class MethodHandlesTest { ...@@ -1326,9 +1375,10 @@ public class MethodHandlesTest {
public void testPermuteArguments() throws Throwable { public void testPermuteArguments() throws Throwable {
if (CAN_SKIP_WORKING) return; if (CAN_SKIP_WORKING) return;
startTest("permuteArguments"); startTest("permuteArguments");
testPermuteArguments(4, Integer.class, 2, long.class, 6);
if (CAN_TEST_LIGHTLY) return;
testPermuteArguments(4, Integer.class, 2, String.class, 0); testPermuteArguments(4, Integer.class, 2, String.class, 0);
testPermuteArguments(6, Integer.class, 0, null, 30); testPermuteArguments(6, Integer.class, 0, null, 30);
//testPermuteArguments(4, Integer.class, 2, long.class, 6); // FIXME Fail_7
} }
public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable { public void testPermuteArguments(int max, Class<?> type1, int t2c, Class<?> type2, int dilution) throws Throwable {
if (verbosity >= 2) if (verbosity >= 2)
...@@ -1354,7 +1404,9 @@ public class MethodHandlesTest { ...@@ -1354,7 +1404,9 @@ public class MethodHandlesTest {
casStep++; casStep++;
testPermuteArguments(args, types, outargs, numcases, casStep); testPermuteArguments(args, types, outargs, numcases, casStep);
numcases *= inargs; numcases *= inargs;
if (CAN_TEST_LIGHTLY && outargs < max-2) continue;
if (dilution > 10 && outargs >= 4) { if (dilution > 10 && outargs >= 4) {
if (CAN_TEST_LIGHTLY) continue;
int[] reorder = new int[outargs]; int[] reorder = new int[outargs];
// Do some special patterns, which we probably missed. // Do some special patterns, which we probably missed.
// Replication of a single argument or argument pair. // Replication of a single argument or argument pair.
...@@ -1392,6 +1444,7 @@ public class MethodHandlesTest { ...@@ -1392,6 +1444,7 @@ public class MethodHandlesTest {
reorder[i] = c % inargs; reorder[i] = c % inargs;
c /= inargs; c /= inargs;
} }
if (CAN_TEST_LIGHTLY && outargs >= 3 && (reorder[0] == reorder[1] || reorder[1] == reorder[2])) continue;
testPermuteArguments(args, types, reorder); testPermuteArguments(args, types, reorder);
} }
} }
...@@ -1464,11 +1517,12 @@ public class MethodHandlesTest { ...@@ -1464,11 +1517,12 @@ public class MethodHandlesTest {
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
if (verbosity >= 3) if (verbosity >= 3)
System.out.println("spreadArguments "+argType); System.out.println("spreadArguments "+argType);
// FIXME: enable _adapter_spread_args and fix Fail_2 for (int nargs = 0; nargs < 50; nargs++) {
for (int nargs = 0; nargs < 10; nargs++) { if (CAN_TEST_LIGHTLY && nargs > 7) break;
if (argType == int.class && nargs >= 6) continue; // FIXME Fail_1 for (int pos = 0; pos <= nargs; pos++) {
for (int pos = 0; pos < nargs; pos++) { if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue;
if (argType == int.class && pos > 0) continue; // FIXME Fail_3 if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
continue;
testSpreadArguments(argType, pos, nargs); testSpreadArguments(argType, pos, nargs);
} }
} }
...@@ -1557,9 +1611,12 @@ public class MethodHandlesTest { ...@@ -1557,9 +1611,12 @@ public class MethodHandlesTest {
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
if (verbosity >= 3) if (verbosity >= 3)
System.out.println("collectArguments "+argType); System.out.println("collectArguments "+argType);
for (int nargs = 0; nargs < 10; nargs++) { for (int nargs = 0; nargs < 50; nargs++) {
for (int pos = 0; pos < nargs; pos++) { if (CAN_TEST_LIGHTLY && nargs > 7) break;
if (argType == int.class) continue; // FIXME Fail_4 for (int pos = 0; pos <= nargs; pos++) {
if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue;
if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
continue;
testCollectArguments(argType, pos, nargs); testCollectArguments(argType, pos, nargs);
} }
} }
...@@ -1593,10 +1650,15 @@ public class MethodHandlesTest { ...@@ -1593,10 +1650,15 @@ public class MethodHandlesTest {
public void testInsertArguments() throws Throwable { public void testInsertArguments() throws Throwable {
if (CAN_SKIP_WORKING) return; if (CAN_SKIP_WORKING) return;
startTest("insertArguments"); startTest("insertArguments");
for (int nargs = 0; nargs <= 4; nargs++) { for (int nargs = 0; nargs < 50; nargs++) {
for (int ins = 0; ins <= 4; ins++) { if (CAN_TEST_LIGHTLY && nargs > 7) break;
if (ins > MAX_ARG_INCREASE) continue; // FIXME Fail_6 for (int ins = 0; ins <= nargs; ins++) {
if (nargs > 10 && ins > 4 && ins < nargs-4 && ins % 10 != 3)
continue;
for (int pos = 0; pos <= nargs; pos++) { for (int pos = 0; pos <= nargs; pos++) {
if (nargs > 10 && pos > 4 && pos < nargs-4 && pos % 10 != 3)
continue;
if (CAN_TEST_LIGHTLY && pos > 2 && pos < nargs-2) continue;
testInsertArguments(nargs, pos, ins); testInsertArguments(nargs, pos, ins);
} }
} }
...@@ -1634,8 +1696,8 @@ public class MethodHandlesTest { ...@@ -1634,8 +1696,8 @@ public class MethodHandlesTest {
for (Class<?> rtype : new Class[] { Object.class, for (Class<?> rtype : new Class[] { Object.class,
List.class, List.class,
int.class, int.class,
//byte.class, //FIXME: add this byte.class,
//long.class, //FIXME: add this long.class,
CharSequence.class, CharSequence.class,
String.class }) { String.class }) {
testFilterReturnValue(nargs, rtype); testFilterReturnValue(nargs, rtype);
...@@ -1780,6 +1842,7 @@ public class MethodHandlesTest { ...@@ -1780,6 +1842,7 @@ public class MethodHandlesTest {
// exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker // exactInvoker, genericInvoker, varargsInvoker[0..N], dynamicInvoker
Set<MethodType> done = new HashSet<MethodType>(); Set<MethodType> done = new HashSet<MethodType>();
for (int i = 0; i <= 6; i++) { for (int i = 0; i <= 6; i++) {
if (CAN_TEST_LIGHTLY && i > 3) break;
MethodType gtype = MethodType.genericMethodType(i); MethodType gtype = MethodType.genericMethodType(i);
for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) { for (Class<?> argType : new Class[]{Object.class, Integer.class, int.class}) {
for (int j = -1; j < i; j++) { for (int j = -1; j < i; j++) {
...@@ -1790,7 +1853,6 @@ public class MethodHandlesTest { ...@@ -1790,7 +1853,6 @@ public class MethodHandlesTest {
continue; continue;
else else
type = type.changeParameterType(j, argType); type = type.changeParameterType(j, argType);
if (argType.isPrimitive() && j != i-1) continue; // FIXME Fail_5
if (done.add(type)) if (done.add(type))
testInvokers(type); testInvokers(type);
MethodType vtype = type.changeReturnType(void.class); MethodType vtype = type.changeReturnType(void.class);
...@@ -1890,6 +1952,7 @@ public class MethodHandlesTest { ...@@ -1890,6 +1952,7 @@ public class MethodHandlesTest {
} }
for (int k = 0; k <= nargs; k++) { for (int k = 0; k <= nargs; k++) {
// varargs invoker #0..N // varargs invoker #0..N
if (CAN_TEST_LIGHTLY && (k > 1 || k < nargs - 1)) continue;
countTest(); countTest();
calledLog.clear(); calledLog.clear();
inv = MethodHandles.spreadInvoker(type, k); inv = MethodHandles.spreadInvoker(type, k);
...@@ -1933,6 +1996,7 @@ public class MethodHandlesTest { ...@@ -1933,6 +1996,7 @@ public class MethodHandlesTest {
} }
private static final String MISSING_ARG = "missingArg"; private static final String MISSING_ARG = "missingArg";
private static final String MISSING_ARG_2 = "missingArg#2";
static Object targetIfEquals() { static Object targetIfEquals() {
return called("targetIfEquals"); return called("targetIfEquals");
} }
...@@ -1968,28 +2032,39 @@ public class MethodHandlesTest { ...@@ -1968,28 +2032,39 @@ public class MethodHandlesTest {
public void testGuardWithTest() throws Throwable { public void testGuardWithTest() throws Throwable {
if (CAN_SKIP_WORKING) return; if (CAN_SKIP_WORKING) return;
startTest("guardWithTest"); startTest("guardWithTest");
for (int nargs = 0; nargs <= 3; nargs++) { for (int nargs = 0; nargs <= 50; nargs++) {
if (nargs != 2) continue; // FIXME: test more later if (CAN_TEST_LIGHTLY && nargs > 7) break;
testGuardWithTest(nargs, Object.class); testGuardWithTest(nargs, Object.class);
testGuardWithTest(nargs, String.class); testGuardWithTest(nargs, String.class);
} }
} }
void testGuardWithTest(int nargs, Class<?> argClass) throws Throwable { void testGuardWithTest(int nargs, Class<?> argClass) throws Throwable {
testGuardWithTest(nargs, 0, argClass);
if (nargs <= 5 || nargs % 10 == 3) {
for (int testDrops = 1; testDrops <= nargs; testDrops++)
testGuardWithTest(nargs, testDrops, argClass);
}
}
void testGuardWithTest(int nargs, int testDrops, Class<?> argClass) throws Throwable {
countTest(); countTest();
int nargs1 = Math.min(3, nargs);
MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class)); MethodHandle test = PRIVATE.findVirtual(Object.class, "equals", MethodType.methodType(boolean.class, Object.class));
MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs)); MethodHandle target = PRIVATE.findStatic(MethodHandlesTest.class, "targetIfEquals", MethodType.genericMethodType(nargs1));
MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs)); MethodHandle fallback = PRIVATE.findStatic(MethodHandlesTest.class, "fallbackIfNotEquals", MethodType.genericMethodType(nargs1));
while (test.type().parameterCount() < nargs)
test = MethodHandles.dropArguments(test, test.type().parameterCount()-1, Object.class);
while (test.type().parameterCount() > nargs) while (test.type().parameterCount() > nargs)
// 0: test = constant(MISSING_ARG.equals(MISSING_ARG))
// 1: test = lambda (_) MISSING_ARG.equals(_)
test = MethodHandles.insertArguments(test, 0, MISSING_ARG); test = MethodHandles.insertArguments(test, 0, MISSING_ARG);
if (argClass != Object.class) { if (argClass != Object.class) {
test = changeArgTypes(test, argClass); test = changeArgTypes(test, argClass);
target = changeArgTypes(target, argClass); target = changeArgTypes(target, argClass);
fallback = changeArgTypes(fallback, argClass); fallback = changeArgTypes(fallback, argClass);
} }
MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback); int testArgs = nargs - testDrops;
assertEquals(target.type(), mh.type()); assert(testArgs >= 0);
test = addTrailingArgs(test, Math.min(testArgs, nargs), argClass);
target = addTrailingArgs(target, nargs, argClass);
fallback = addTrailingArgs(fallback, nargs, argClass);
Object[][] argLists = { Object[][] argLists = {
{ }, { },
{ "foo" }, { MISSING_ARG }, { "foo" }, { MISSING_ARG },
...@@ -1997,7 +2072,19 @@ public class MethodHandlesTest { ...@@ -1997,7 +2072,19 @@ public class MethodHandlesTest {
{ "foo", "foo", "baz" }, { "foo", "bar", "baz" } { "foo", "foo", "baz" }, { "foo", "bar", "baz" }
}; };
for (Object[] argList : argLists) { for (Object[] argList : argLists) {
if (argList.length != nargs) continue; Object[] argList1 = argList;
if (argList.length != nargs) {
if (argList.length != nargs1) continue;
argList1 = Arrays.copyOf(argList, nargs);
Arrays.fill(argList1, nargs1, nargs, MISSING_ARG_2);
}
MethodHandle test1 = test;
if (test1.type().parameterCount() > testArgs) {
int pc = test1.type().parameterCount();
test1 = MethodHandles.insertArguments(test, testArgs, Arrays.copyOfRange(argList1, testArgs, pc));
}
MethodHandle mh = MethodHandles.guardWithTest(test1, target, fallback);
assertEquals(target.type(), mh.type());
boolean equals; boolean equals;
switch (nargs) { switch (nargs) {
case 0: equals = true; break; case 0: equals = true; break;
...@@ -2007,7 +2094,7 @@ public class MethodHandlesTest { ...@@ -2007,7 +2094,7 @@ public class MethodHandlesTest {
String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals"); String willCall = (equals ? "targetIfEquals" : "fallbackIfNotEquals");
if (verbosity >= 3) if (verbosity >= 3)
System.out.println(logEntry(willCall, argList)); System.out.println(logEntry(willCall, argList));
Object result = mh.invokeWithArguments(argList); Object result = mh.invokeWithArguments(argList1);
assertCalled(willCall, argList); assertCalled(willCall, argList);
} }
} }
...@@ -2016,49 +2103,102 @@ public class MethodHandlesTest { ...@@ -2016,49 +2103,102 @@ public class MethodHandlesTest {
public void testCatchException() throws Throwable { public void testCatchException() throws Throwable {
if (CAN_SKIP_WORKING) return; if (CAN_SKIP_WORKING) return;
startTest("catchException"); startTest("catchException");
for (int nargs = 2; nargs <= 6; nargs++) { for (int nargs = 0; nargs < 40; nargs++) {
for (int ti = 0; ti <= 1; ti++) { if (CAN_TEST_LIGHTLY && nargs > 7) break;
boolean throwIt = (ti != 0); for (int throwMode = 0; throwMode < THROW_MODE_LIMIT; throwMode++) {
testCatchException(int.class, new ClassCastException("testing"), throwIt, nargs); testCatchException(int.class, new ClassCastException("testing"), throwMode, nargs);
testCatchException(void.class, new java.io.IOException("testing"), throwIt, nargs); if (CAN_TEST_LIGHTLY && nargs > 3) continue;
testCatchException(String.class, new LinkageError("testing"), throwIt, nargs); testCatchException(void.class, new java.io.IOException("testing"), throwMode, nargs);
testCatchException(String.class, new LinkageError("testing"), throwMode, nargs);
} }
} }
} }
static final int THROW_NOTHING = 0, THROW_CAUGHT = 1, THROW_UNCAUGHT = 2, THROW_THROUGH_ADAPTER = 3, THROW_MODE_LIMIT = 4;
void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs) throws Throwable {
testCatchException(returnType, thrown, throwMode, nargs, 0);
if (nargs <= 5 || nargs % 10 == 3) {
for (int catchDrops = 1; catchDrops <= nargs; catchDrops++)
testCatchException(returnType, thrown, throwMode, nargs, catchDrops);
}
}
private static <T extends Throwable> private static <T extends Throwable>
Object throwOrReturn(Object normal, T exception) throws T { Object throwOrReturn(Object normal, T exception) throws T {
if (exception != null) throw exception; if (exception != null) {
called("throwOrReturn/throw", normal, exception);
throw exception;
}
called("throwOrReturn/normal", normal, exception);
return normal; return normal;
} }
private int fakeIdentityCount;
private Object fakeIdentity(Object x) {
System.out.println("should throw through this!");
fakeIdentityCount++;
return x;
}
void testCatchException(Class<?> returnType, Throwable thrown, boolean throwIt, int nargs) throws Throwable { void testCatchException(Class<?> returnType, Throwable thrown, int throwMode, int nargs, int catchDrops) throws Throwable {
countTest(); countTest();
if (verbosity >= 3) if (verbosity >= 3)
System.out.println("catchException rt="+returnType+" throw="+throwIt+" nargs="+nargs); System.out.println("catchException rt="+returnType+" throw="+throwMode+" nargs="+nargs+" drops="+catchDrops);
Class<? extends Throwable> exType = thrown.getClass(); Class<? extends Throwable> exType = thrown.getClass();
if (throwMode > THROW_CAUGHT) thrown = new UnsupportedOperationException("do not catch this");
MethodHandle throwOrReturn MethodHandle throwOrReturn
= PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn", = PRIVATE.findStatic(MethodHandlesTest.class, "throwOrReturn",
MethodType.methodType(Object.class, Object.class, Throwable.class)); MethodType.methodType(Object.class, Object.class, Throwable.class));
if (throwMode == THROW_THROUGH_ADAPTER) {
MethodHandle fakeIdentity
= PRIVATE.findVirtual(MethodHandlesTest.class, "fakeIdentity",
MethodType.methodType(Object.class, Object.class)).bindTo(this);
for (int i = 0; i < 10; i++)
throwOrReturn = MethodHandles.filterReturnValue(throwOrReturn, fakeIdentity);
}
int nargs1 = Math.max(2, nargs);
MethodHandle thrower = throwOrReturn.asType(MethodType.genericMethodType(2)); MethodHandle thrower = throwOrReturn.asType(MethodType.genericMethodType(2));
while (thrower.type().parameterCount() < nargs) thrower = addTrailingArgs(thrower, nargs, Object.class);
thrower = MethodHandles.dropArguments(thrower, thrower.type().parameterCount(), Object.class); int catchArgc = 1 + nargs - catchDrops;
MethodHandle catcher = varargsList(1+nargs).asType(MethodType.genericMethodType(1+nargs)); MethodHandle catcher = varargsList(catchArgc).asType(MethodType.genericMethodType(catchArgc));
MethodHandle target = MethodHandles.catchException(thrower, Object[] args = randomArgs(nargs, Object.class);
thrown.getClass(), catcher); Object arg0 = MISSING_ARG;
Object arg1 = (throwMode == THROW_NOTHING) ? (Throwable) null : thrown;
if (nargs > 0) arg0 = args[0];
if (nargs > 1) args[1] = arg1;
assertEquals(nargs1, thrower.type().parameterCount());
if (nargs < nargs1) {
Object[] appendArgs = { arg0, arg1 };
appendArgs = Arrays.copyOfRange(appendArgs, nargs, nargs1);
thrower = MethodHandles.insertArguments(thrower, nargs, appendArgs);
}
assertEquals(nargs, thrower.type().parameterCount());
MethodHandle target = MethodHandles.catchException(thrower, exType, catcher);
assertEquals(thrower.type(), target.type()); assertEquals(thrower.type(), target.type());
assertEquals(nargs, target.type().parameterCount());
//System.out.println("catching with "+target+" : "+throwOrReturn); //System.out.println("catching with "+target+" : "+throwOrReturn);
Object[] args = randomArgs(nargs, Object.class); Object returned;
args[1] = (throwIt ? thrown : null); try {
Object returned = target.invokeWithArguments(args); returned = target.invokeWithArguments(args);
} catch (Throwable ex) {
assertSame("must get the out-of-band exception", thrown, ex);
if (throwMode <= THROW_CAUGHT)
assertEquals(THROW_UNCAUGHT, throwMode);
returned = ex;
}
assertCalled("throwOrReturn/"+(throwMode == THROW_NOTHING ? "normal" : "throw"), arg0, arg1);
//System.out.println("return from "+target+" : "+returned); //System.out.println("return from "+target+" : "+returned);
if (!throwIt) { if (throwMode == THROW_NOTHING) {
assertSame(args[0], returned); assertSame(arg0, returned);
} else { } else if (throwMode == THROW_CAUGHT) {
List<Object> catchArgs = new ArrayList<Object>(Arrays.asList(args)); List<Object> catchArgs = new ArrayList<Object>(Arrays.asList(args));
// catcher receives an initial subsequence of target arguments:
catchArgs.subList(nargs - catchDrops, nargs).clear();
// catcher also receives the exception, prepended:
catchArgs.add(0, thrown); catchArgs.add(0, thrown);
assertEquals(catchArgs, returned); assertEquals(catchArgs, returned);
} }
assertEquals(0, fakeIdentityCount);
} }
@Test @Test
...@@ -2092,6 +2232,48 @@ public class MethodHandlesTest { ...@@ -2092,6 +2232,48 @@ public class MethodHandlesTest {
assertSame(thrown, caught); assertSame(thrown, caught);
} }
@Test
public void testInterfaceCast() throws Throwable {
for (Class<?> ctype : new Class<?>[]{ Object.class, String.class, CharSequence.class, Number.class, Iterable.class}) {
testInterfaceCast(ctype, false, false);
testInterfaceCast(ctype, true, false);
testInterfaceCast(ctype, false, true);
testInterfaceCast(ctype, true, true);
}
}
public void testInterfaceCast(Class<?> ctype, boolean doret, boolean docast) throws Throwable {
String str = "normal return value";
MethodHandle mh = MethodHandles.identity(String.class);
MethodType mt = mh.type();
if (doret) mt = mt.changeReturnType(ctype);
else mt = mt.changeParameterType(0, ctype);
if (docast) mh = MethodHandles.explicitCastArguments(mh, mt);
else mh = mh.asType(mt);
// this bit is needed to make the interface types disappear for invokeWithArguments:
mh = MethodHandles.explicitCastArguments(mh, mt.generic());
boolean expectFail = !ctype.isInstance(str);
if (ctype.isInterface()) {
// special rules: interfaces slide by more frequently
if (docast || !doret) expectFail = false;
}
Object res;
try {
res = mh.invokeWithArguments(str);
} catch (Exception ex) {
res = ex;
}
boolean sawFail = !(res instanceof String);
if (sawFail != expectFail) {
System.out.println("*** testInterfaceCast: "+mh+" was "+mt+" => "+res+(docast ? " (explicitCastArguments)" : ""));
}
if (!sawFail) {
assertFalse(res.toString(), expectFail);
assertEquals(str, res);
} else {
assertTrue(res.toString(), expectFail);
}
}
@Test @Test
public void testCastFailure() throws Throwable { public void testCastFailure() throws Throwable {
if (CAN_SKIP_WORKING) return; if (CAN_SKIP_WORKING) return;
...@@ -2234,47 +2416,106 @@ public class MethodHandlesTest { ...@@ -2234,47 +2416,106 @@ public class MethodHandlesTest {
static void runForRunnable() { static void runForRunnable() {
called("runForRunnable"); called("runForRunnable");
} }
private interface Fooable { public interface Fooable {
Object foo(Fooable x, Object y); // overloads:
// this is for randomArg: Object foo(Object x, String y);
public class Impl implements Fooable { List foo(String x, int y);
public Object foo(Fooable x, Object y) { Object foo(String x);
throw new RuntimeException("do not call");
} }
final String name; static Object fooForFooable(String x, Object... y) {
public Impl() { name = "Fooable#"+nextArg(); } return called("fooForFooable/"+x, y);
@Override public String toString() { return name; }
} }
public static class MyCheckedException extends Exception {
} }
static Object fooForFooable(Fooable x, Object y) { public interface WillThrow {
return called("fooForFooable", x, y);
}
private static class MyCheckedException extends Exception {
}
private interface WillThrow {
void willThrow() throws MyCheckedException; void willThrow() throws MyCheckedException;
} }
/*non-public*/ interface PrivateRunnable {
public void run();
}
@Test @Test
public void testAsInstance() throws Throwable { public void testAsInterfaceInstance() throws Throwable {
if (CAN_SKIP_WORKING) return; if (CAN_SKIP_WORKING) return;
startTest("testAsInterfaceInstance");
Lookup lookup = MethodHandles.lookup(); Lookup lookup = MethodHandles.lookup();
// test typical case: Runnable.run
{ {
countTest();
if (verbosity >= 2) System.out.println("Runnable");
MethodType mt = MethodType.methodType(void.class); MethodType mt = MethodType.methodType(void.class);
MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt); MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "runForRunnable", mt);
Runnable proxy = MethodHandleProxies.asInterfaceInstance(Runnable.class, mh); Runnable proxy = MethodHandleProxies.asInterfaceInstance(Runnable.class, mh);
proxy.run(); proxy.run();
assertCalled("runForRunnable"); assertCalled("runForRunnable");
} }
// well known single-name overloaded interface: Appendable.append
{
countTest();
if (verbosity >= 2) System.out.println("Appendable");
ArrayList<List> appendResults = new ArrayList<List>();
MethodHandle append = lookup.bind(appendResults, "add", MethodType.methodType(boolean.class, Object.class));
append = append.asType(MethodType.methodType(void.class, List.class)); // specialize the type
MethodHandle asList = lookup.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class));
MethodHandle mh = MethodHandles.filterReturnValue(asList, append).asVarargsCollector(Object[].class);
Appendable proxy = MethodHandleProxies.asInterfaceInstance(Appendable.class, mh);
proxy.append("one");
proxy.append("two", 3, 4);
proxy.append('5');
assertEquals(Arrays.asList(Arrays.asList("one"),
Arrays.asList("two", 3, 4),
Arrays.asList('5')),
appendResults);
if (verbosity >= 3) System.out.println("appendResults="+appendResults);
appendResults.clear();
Formatter formatter = new Formatter(proxy);
String fmt = "foo str=%s char='%c' num=%d";
Object[] fmtArgs = { "str!", 'C', 42 };
String expect = String.format(fmt, fmtArgs);
formatter.format(fmt, fmtArgs);
String actual = "";
if (verbosity >= 3) System.out.println("appendResults="+appendResults);
for (List l : appendResults) {
Object x = l.get(0);
switch (l.size()) {
case 1: actual += x; continue;
case 3: actual += ((String)x).substring((int)l.get(1), (int)l.get(2)); continue;
}
actual += l;
}
if (verbosity >= 3) System.out.println("expect="+expect);
if (verbosity >= 3) System.out.println("actual="+actual);
assertEquals(expect, actual);
}
// test case of an single name which is overloaded: Fooable.foo(...)
{ {
MethodType mt = MethodType.methodType(Object.class, Fooable.class, Object.class); if (verbosity >= 2) System.out.println("Fooable");
MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable", mt); MethodHandle mh = lookup.findStatic(MethodHandlesTest.class, "fooForFooable",
MethodType.methodType(Object.class, String.class, Object[].class));
Fooable proxy = MethodHandleProxies.asInterfaceInstance(Fooable.class, mh); Fooable proxy = MethodHandleProxies.asInterfaceInstance(Fooable.class, mh);
Object[] args = randomArgs(mt.parameterArray()); for (Method m : Fooable.class.getDeclaredMethods()) {
Object result = proxy.foo((Fooable) args[0], args[1]); countTest();
assertCalled("fooForFooable", args); assertSame("foo", m.getName());
assertEquals(result, logEntry("fooForFooable", args)); if (verbosity > 3)
System.out.println("calling "+m);
MethodHandle invoker = lookup.unreflect(m);
MethodType mt = invoker.type();
Class<?>[] types = mt.parameterArray();
types[0] = int.class; // placeholder
Object[] args = randomArgs(types);
args[0] = proxy;
if (verbosity > 3)
System.out.println("calling "+m+" on "+Arrays.asList(args));
Object result = invoker.invokeWithArguments(args);
if (verbosity > 4)
System.out.println("result = "+result);
String name = "fooForFooable/"+args[1];
Object[] argTail = Arrays.copyOfRange(args, 2, args.length);
assertCalled(name, argTail);
assertEquals(result, logEntry(name, argTail));
} }
}
// test processing of thrown exceptions:
for (Throwable ex : new Throwable[] { new NullPointerException("ok"), for (Throwable ex : new Throwable[] { new NullPointerException("ok"),
new InternalError("ok"), new InternalError("ok"),
new Throwable("fail"), new Throwable("fail"),
...@@ -2285,11 +2526,12 @@ public class MethodHandlesTest { ...@@ -2285,11 +2526,12 @@ public class MethodHandlesTest {
mh = MethodHandles.insertArguments(mh, 0, ex); mh = MethodHandles.insertArguments(mh, 0, ex);
WillThrow proxy = MethodHandleProxies.asInterfaceInstance(WillThrow.class, mh); WillThrow proxy = MethodHandleProxies.asInterfaceInstance(WillThrow.class, mh);
try { try {
countTest();
proxy.willThrow(); proxy.willThrow();
System.out.println("Failed to throw: "+ex); System.out.println("Failed to throw: "+ex);
assertTrue(false); assertTrue(false);
} catch (Throwable ex1) { } catch (Throwable ex1) {
if (verbosity > 2) { if (verbosity > 3) {
System.out.println("throw "+ex); System.out.println("throw "+ex);
System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1)); System.out.println("catch "+(ex == ex1 ? "UNWRAPPED" : ex1));
} }
...@@ -2300,23 +2542,84 @@ public class MethodHandlesTest { ...@@ -2300,23 +2542,84 @@ public class MethodHandlesTest {
assertSame("must pass declared exception out without wrapping", ex, ex1); assertSame("must pass declared exception out without wrapping", ex, ex1);
} else { } else {
assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1); assertNotSame("must pass undeclared checked exception with wrapping", ex, ex1);
if (!(ex1 instanceof UndeclaredThrowableException) || ex1.getCause() != ex) {
ex1.printStackTrace();
}
assertSame(ex, ex1.getCause());
UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1; UndeclaredThrowableException utex = (UndeclaredThrowableException) ex1;
assertSame(ex, utex.getCause());
} }
} }
} }
// Test error checking: // Test error checking on bad interfaces:
for (Class<?> nonSAM : new Class[] { Object.class, for (Class<?> nonSMI : new Class[] { Object.class,
String.class, String.class,
CharSequence.class, CharSequence.class,
java.io.Serializable.class,
PrivateRunnable.class,
Example.class }) { Example.class }) {
if (verbosity > 2) System.out.println(nonSMI.getName());
try { try {
MethodHandleProxies.asInterfaceInstance(nonSAM, varargsArray(0)); countTest(false);
System.out.println("Failed to throw"); MethodHandleProxies.asInterfaceInstance(nonSMI, varargsArray(0));
assertTrue(false); assertTrue("Failed to throw on "+nonSMI.getName(), false);
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
if (verbosity > 2) System.out.println(nonSMI.getSimpleName()+": "+ex);
// Object: java.lang.IllegalArgumentException:
// not a public interface: java.lang.Object
// String: java.lang.IllegalArgumentException:
// not a public interface: java.lang.String
// CharSequence: java.lang.IllegalArgumentException:
// not a single-method interface: java.lang.CharSequence
// Serializable: java.lang.IllegalArgumentException:
// not a single-method interface: java.io.Serializable
// PrivateRunnable: java.lang.IllegalArgumentException:
// not a public interface: test.java.lang.invoke.MethodHandlesTest$PrivateRunnable
// Example: java.lang.IllegalArgumentException:
// not a public interface: test.java.lang.invoke.MethodHandlesTest$Example
}
}
// Test error checking on interfaces with the wrong method type:
for (Class<?> intfc : new Class[] { Runnable.class /*arity 0*/,
Fooable.class /*arity 1 & 2*/ }) {
int badArity = 1; // known to be incompatible
if (verbosity > 2) System.out.println(intfc.getName());
try {
countTest(false);
MethodHandleProxies.asInterfaceInstance(intfc, varargsArray(badArity));
assertTrue("Failed to throw on "+intfc.getName(), false);
} catch (WrongMethodTypeException ex) {
if (verbosity > 2) System.out.println(intfc.getSimpleName()+": "+ex);
// Runnable: java.lang.invoke.WrongMethodTypeException:
// cannot convert MethodHandle(Object)Object[] to ()void
// Fooable: java.lang.invoke.WrongMethodTypeException:
// cannot convert MethodHandle(Object)Object[] to (Object,String)Object
}
} }
} }
@Test
public void testRunnableProxy() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("testRunnableProxy");
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle run = lookup.findStatic(lookup.lookupClass(), "runForRunnable", MethodType.methodType(void.class));
Runnable r = MethodHandleProxies.asInterfaceInstance(Runnable.class, run);
testRunnableProxy(r);
assertCalled("runForRunnable");
}
private static void testRunnableProxy(Runnable r) {
//7058630: JSR 292 method handle proxy violates contract for Object methods
r.run();
Object o = r;
r = null;
boolean eq = (o == o);
int hc = System.identityHashCode(o);
String st = o.getClass().getName() + "@" + Integer.toHexString(hc);
Object expect = Arrays.asList(st, eq, hc);
if (verbosity >= 2) System.out.println("expect st/eq/hc = "+expect);
Object actual = Arrays.asList(o.toString(), o.equals(o), o.hashCode());
if (verbosity >= 2) System.out.println("actual st/eq/hc = "+actual);
assertEquals(expect, actual);
} }
} }
// Local abbreviated copy of sun.invoke.util.ValueConversions // Local abbreviated copy of sun.invoke.util.ValueConversions
...@@ -2380,8 +2683,7 @@ class ValueConversions { ...@@ -2380,8 +2683,7 @@ class ValueConversions {
public static MethodHandle varargsArray(int nargs) { public static MethodHandle varargsArray(int nargs) {
if (nargs < ARRAYS.length) if (nargs < ARRAYS.length)
return ARRAYS[nargs]; return ARRAYS[nargs];
// else need to spin bytecode or do something else fancy return MethodHandles.identity(Object[].class).asCollector(Object[].class, nargs);
throw new UnsupportedOperationException("NYI: cannot form a varargs array of length "+nargs);
} }
public static MethodHandle varargsArray(Class<?> arrayType, int nargs) { public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
Class<?> elemType = arrayType.getComponentType(); Class<?> elemType = arrayType.getComponentType();
...@@ -2463,6 +2765,12 @@ class ValueConversions { ...@@ -2463,6 +2765,12 @@ class ValueConversions {
return lists.toArray(new MethodHandle[0]); return lists.toArray(new MethodHandle[0]);
} }
static final MethodHandle[] LISTS = makeLists(); static final MethodHandle[] LISTS = makeLists();
static final MethodHandle AS_LIST;
static {
try {
AS_LIST = IMPL_LOOKUP.findStatic(Arrays.class, "asList", MethodType.methodType(List.class, Object[].class));
} catch (Exception ex) { throw new RuntimeException(ex); }
}
/** Return a method handle that takes the indicated number of Object /** Return a method handle that takes the indicated number of Object
* arguments and returns List. * arguments and returns List.
...@@ -2470,8 +2778,7 @@ class ValueConversions { ...@@ -2470,8 +2778,7 @@ class ValueConversions {
public static MethodHandle varargsList(int nargs) { public static MethodHandle varargsList(int nargs) {
if (nargs < LISTS.length) if (nargs < LISTS.length)
return LISTS[nargs]; return LISTS[nargs];
// else need to spin bytecode or do something else fancy return AS_LIST.asCollector(Object[].class, nargs);
throw new UnsupportedOperationException("NYI");
} }
} }
// This guy tests access from outside the same package member, but inside // This guy tests access from outside the same package member, but inside
......
...@@ -82,6 +82,7 @@ public class RicochetTest { ...@@ -82,6 +82,7 @@ public class RicochetTest {
testLongSpreads(); testLongSpreads();
testIntCollects(); testIntCollects();
testReturns(); testReturns();
testRecursion();
} }
@Test @Test
...@@ -371,6 +372,61 @@ public class RicochetTest { ...@@ -371,6 +372,61 @@ public class RicochetTest {
//System.out.println("faultCount="+faultCount); //System.out.println("faultCount="+faultCount);
} }
@Test
public void testRecursion() throws Throwable {
if (!startTest("testRecursion")) return;
final int LIMIT = 10;
for (int i = 0; i < LIMIT; i++) {
RFCB rfcb = new RFCB(i);
Object x = "x", y = "y";
Object result = rfcb.recursiveFunction(x, y);
verbose(1, result);
}
}
/** Recursive Function Control Block */
private static class RFCB {
java.util.Random random;
final MethodHandle[] fns;
int depth;
RFCB(int seed) throws Throwable {
this.random = new java.util.Random(seed);
this.fns = new MethodHandle[Math.max(29, (1 << MAX_DEPTH-2)/3)];
java.util.Arrays.fill(fns, lookup().bind(this, "recursiveFunction", genericMethodType(2)));
for (int i = 5; i < fns.length; i++) {
switch (i % 4) {
case 0: fns[i] = filterArguments(fns[i - 5], 0, insertArguments(fns[i - 4], 1, ".")); break;
case 1: fns[i] = filterArguments(fns[i - 5], 1, insertArguments(fns[i - 3], 1, ".")); break;
case 2: fns[i] = filterReturnValue(fns[i - 5], insertArguments(fns[i - 2], 1, ".")); break;
}
}
}
Object recursiveFunction(Object x, Object y) throws Throwable {
depth++;
try {
final int ACTION_COUNT = 11;
switch (random.nextInt(ACTION_COUNT)) {
case 1:
Throwable ex = new RuntimeException();
ex.fillInStackTrace();
if (VERBOSITY >= 2) ex.printStackTrace();
x = "ST; " + x;
break;
case 2:
System.gc();
x = "GC; " + x;
break;
}
boolean isLeaf = (depth >= MAX_DEPTH);
if (isLeaf) {
return Arrays.asList(x, y).toString();
}
return fns[random.nextInt(fns.length)].invokeExact(x, y);
} finally {
depth--;
}
}
}
private static MethodHandle sequence(MethodHandle mh1, MethodHandle... mhs) { private static MethodHandle sequence(MethodHandle mh1, MethodHandle... mhs) {
MethodHandle res = mh1; MethodHandle res = mh1;
for (MethodHandle mh2 : mhs) for (MethodHandle mh2 : mhs)
...@@ -536,6 +592,7 @@ public class RicochetTest { ...@@ -536,6 +592,7 @@ public class RicochetTest {
} }
// stress modes: // stress modes:
private static final int MAX_DEPTH = getProperty("MAX_DEPTH", 5);
private static final int REPEAT = getProperty("REPEAT", 0); private static final int REPEAT = getProperty("REPEAT", 0);
private static final int STRESS = getProperty("STRESS", 0); private static final int STRESS = getProperty("STRESS", 0);
private static /*v*/ int STRESS_COUNT; private static /*v*/ int STRESS_COUNT;
......
/*
* 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 unit tests for method handles which permute their arguments
* @run junit test.java.lang.invoke.ThrowExceptionsTest
*/
package test.java.lang.invoke;
import org.junit.*;
import java.util.*;
import java.lang.reflect.*;
import java.lang.invoke.*;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
public class ThrowExceptionsTest {
private static final Class CLASS = ThrowExceptionsTest.class;
private static final Lookup LOOKUP = lookup();
public static void main(String argv[]) throws Throwable {
new ThrowExceptionsTest().testAll((argv.length == 0 ? null : Arrays.asList(argv).toString()));
}
@Test
public void testWMT() throws Throwable {
// mostly call testWMTCallee, but sometimes call its void-returning variant
MethodHandle mh = testWMTCallee();
MethodHandle mh1 = mh.asType(mh.type().changeReturnType(void.class));
assert(mh1 != mh);
testWMT(mh, mh1, 1000);
}
@Test
public void testBoundWMT() throws Throwable {
// mostly call exactInvoker.bindTo(testWMTCallee), but sometimes call its void-returning variant
MethodHandle callee = testWMTCallee();
MethodHandle callee1 = callee.asType(callee.type().changeReturnType(void.class));
MethodHandle invoker = exactInvoker(callee.type());
MethodHandle mh = invoker.bindTo(callee);
MethodHandle mh1 = invoker.bindTo(callee1);
testWMT(mh, mh1, 1000);
}
@Test
public void testFoldWMT() throws Throwable {
// mostly call exactInvoker.fold(constant(testWMTCallee)), but sometimes call its void-returning variant
MethodHandle callee = testWMTCallee();
MethodHandle callee1 = callee.asType(callee.type().changeReturnType(void.class));
MethodHandle invoker = exactInvoker(callee.type());
MethodHandle mh = foldArguments(invoker, constant(MethodHandle.class, callee));
MethodHandle mh1 = foldArguments(invoker, constant(MethodHandle.class, callee1));
testWMT(mh, mh1, 1000);
}
@Test
public void testFoldCCE() throws Throwable {
MethodHandle callee = testWMTCallee();
MethodHandle callee1 = callee.asType(callee.type().changeParameterType(1, Number.class)).asType(callee.type());
MethodHandle invoker = exactInvoker(callee.type());
MethodHandle mh = foldArguments(invoker, constant(MethodHandle.class, callee));
MethodHandle mh1 = foldArguments(invoker, constant(MethodHandle.class, callee1));
testWMT(mh, mh1, 1000);
}
@Test
public void testStackOverflow() throws Throwable {
MethodHandle callee = testWMTCallee();
MethodHandle callee1 = makeStackOverflow().asType(callee.type());
MethodHandle invoker = exactInvoker(callee.type());
MethodHandle mh = foldArguments(invoker, constant(MethodHandle.class, callee));
MethodHandle mh1 = foldArguments(invoker, constant(MethodHandle.class, callee1));
for (int i = 0; i < REPEAT; i++) {
try {
testWMT(mh, mh1, 1000);
} catch (StackOverflowError ex) {
// OK, try again
}
}
}
private static MethodHandle makeStackOverflow() {
MethodType cellType = methodType(void.class);
MethodHandle[] cell = { null }; // recursion point
MethodHandle getCell = insertArguments(arrayElementGetter(cell.getClass()), 0, cell, 0);
MethodHandle invokeCell = foldArguments(exactInvoker(cellType), getCell);
assert(invokeCell.type() == cellType);
cell[0] = invokeCell;
// make it conformable to any type:
invokeCell = dropArguments(invokeCell, 0, Object[].class).asVarargsCollector(Object[].class);
return invokeCell;
}
static int testCases;
private void testAll(String match) throws Throwable {
testCases = 0;
Lookup lookup = lookup();
for (Method m : CLASS.getDeclaredMethods()) {
String name = m.getName();
if (name.startsWith("test") &&
(match == null || match.contains(name.substring("test".length()))) &&
m.getParameterTypes().length == 0 &&
Modifier.isPublic(m.getModifiers()) &&
!Modifier.isStatic(m.getModifiers())) {
System.out.println("["+name+"]");
int tc = testCases;
try {
m.invoke(this);
} catch (Throwable ex) {
System.out.println("*** "+ex);
ex.printStackTrace();
}
if (testCases == tc) testCases++;
}
}
if (testCases == 0) throw new RuntimeException("no test cases found");
System.out.println("ran a total of "+testCases+" test cases");
}
private static MethodHandle findStatic(String name) {
return findMethod(name, true);
}
private static MethodHandle findVirtual(String name) {
return findMethod(name, false);
}
private static MethodHandle findMethod(String name, boolean isStatic) {
MethodHandle mh = null;
for (Method m : CLASS.getDeclaredMethods()) {
if (m.getName().equals(name) &&
Modifier.isStatic(m.getModifiers()) == isStatic) {
if (mh != null)
throw new RuntimeException("duplicate methods: "+name);
try {
mh = LOOKUP.unreflect(m);
} catch (ReflectiveOperationException ex) {
throw new RuntimeException(ex);
}
}
}
if (mh == null)
throw new RuntimeException("no method: "+name);
return mh;
}
int testWMTCallee;
private int testWMTCallee(String x) {
return testWMTCallee++;
}
private static MethodHandle testWMTCallee() {
MethodHandle callee = findVirtual("testWMTCallee");
// FIXME: should not have to retype callee
callee = callee.asType(callee.type().changeParameterType(0, Object.class));
return callee;
}
private Exception testWMT(MethodHandle[] mhs, int reps) throws Throwable {
testCases += 1;
testWMTCallee = 0;
int catches = 0;
Exception savedEx = null;
for (int i = 0; i < reps; i++) {
MethodHandle mh = mhs[i % mhs.length];
int n;
try {
// FIXME: should not have to retype this
n = (int) mh.invokeExact((Object)this, "x");
assertEquals(n, i - catches);
// Using the exact type for this causes endless deopt due to
// 'non_cached_result' in SystemDictionary::find_method_handle_invoke.
// The problem is that the compiler thread needs to access a cached
// invoke method, but invoke methods are not cached if one of the
// component types is not on the BCP.
} catch (Exception ex) {
savedEx = ex;
catches++;
}
}
//VERBOSE: System.out.println("reps="+reps+" catches="+catches);
return savedEx;
}
private static final int REPEAT = Integer.getInteger(CLASS.getSimpleName()+".REPEAT", 10);
private Exception testWMT(MethodHandle mh, MethodHandle mh1, int reps) throws Throwable {
//VERBOSE: System.out.println("mh="+mh+" mh1="+mh1);
MethodHandle[] mhs = new MethodHandle[100];
Arrays.fill(mhs, mh);
int patch = mhs.length-1;
Exception savedEx = null;
for (int i = 0; i < REPEAT; i++) {
mhs[patch] = mh;
testWMT(mhs, 10000);
mhs[patch] = mh1;
savedEx = testWMT(mhs, reps);
}
return savedEx;
}
private static void assertEquals(Object x, Object y) {
if (x == y || x != null && x.equals(y)) return;
throw new RuntimeException(x+" != "+y);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册