提交 0c13f227 编写于 作者: V vlivanov

8050173: Add j.l.i.MethodHandle.copyWith(MethodType, LambdaForm)

Reviewed-by: vlivanov, psandoz
Contributed-by: john.r.rose@oracle.com
上级 50e98779
......@@ -242,7 +242,7 @@ public class CallSite {
invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker);
}
// unchecked view is OK since no values will be received or returned
return invoker.viewAsType(targetType);
return invoker.viewAsType(targetType, false);
}
// unsafe stuff:
......
......@@ -126,6 +126,12 @@ class DirectMethodHandle extends MethodHandle {
return new Constructor(mtype, lform, ctor, init, instanceClass);
}
@Override
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
assert(this.getClass() == DirectMethodHandle.class); // must override in subclasses
return new DirectMethodHandle(mt, lf, member);
}
@Override
String internalProperties() {
return "\n& DMH.MN="+internalMemberName();
......@@ -133,10 +139,6 @@ class DirectMethodHandle extends MethodHandle {
//// Implementation methods.
@Override
MethodHandle viewAsType(MethodType newType) {
return new DirectMethodHandle(newType, form, member);
}
@Override
@ForceInline
MemberName internalMemberName() {
return member;
......@@ -364,8 +366,8 @@ class DirectMethodHandle extends MethodHandle {
return true;
}
@Override
MethodHandle viewAsType(MethodType newType) {
return new Special(newType, form, member);
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
return new Special(mt, lf, member);
}
}
......@@ -382,8 +384,8 @@ class DirectMethodHandle extends MethodHandle {
assert(initMethod.isResolved());
}
@Override
MethodHandle viewAsType(MethodType newType) {
return new Constructor(newType, form, member, initMethod, instanceClass);
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
return new Constructor(mt, lf, member, initMethod, instanceClass);
}
}
......@@ -412,8 +414,8 @@ class DirectMethodHandle extends MethodHandle {
return fieldType.cast(obj);
}
@Override
MethodHandle viewAsType(MethodType newType) {
return new Accessor(newType, form, member, fieldOffset);
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
return new Accessor(mt, lf, member, fieldOffset);
}
}
......@@ -455,8 +457,8 @@ class DirectMethodHandle extends MethodHandle {
return fieldType.cast(obj);
}
@Override
MethodHandle viewAsType(MethodType newType) {
return new StaticAccessor(newType, form, member, staticBase, staticOffset);
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
return new StaticAccessor(mt, lf, member, staticBase, staticOffset);
}
}
......
......@@ -1315,9 +1315,27 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
}
/*non-public*/
MethodHandle viewAsType(MethodType newType) {
MethodHandle viewAsType(MethodType newType, boolean strict) {
// No actual conversions, just a new view of the same method.
return MethodHandleImpl.makePairwiseConvert(this, newType, 0);
// Note that this operation must not produce a DirectMethodHandle,
// because retyped DMHs, like any transformed MHs,
// cannot be cracked into MethodHandleInfo.
assert viewAsTypeChecks(newType, strict);
BoundMethodHandle mh = rebind();
assert(!((MethodHandle)mh instanceof DirectMethodHandle));
return mh.copyWith(newType, mh.form);
}
/*non-public*/
boolean viewAsTypeChecks(MethodType newType, boolean strict) {
if (strict) {
assert(type().isViewableAs(newType, true))
: Arrays.asList(this, newType);
} else {
assert(type().basicType().isViewableAs(newType.basicType(), true))
: Arrays.asList(this, newType);
}
return true;
}
// Decoding
......@@ -1372,6 +1390,9 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
//// Sub-classes can override these default implementations.
//// All these methods assume arguments are already validated.
/*non-public*/
abstract MethodHandle copyWith(MethodType mt, LambdaForm lf);
/*non-public*/
BoundMethodHandle rebind() {
// Bind 'this' into a new invoker, of the known class BMH.
......
......@@ -84,7 +84,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class);
assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType());
// safe to view non-strictly, because element type follows from array type
mh = mh.viewAsType(correctType);
mh = mh.viewAsType(correctType, false);
}
// Atomically update accessor cache.
synchronized(cache) {
......@@ -406,18 +406,21 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
}
@Override
MethodHandle setVarargs(MemberName member) {
if (member.isVarargs()) return this;
return asFixedArity();
boolean viewAsTypeChecks(MethodType newType, boolean strict) {
super.viewAsTypeChecks(newType, true);
if (strict) return true;
// extra assertion for non-strict checks:
assert (type().lastParameterType().getComponentType()
.isAssignableFrom(
newType.lastParameterType().getComponentType()))
: Arrays.asList(this, newType);
return true;
}
@Override
MethodHandle viewAsType(MethodType newType) {
if (newType.lastParameterType() != type().lastParameterType())
throw new InternalError();
MethodHandle newTarget = asFixedArity().viewAsType(newType);
// put back the varargs bit:
return new AsVarargsCollector(newTarget, newType, arrayType);
MethodHandle setVarargs(MemberName member) {
if (member.isVarargs()) return this;
return asFixedArity();
}
@Override
......@@ -434,6 +437,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
boolean isInvokeSpecial() {
return asFixedArity().isInvokeSpecial();
}
@Override
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
throw newIllegalArgumentException("do not use this");
}
}
/** Factory method: Spread selected argument. */
......@@ -996,9 +1004,10 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
boolean isInvokeSpecial() {
return target.isInvokeSpecial();
}
@Override
MethodHandle viewAsType(MethodType newType) {
return new WrappedMember(target, newType, member, callerClass);
MethodHandle copyWith(MethodType mt, LambdaForm lf) {
throw newIllegalArgumentException("do not use this");
}
}
......
......@@ -1580,7 +1580,7 @@ return mh1;
return false;
return true;
}
private MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException {
private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class<?> caller) throws IllegalAccessException {
assert(!method.isStatic());
// receiver type of mh is too wide; narrow to caller
if (!method.getDeclaringClass().isAssignableFrom(caller)) {
......@@ -1589,7 +1589,9 @@ return mh1;
MethodType rawType = mh.type();
if (rawType.parameterType(0) == caller) return mh;
MethodType narrowType = rawType.changeParameterType(0, caller);
return mh.viewAsType(narrowType);
assert(!mh.isVarargsCollector()); // viewAsType will lose varargs-ness
assert(mh.viewAsTypeChecks(narrowType, true));
return mh.copyWith(narrowType, mh.form);
}
/** Check access and get the requested method. */
......@@ -1651,15 +1653,17 @@ return mh1;
checkMethod(refKind, refc, method);
}
MethodHandle mh = DirectMethodHandle.make(refKind, refc, method);
mh = maybeBindCaller(method, mh, callerClass);
mh = mh.setVarargs(method);
DirectMethodHandle dmh = DirectMethodHandle.make(refKind, refc, method);
MethodHandle mh = dmh;
// Optionally narrow the receiver argument to refc using restrictReceiver.
if (doRestrict &&
(refKind == REF_invokeSpecial ||
(MethodHandleNatives.refKindHasReceiver(refKind) &&
restrictProtectedReceiver(method))))
mh = restrictReceiver(method, mh, lookupClass());
restrictProtectedReceiver(method)))) {
mh = restrictReceiver(method, dmh, lookupClass());
}
mh = maybeBindCaller(method, mh, callerClass);
mh = mh.setVarargs(method);
return mh;
}
private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh,
......@@ -1691,12 +1695,12 @@ return mh1;
// Optionally check with the security manager; this isn't needed for unreflect* calls.
if (checkSecurity)
checkSecurityManager(refc, field);
MethodHandle mh = DirectMethodHandle.make(refc, field);
DirectMethodHandle dmh = DirectMethodHandle.make(refc, field);
boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(refKind) &&
restrictProtectedReceiver(field));
if (doRestrict)
mh = restrictReceiver(field, mh, lookupClass());
return mh;
return restrictReceiver(field, dmh, lookupClass());
return dmh;
}
/** Check access and get the requested constructor. */
private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
......
......@@ -775,16 +775,27 @@ class MethodType implements java.io.Serializable {
return sb.toString();
}
/** True if the old return type can always be viewed (w/o casting) under new return type,
* and the new parameters can be viewed (w/o casting) under the old parameter types.
*/
/*non-public*/
boolean isViewableAs(MethodType newType) {
if (!VerifyType.isNullConversion(returnType(), newType.returnType(), true))
boolean isViewableAs(MethodType newType, boolean keepInterfaces) {
if (!VerifyType.isNullConversion(returnType(), newType.returnType(), keepInterfaces))
return false;
return parametersAreViewableAs(newType, keepInterfaces);
}
/** True if the new parameters can be viewed (w/o casting) under the old parameter types. */
/*non-public*/
boolean parametersAreViewableAs(MethodType newType, boolean keepInterfaces) {
if (form == newType.form && form.erasedType == this)
return true; // my reference parameters are all Object
if (ptypes == newType.ptypes)
return true;
int argc = parameterCount();
if (argc != newType.parameterCount())
return false;
for (int i = 0; i < argc; i++) {
if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i), true))
if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i), keepInterfaces))
return false;
}
return true;
......
......@@ -37,4 +37,9 @@ final class SimpleMethodHandle extends MethodHandle {
/*non-public*/ static SimpleMethodHandle make(MethodType type, LambdaForm form) {
return new SimpleMethodHandle(type, form);
}
@Override
/*non-public*/ SimpleMethodHandle copyWith(MethodType mt, LambdaForm lf) {
return make(mt, lf);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册