6983728: JSR 292 remove argument count limitations
Remove workarounds and limitations from before 6939861. Reviewed-by: never
This commit is contained in:
parent
8b3e857aab
commit
ee85a30479
@ -247,10 +247,6 @@ class AdapterMethodHandle extends BoundMethodHandle {
|
||||
MethodType needConversion = MethodType.methodType(needReturn, haveReturn);
|
||||
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);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.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);
|
||||
// }
|
||||
}
|
@ -1,633 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.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,172 +102,46 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
MethodType rawConType = rawConstructor.type();
|
||||
Class<?> allocateClass = rawConType.parameterType(0);
|
||||
// Wrap the raw (unsafe) constructor with the allocation of a suitable object.
|
||||
if (AdapterMethodHandle.canCollectArguments(rawConType, MethodType.methodType(allocateClass), 0, true)) {
|
||||
// allocator(arg...)
|
||||
// [fold]=> cookedConstructor(obj=allocate(C), arg...)
|
||||
// [dup,collect]=> identity(obj, void=rawConstructor(obj, arg...))
|
||||
MethodHandle returner = MethodHandles.identity(allocateClass);
|
||||
MethodType ctype = rawConType.insertParameterTypes(0, allocateClass).changeReturnType(allocateClass);
|
||||
MethodHandle cookedConstructor = AdapterMethodHandle.makeCollectArguments(returner, rawConstructor, 1, false);
|
||||
assert(cookedConstructor.type().equals(ctype));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true);
|
||||
MethodHandle allocator = new AllocateObject(allocateClass);
|
||||
// allocate() => new C(void)
|
||||
assert(allocator.type().equals(MethodType.methodType(allocateClass)));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
MethodHandle fold = foldArguments(cookedConstructor, ctype, 0, allocator);
|
||||
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;
|
||||
assert(AdapterMethodHandle.canCollectArguments(rawConType, MethodType.methodType(allocateClass), 0, true));
|
||||
// allocator(arg...)
|
||||
// [fold]=> cookedConstructor(obj=allocate(C), arg...)
|
||||
// [dup,collect]=> identity(obj, void=rawConstructor(obj, arg...))
|
||||
MethodHandle returner = MethodHandles.identity(allocateClass);
|
||||
MethodType ctype = rawConType.insertParameterTypes(0, allocateClass).changeReturnType(allocateClass);
|
||||
MethodHandle cookedConstructor = AdapterMethodHandle.makeCollectArguments(returner, rawConstructor, 1, false);
|
||||
assert(cookedConstructor.type().equals(ctype));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
cookedConstructor = AdapterMethodHandle.makeCollectArguments(cookedConstructor, returner, 0, true);
|
||||
MethodHandle allocator = new AllocateObject(allocateClass);
|
||||
// allocate() => new C(void)
|
||||
assert(allocator.type().equals(MethodType.methodType(allocateClass)));
|
||||
ctype = ctype.dropParameterTypes(0, 1);
|
||||
MethodHandle fold = foldArguments(cookedConstructor, ctype, 0, allocator);
|
||||
return fold;
|
||||
}
|
||||
|
||||
static final class AllocateObject<C> extends BoundMethodHandle {
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
|
||||
private final Class<C> allocateClass;
|
||||
private final MethodHandle rawConstructor;
|
||||
|
||||
private AllocateObject(MethodHandle invoker,
|
||||
Class<C> allocateClass, MethodHandle rawConstructor) {
|
||||
super(invoker);
|
||||
this.allocateClass = allocateClass;
|
||||
this.rawConstructor = rawConstructor;
|
||||
assert(MethodHandleNatives.workaroundWithoutRicochetFrames()); // this code is deprecated
|
||||
}
|
||||
// for allocation only:
|
||||
private AllocateObject(Class<C> allocateClass) {
|
||||
super(ALLOCATE.asType(MethodType.methodType(allocateClass, AllocateObject.class)));
|
||||
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")
|
||||
private C allocate() throws InstantiationException {
|
||||
return (C) unsafe.allocateInstance(allocateClass);
|
||||
}
|
||||
private C invoke_V(Object... av) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, av);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L0() throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L1(Object a0) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L2(Object a0, Object a1) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6);
|
||||
return obj;
|
||||
}
|
||||
private C invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
|
||||
C obj = allocate();
|
||||
rawConstructor.invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7);
|
||||
return obj;
|
||||
}
|
||||
static MethodHandle[] makeInvokes() {
|
||||
ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
|
||||
MethodHandles.Lookup lookup = IMPL_LOOKUP;
|
||||
for (;;) {
|
||||
int nargs = invokes.size();
|
||||
String name = "invoke_L"+nargs;
|
||||
MethodHandle invoke = null;
|
||||
try {
|
||||
invoke = lookup.findVirtual(AllocateObject.class, name, MethodType.genericMethodType(nargs));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
}
|
||||
if (invoke == null) break;
|
||||
invokes.add(invoke);
|
||||
}
|
||||
assert(invokes.size() == 9); // current number of methods
|
||||
return invokes.toArray(new MethodHandle[0]);
|
||||
};
|
||||
static final MethodHandle[] INVOKES = makeInvokes();
|
||||
// For testing use this:
|
||||
//static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
|
||||
static final MethodHandle VARARGS_INVOKE;
|
||||
static final MethodHandle ALLOCATE;
|
||||
static {
|
||||
try {
|
||||
VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
|
||||
ALLOCATE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "allocate", MethodType.genericMethodType(0));
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw uncaughtException(ex);
|
||||
}
|
||||
}
|
||||
// Corresponding generic constructor types:
|
||||
static final MethodType[] CON_TYPES = new MethodType[INVOKES.length];
|
||||
static {
|
||||
for (int i = 0; i < INVOKES.length; i++)
|
||||
CON_TYPES[i] = makeConType(INVOKES[i]);
|
||||
}
|
||||
static final MethodType VARARGS_CON_TYPE = makeConType(VARARGS_INVOKE);
|
||||
static MethodType makeConType(MethodHandle invoke) {
|
||||
MethodType invType = invoke.type();
|
||||
return invType.changeParameterType(0, Object.class).changeReturnType(void.class);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
@ -757,26 +631,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
return target;
|
||||
if (oldType.parameterCount() != newType.parameterCount())
|
||||
throw newIllegalArgumentException("mismatched parameter count", oldType, newType);
|
||||
MethodHandle res = 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);
|
||||
return AdapterMethodHandle.makePairwiseConvert(newType, target, level);
|
||||
}
|
||||
|
||||
static MethodHandle spreadArguments(MethodHandle target, Class<?> arrayType, int arrayLength) {
|
||||
@ -829,19 +684,8 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
// oldType // (a..., b...)=>r
|
||||
assert(newType.parameterCount() == collectArg + colType.parameterCount());
|
||||
assert(oldType.parameterCount() == collectArg + 1);
|
||||
MethodHandle result = null;
|
||||
if (AdapterMethodHandle.canCollectArguments(oldType, colType, 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;
|
||||
assert(AdapterMethodHandle.canCollectArguments(oldType, colType, collectArg, false));
|
||||
return AdapterMethodHandle.makeCollectArguments(target, collector, collectArg, false);
|
||||
}
|
||||
|
||||
static MethodHandle filterArgument(MethodHandle target,
|
||||
@ -850,32 +694,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
MethodType ttype = target.type();
|
||||
MethodType ftype = filter.type();
|
||||
assert(ftype.parameterCount() == 1);
|
||||
MethodHandle result = null;
|
||||
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;
|
||||
return AdapterMethodHandle.makeCollectArguments(target, filter, pos, false);
|
||||
}
|
||||
|
||||
static MethodHandle foldArguments(MethodHandle target,
|
||||
@ -884,155 +703,15 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
MethodHandle combiner) {
|
||||
MethodType oldType = target.type();
|
||||
MethodType ctype = combiner.type();
|
||||
if (AdapterMethodHandle.canCollectArguments(oldType, ctype, foldPos, true)) {
|
||||
MethodHandle res = 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);
|
||||
assert(AdapterMethodHandle.canCollectArguments(oldType, ctype, foldPos, true));
|
||||
return AdapterMethodHandle.makeCollectArguments(target, combiner, foldPos, true);
|
||||
}
|
||||
|
||||
static
|
||||
MethodHandle dropArguments(MethodHandle target,
|
||||
MethodType newType, int argnum) {
|
||||
int drops = newType.parameterCount() - target.type().parameterCount();
|
||||
MethodHandle res = AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops);
|
||||
if (res != null)
|
||||
return res;
|
||||
throw new UnsupportedOperationException("NYI");
|
||||
}
|
||||
|
||||
private static class GuardWithTest extends BoundMethodHandle {
|
||||
private final MethodHandle test, target, fallback;
|
||||
private GuardWithTest(MethodHandle invoker,
|
||||
MethodHandle test, MethodHandle target, MethodHandle fallback) {
|
||||
super(invoker);
|
||||
this.test = test;
|
||||
this.target = target;
|
||||
this.fallback = fallback;
|
||||
}
|
||||
static 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);
|
||||
}
|
||||
}
|
||||
return AdapterMethodHandle.makeDropArguments(newType, target, argnum, drops);
|
||||
}
|
||||
|
||||
static
|
||||
@ -1065,21 +744,18 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
|
||||
assert(test.type().returnType() == boolean.class);
|
||||
MethodType targetType = target.type();
|
||||
MethodType foldTargetType = targetType.insertParameterTypes(0, boolean.class);
|
||||
if (AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true)
|
||||
&& GuardWithTest.preferRicochetFrame(targetType)) {
|
||||
// working backwards, as usual:
|
||||
assert(target.type().equals(fallback.type()));
|
||||
MethodHandle tailcall = MethodHandles.exactInvoker(target.type());
|
||||
MethodHandle select = selectAlternative();
|
||||
select = bindArgument(select, 2, fallback);
|
||||
select = bindArgument(select, 1, target);
|
||||
// select(z: boolean) => (z ? target : fallback)
|
||||
MethodHandle filter = filterArgument(tailcall, 0, select);
|
||||
assert(filter.type().parameterType(0) == boolean.class);
|
||||
MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test);
|
||||
return fold;
|
||||
}
|
||||
return GuardWithTest.make(test, target, fallback);
|
||||
assert(AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true));
|
||||
// working backwards, as usual:
|
||||
assert(target.type().equals(fallback.type()));
|
||||
MethodHandle tailcall = MethodHandles.exactInvoker(target.type());
|
||||
MethodHandle select = selectAlternative();
|
||||
select = bindArgument(select, 2, fallback);
|
||||
select = bindArgument(select, 1, target);
|
||||
// select(z: boolean) => (z ? target : fallback)
|
||||
MethodHandle filter = filterArgument(tailcall, 0, select);
|
||||
assert(filter.type().parameterType(0) == boolean.class);
|
||||
MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test);
|
||||
return fold;
|
||||
}
|
||||
|
||||
private static class GuardWithCatch extends BoundMethodHandle {
|
||||
|
@ -391,13 +391,4 @@ class MethodHandleNatives {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1995,16 +1995,8 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
|
||||
// lambda( arg...) { target(arg...) } )
|
||||
MethodType newType = targetType.changeReturnType(filterType.returnType());
|
||||
MethodHandle result = null;
|
||||
if (AdapterMethodHandle.canCollectArguments(filterType, targetType, 0, false)) {
|
||||
result = 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;
|
||||
assert(AdapterMethodHandle.canCollectArguments(filterType, targetType, 0, false));
|
||||
return AdapterMethodHandle.makeCollectArguments(filter, target, 0, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,10 +56,6 @@ class MethodTypeForm {
|
||||
/*lazy*/ MethodType primsAtEnd; // reorder primitives to the end
|
||||
|
||||
// Cached adapter information:
|
||||
/*lazy*/ ToGeneric toGeneric; // convert cs. with prims to w/o
|
||||
/*lazy*/ FromGeneric fromGeneric; // convert cs. w/o prims to with
|
||||
/*lazy*/ SpreadGeneric[] spreadGeneric; // expand one argument to many
|
||||
/*lazy*/ FilterGeneric filterGeneric; // convert argument(s) on the fly
|
||||
/*lazy*/ MethodHandle genericInvoker; // hook for inexact invoke
|
||||
|
||||
public MethodType erasedType() {
|
||||
|
@ -1,682 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.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)); }
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user