提交 50e98779 编写于 作者: V vlivanov

8050166: Get rid of some package-private methods on arguments in j.l.i.MethodHandle

Reviewed-by: vlivanov, psandoz
Contributed-by: john.r.rose@oracle.com
上级 6be16bf0
...@@ -60,13 +60,12 @@ import jdk.internal.org.objectweb.asm.Type; ...@@ -60,13 +60,12 @@ import jdk.internal.org.objectweb.asm.Type;
// BMH API and internals // BMH API and internals
// //
static MethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) { static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
// for some type signatures, there exist pre-defined concrete BMH classes // for some type signatures, there exist pre-defined concrete BMH classes
try { try {
switch (xtype) { switch (xtype) {
case L_TYPE: case L_TYPE:
if (true) return bindSingle(type, form, x); // Use known fast path. return bindSingle(type, form, x); // Use known fast path.
return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(L_TYPE).constructor().invokeBasic(type, form, x);
case I_TYPE: case I_TYPE:
return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x)); return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x));
case J_TYPE: case J_TYPE:
...@@ -82,49 +81,40 @@ import jdk.internal.org.objectweb.asm.Type; ...@@ -82,49 +81,40 @@ import jdk.internal.org.objectweb.asm.Type;
} }
} }
static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) { static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
return new Species_L(type, form, x); return Species_L.make(type, form, x);
} }
MethodHandle cloneExtend(MethodType type, LambdaForm form, BasicType xtype, Object x) { @Override // there is a default binder in the super class, for 'L' types only
try { /*non-public*/
switch (xtype) { BoundMethodHandle bindArgumentL(int pos, Object value) {
case L_TYPE: return copyWithExtendL(type, form, x);
case I_TYPE: return copyWithExtendI(type, form, ValueConversions.widenSubword(x));
case J_TYPE: return copyWithExtendJ(type, form, (long) x);
case F_TYPE: return copyWithExtendF(type, form, (float) x);
case D_TYPE: return copyWithExtendD(type, form, (double) x);
}
} catch (Throwable t) {
throw newInternalError(t);
}
throw newInternalError("unexpected type: " + xtype);
}
@Override
MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
MethodType type = type().dropParameterTypes(pos, pos+1); MethodType type = type().dropParameterTypes(pos, pos+1);
LambdaForm form = internalForm().bind(1+pos, speciesData()); LambdaForm form = internalForm().bind(1+pos, speciesData());
return cloneExtend(type, form, basicType, value); return copyWithExtendL(type, form, value);
} }
/*non-public*/
@Override BoundMethodHandle bindArgumentI(int pos, int value) {
MethodHandle dropArguments(MethodType srcType, int pos, int drops) { MethodType type = type().dropParameterTypes(pos, pos+1);
LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos + drops)); LambdaForm form = internalForm().bind(1+pos, speciesData());
try { return copyWithExtendI(type, form, value);
return copyWith(srcType, form);
} catch (Throwable t) {
throw newInternalError(t);
} }
/*non-public*/
BoundMethodHandle bindArgumentJ(int pos, long value) {
MethodType type = type().dropParameterTypes(pos, pos+1);
LambdaForm form = internalForm().bind(1+pos, speciesData());
return copyWithExtendJ(type, form, value);
} }
/*non-public*/
@Override BoundMethodHandle bindArgumentF(int pos, float value) {
MethodHandle permuteArguments(MethodType newType, int[] reorder) { MethodType type = type().dropParameterTypes(pos, pos+1);
try { LambdaForm form = internalForm().bind(1+pos, speciesData());
return copyWith(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList()))); return copyWithExtendF(type, form, value);
} catch (Throwable t) {
throw newInternalError(t);
} }
/*non-public*/
BoundMethodHandle bindArgumentD(int pos, double value) {
MethodType type = type().dropParameterTypes(pos, pos + 1);
LambdaForm form = internalForm().bind(1+pos, speciesData());
return copyWithExtendD(type, form, value);
} }
/** /**
......
...@@ -211,7 +211,7 @@ public class CallSite { ...@@ -211,7 +211,7 @@ public class CallSite {
public abstract MethodHandle dynamicInvoker(); public abstract MethodHandle dynamicInvoker();
/*non-public*/ MethodHandle makeDynamicInvoker() { /*non-public*/ MethodHandle makeDynamicInvoker() {
MethodHandle getTarget = GET_TARGET.bindReceiver(this); MethodHandle getTarget = GET_TARGET.bindArgumentL(0, this);
MethodHandle invoker = MethodHandles.exactInvoker(this.type()); MethodHandle invoker = MethodHandles.exactInvoker(this.type());
return MethodHandles.foldArguments(invoker, getTarget); return MethodHandles.foldArguments(invoker, getTarget);
} }
......
...@@ -142,45 +142,8 @@ class DirectMethodHandle extends MethodHandle { ...@@ -142,45 +142,8 @@ class DirectMethodHandle extends MethodHandle {
return member; return member;
} }
@Override
MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
// If the member needs dispatching, do so.
if (pos == 0 && basicType == L_TYPE) {
DirectMethodHandle concrete = maybeRebind(value);
if (concrete != null)
return concrete.bindReceiver(value);
}
return super.bindArgument(pos, basicType, value);
}
@Override
MethodHandle bindReceiver(Object receiver) {
// If the member needs dispatching, do so.
DirectMethodHandle concrete = maybeRebind(receiver);
if (concrete != null)
return concrete.bindReceiver(receiver);
return super.bindReceiver(receiver);
}
private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(); private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
private DirectMethodHandle maybeRebind(Object receiver) {
if (receiver != null) {
switch (member.getReferenceKind()) {
case REF_invokeInterface:
case REF_invokeVirtual:
// Pre-dispatch the member.
Class<?> concreteClass = receiver.getClass();
MemberName concrete = new MemberName(concreteClass, member.getName(), member.getMethodType(), REF_invokeSpecial);
concrete = IMPL_NAMES.resolveOrNull(REF_invokeSpecial, concrete, concreteClass);
if (concrete != null)
return new DirectMethodHandle(type(), preparedLambdaForm(concrete), concrete);
break;
}
}
return null;
}
/** /**
* Create a LF which can invoke the given method. * Create a LF which can invoke the given method.
* Cache and share this structure among all methods with * Cache and share this structure among all methods with
......
...@@ -774,7 +774,7 @@ public abstract class MethodHandle { ...@@ -774,7 +774,7 @@ public abstract class MethodHandle {
/*non-public*/ MethodHandle asTypeUncached(MethodType newType) { /*non-public*/ MethodHandle asTypeUncached(MethodType newType) {
if (!type.isConvertibleTo(newType)) if (!type.isConvertibleTo(newType))
throw new WrongMethodTypeException("cannot convert "+this+" to "+newType); throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
return asTypeCache = convertArguments(newType); return asTypeCache = MethodHandleImpl.makePairwiseConvert(this, newType, 1);
} }
/** /**
...@@ -987,7 +987,7 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); ...@@ -987,7 +987,7 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123));
int collectArgPos = type().parameterCount()-1; int collectArgPos = type().parameterCount()-1;
MethodHandle target = this; MethodHandle target = this;
if (arrayType != type().parameterType(collectArgPos)) if (arrayType != type().parameterType(collectArgPos))
target = convertArguments(type().changeParameterType(collectArgPos, arrayType)); target = MethodHandleImpl.makePairwiseConvert(this, type().changeParameterType(collectArgPos, arrayType), 1);
MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength); MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength);
return MethodHandles.collectArguments(target, collectArgPos, collector); return MethodHandles.collectArguments(target, collectArgPos, collector);
} }
...@@ -1260,14 +1260,8 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); ...@@ -1260,14 +1260,8 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
* @see MethodHandles#insertArguments * @see MethodHandles#insertArguments
*/ */
public MethodHandle bindTo(Object x) { public MethodHandle bindTo(Object x) {
Class<?> ptype; x = type.leadingReferenceParameter().cast(x); // throw CCE if needed
@SuppressWarnings("LocalVariableHidesMemberVariable") return bindArgumentL(0, x);
MethodType type = type();
if (type.parameterCount() == 0 ||
(ptype = type.parameterType(0)).isPrimitive())
throw newIllegalArgumentException("no leading reference parameter", x);
x = ptype.cast(x); // throw CCE if needed
return bindReceiver(x);
} }
/** /**
...@@ -1306,6 +1300,10 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); ...@@ -1306,6 +1300,10 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
// Other transforms to do: convert, explicitCast, permute, drop, filter, fold, GWT, catch // Other transforms to do: convert, explicitCast, permute, drop, filter, fold, GWT, catch
BoundMethodHandle bindArgumentL(int pos, Object value) {
return rebind().bindArgumentL(pos, value);
}
/*non-public*/ /*non-public*/
MethodHandle setVarargs(MemberName member) throws IllegalAccessException { MethodHandle setVarargs(MemberName member) throws IllegalAccessException {
if (!member.isVarargs()) return this; if (!member.isVarargs()) return this;
...@@ -1374,37 +1372,8 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); ...@@ -1374,37 +1372,8 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
//// Sub-classes can override these default implementations. //// Sub-classes can override these default implementations.
//// All these methods assume arguments are already validated. //// All these methods assume arguments are already validated.
/*non-public*/ MethodHandle convertArguments(MethodType newType) {
// Override this if it can be improved.
return MethodHandleImpl.makePairwiseConvert(this, newType, 1);
}
/*non-public*/
MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
// Override this if it can be improved.
return rebind().bindArgument(pos, basicType, value);
}
/*non-public*/
MethodHandle bindReceiver(Object receiver) {
// Override this if it can be improved.
return bindArgument(0, L_TYPE, receiver);
}
/*non-public*/
MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
// Override this if it can be improved.
return rebind().dropArguments(srcType, pos, drops);
}
/*non-public*/
MethodHandle permuteArguments(MethodType newType, int[] reorder) {
// Override this if it can be improved.
return rebind().permuteArguments(newType, reorder);
}
/*non-public*/ /*non-public*/
MethodHandle rebind() { BoundMethodHandle rebind() {
// Bind 'this' into a new invoker, of the known class BMH. // Bind 'this' into a new invoker, of the known class BMH.
MethodType type2 = type(); MethodType type2 = type();
LambdaForm form2 = reinvokerForm(this); LambdaForm form2 = reinvokerForm(this);
......
...@@ -434,27 +434,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -434,27 +434,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
boolean isInvokeSpecial() { boolean isInvokeSpecial() {
return asFixedArity().isInvokeSpecial(); return asFixedArity().isInvokeSpecial();
} }
@Override
MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
return asFixedArity().bindArgument(pos, basicType, value);
}
@Override
MethodHandle bindReceiver(Object receiver) {
return asFixedArity().bindReceiver(receiver);
}
@Override
MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
return asFixedArity().dropArguments(srcType, pos, drops);
}
@Override
MethodHandle permuteArguments(MethodType newType, int[] reorder) {
return asFixedArity().permuteArguments(newType, reorder);
}
} }
/** Factory method: Spread selected argument. */ /** Factory method: Spread selected argument. */
...@@ -794,7 +773,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; ...@@ -794,7 +773,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
assert(Throwable.class.isAssignableFrom(type.parameterType(0))); assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
int arity = type.parameterCount(); int arity = type.parameterCount();
if (arity > 1) { if (arity > 1) {
return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1); MethodHandle mh = throwException(type.dropParameterTypes(1, arity));
mh = MethodHandles.dropArguments(mh, 1, type.parameterList().subList(1, arity));
return mh;
} }
return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, 2); return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, 2);
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
package java.lang.invoke; package java.lang.invoke;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.BitSet;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
...@@ -1144,7 +1145,7 @@ return mh1; ...@@ -1144,7 +1145,7 @@ return mh1;
Class<? extends Object> refc = receiver.getClass(); // may get NPE Class<? extends Object> refc = receiver.getClass(); // may get NPE
MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type); MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method)); MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method));
return mh.bindReceiver(receiver).setVarargs(method); return mh.bindArgumentL(0, receiver).setVarargs(method);
} }
/** /**
...@@ -2087,11 +2088,55 @@ assert((int)twice.invokeExact(21) == 42); ...@@ -2087,11 +2088,55 @@ assert((int)twice.invokeExact(21) == 42);
public static public static
MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) { MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
reorder = reorder.clone(); reorder = reorder.clone();
checkReorder(reorder, newType, target.type()); permuteArgumentChecks(reorder, newType, target.type());
return target.permuteArguments(newType, reorder); // first detect dropped arguments and handle them separately
} MethodHandle originalTarget = target;
int newArity = newType.parameterCount();
private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) { for (int dropIdx; (dropIdx = findFirstDrop(reorder, newArity)) >= 0; ) {
// dropIdx is missing from reorder; add it in at the end
int oldArity = reorder.length;
target = dropArguments(target, oldArity, newType.parameterType(dropIdx));
reorder = Arrays.copyOf(reorder, oldArity+1);
reorder[oldArity] = dropIdx;
}
assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type()));
// Note: This may cache too many distinct LFs. Consider backing off to varargs code.
BoundMethodHandle result = target.rebind();
LambdaForm form = result.form.permuteArguments(1, reorder, basicTypes(newType.parameterList()));
return result.copyWith(newType, form);
}
/** Return the first value in [0..newArity-1] that is not present in reorder. */
private static int findFirstDrop(int[] reorder, int newArity) {
final int BIT_LIMIT = 63; // max number of bits in bit mask
if (newArity < BIT_LIMIT) {
long mask = 0;
for (int arg : reorder) {
assert(arg < newArity);
mask |= (1 << arg);
}
if (mask == (1 << newArity) - 1) {
assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
return -1;
}
// find first zero
long zeroBit = Long.lowestOneBit(~mask);
int zeroPos = Long.numberOfTrailingZeros(zeroBit);
assert(zeroPos < newArity);
return zeroPos;
}
BitSet mask = new BitSet(newArity);
for (int arg : reorder) {
assert(arg < newArity);
mask.set(arg);
}
int zeroPos = mask.nextClearBit(0);
if (zeroPos == newArity)
return -1;
return zeroPos;
}
private static boolean permuteArgumentChecks(int[] reorder, MethodType newType, MethodType oldType) {
if (newType.returnType() != oldType.returnType()) if (newType.returnType() != oldType.returnType())
throw newIllegalArgumentException("return types do not match", throw newIllegalArgumentException("return types do not match",
oldType, newType); oldType, newType);
...@@ -2109,7 +2154,7 @@ assert((int)twice.invokeExact(21) == 42); ...@@ -2109,7 +2154,7 @@ assert((int)twice.invokeExact(21) == 42);
throw newIllegalArgumentException("parameter types do not match after reorder", throw newIllegalArgumentException("parameter types do not match after reorder",
oldType, newType); oldType, newType);
} }
if (!bad) return; if (!bad) return true;
} }
throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder)); throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder));
} }
...@@ -2193,38 +2238,45 @@ assert((int)twice.invokeExact(21) == 42); ...@@ -2193,38 +2238,45 @@ assert((int)twice.invokeExact(21) == 42);
public static public static
MethodHandle insertArguments(MethodHandle target, int pos, Object... values) { MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
int insCount = values.length; int insCount = values.length;
MethodType oldType = target.type(); Class<?>[] ptypes = insertArgumentsChecks(target, insCount, pos);
int outargs = oldType.parameterCount(); if (insCount == 0) return target;
int inargs = outargs - insCount; BoundMethodHandle result = target.rebind();
if (inargs < 0)
throw newIllegalArgumentException("too many values to insert");
if (pos < 0 || pos > inargs)
throw newIllegalArgumentException("no argument type to append");
MethodHandle result = target;
for (int i = 0; i < insCount; i++) { for (int i = 0; i < insCount; i++) {
Object value = values[i]; Object value = values[i];
Class<?> ptype = oldType.parameterType(pos+i); Class<?> ptype = ptypes[pos+i];
if (ptype.isPrimitive()) { if (ptype.isPrimitive()) {
BasicType btype = I_TYPE; result = insertArgumentPrimitive(result, pos, ptype, value);
Wrapper w = Wrapper.forPrimitiveType(ptype); } else {
switch (w) { value = ptype.cast(value); // throw CCE if needed
case LONG: btype = J_TYPE; break; result = result.bindArgumentL(pos, value);
case FLOAT: btype = F_TYPE; break; }
case DOUBLE: btype = D_TYPE; break;
} }
return result;
}
private static BoundMethodHandle insertArgumentPrimitive(BoundMethodHandle result, int pos,
Class<?> ptype, Object value) {
Wrapper w = Wrapper.forPrimitiveType(ptype);
// perform unboxing and/or primitive conversion // perform unboxing and/or primitive conversion
value = w.convert(value, ptype); value = w.convert(value, ptype);
result = result.bindArgument(pos, btype, value); switch (w) {
continue; case INT: return result.bindArgumentI(pos, (int)value);
} case LONG: return result.bindArgumentJ(pos, (long)value);
value = ptype.cast(value); // throw CCE if needed case FLOAT: return result.bindArgumentF(pos, (float)value);
if (pos == 0) { case DOUBLE: return result.bindArgumentD(pos, (double)value);
result = result.bindReceiver(value); default: return result.bindArgumentI(pos, ValueConversions.widenSubword(value));
} else {
result = result.bindArgument(pos, L_TYPE, value);
} }
} }
return result;
private static Class<?>[] insertArgumentsChecks(MethodHandle target, int insCount, int pos) throws RuntimeException {
MethodType oldType = target.type();
int outargs = oldType.parameterCount();
int inargs = outargs - insCount;
if (inargs < 0)
throw newIllegalArgumentException("too many values to insert");
if (pos < 0 || pos > inargs)
throw newIllegalArgumentException("no argument type to append");
return oldType.ptypes();
} }
/** /**
...@@ -2272,18 +2324,26 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z")); ...@@ -2272,18 +2324,26 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
public static public static
MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) { MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
MethodType oldType = target.type(); // get NPE MethodType oldType = target.type(); // get NPE
int dropped = dropArgumentChecks(oldType, pos, valueTypes);
if (dropped == 0) return target;
BoundMethodHandle result = target.rebind();
LambdaForm lform = result.form;
lform = lform.addArguments(pos, valueTypes);
MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
result = result.copyWith(newType, lform);
return result;
}
private static int dropArgumentChecks(MethodType oldType, int pos, List<Class<?>> valueTypes) {
int dropped = valueTypes.size(); int dropped = valueTypes.size();
MethodType.checkSlotCount(dropped); MethodType.checkSlotCount(dropped);
if (dropped == 0) return target;
int outargs = oldType.parameterCount(); int outargs = oldType.parameterCount();
int inargs = outargs + dropped; int inargs = outargs + dropped;
if (pos < 0 || pos >= inargs) if (pos < 0 || pos > outargs)
throw newIllegalArgumentException("no argument type to remove"); throw newIllegalArgumentException("no argument type to remove"
ArrayList<Class<?>> ptypes = new ArrayList<>(oldType.parameterList()); + Arrays.asList(oldType, pos, valueTypes, inargs, outargs)
ptypes.addAll(pos, valueTypes); );
if (ptypes.size() != inargs) throw newIllegalArgumentException("valueTypes"); return dropped;
MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
return target.dropArguments(newType, pos, dropped);
} }
/** /**
......
...@@ -498,6 +498,17 @@ class MethodType implements java.io.Serializable { ...@@ -498,6 +498,17 @@ class MethodType implements java.io.Serializable {
return this; // arguments check out; no change return this; // arguments check out; no change
} }
/** Return the leading parameter type, which must exist and be a reference.
* @return the leading parameter type, after error checks
*/
/*non-public*/ Class<?> leadingReferenceParameter() {
Class<?> ptype;
if (ptypes.length == 0 ||
(ptype = ptypes[0]).isPrimitive())
throw newIllegalArgumentException("no leading reference parameter");
return ptype;
}
/** /**
* Finds or creates a method type with some parameter types omitted. * Finds or creates a method type with some parameter types omitted.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}. * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
......
...@@ -25,9 +25,6 @@ ...@@ -25,9 +25,6 @@
package java.lang.invoke; package java.lang.invoke;
import static java.lang.invoke.LambdaForm.*;
import static java.lang.invoke.LambdaForm.BasicType.*;
/** /**
* A method handle whose behavior is determined only by its LambdaForm. * A method handle whose behavior is determined only by its LambdaForm.
* @author jrose * @author jrose
...@@ -40,23 +37,4 @@ final class SimpleMethodHandle extends MethodHandle { ...@@ -40,23 +37,4 @@ final class SimpleMethodHandle extends MethodHandle {
/*non-public*/ static SimpleMethodHandle make(MethodType type, LambdaForm form) { /*non-public*/ static SimpleMethodHandle make(MethodType type, LambdaForm form) {
return new SimpleMethodHandle(type, form); return new SimpleMethodHandle(type, form);
} }
@Override
MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
MethodType type2 = type().dropParameterTypes(pos, pos+1);
LambdaForm form2 = internalForm().bind(1+pos, BoundMethodHandle.SpeciesData.EMPTY);
return BoundMethodHandle.bindSingle(type2, form2, basicType, value);
}
@Override
MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
LambdaForm newForm = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops));
return new SimpleMethodHandle(srcType, newForm);
}
@Override
MethodHandle permuteArguments(MethodType newType, int[] reorder) {
LambdaForm form2 = internalForm().permuteArguments(1, reorder, basicTypes(newType.parameterList()));
return new SimpleMethodHandle(newType, form2);
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册