6939134: JSR 292 adjustments to method handle invocation
Split MethodHandle.invoke into invokeExact and invokeGeneric Reviewed-by: twisti
This commit is contained in:
parent
9329c4986e
commit
a56ce23775
@ -230,6 +230,12 @@ public class Flags {
|
||||
*/
|
||||
public static final long PROPRIETARY = 1L<<38;
|
||||
|
||||
/**
|
||||
* Flag that marks a signature-polymorphic invoke method.
|
||||
* (These occur inside java.dyn.MethodHandle.)
|
||||
*/
|
||||
public static final long POLYMORPHIC_SIGNATURE = 1L<<39;
|
||||
|
||||
/** Modifier masks.
|
||||
*/
|
||||
public static final int
|
||||
|
@ -168,6 +168,10 @@ public enum Source {
|
||||
public boolean allowStringsInSwitch() {
|
||||
return compareTo(JDK1_7) >= 0;
|
||||
}
|
||||
// JSR 292: recognize @PolymorphicSignature on java/dyn names
|
||||
public boolean allowPolymorphicSignature() {
|
||||
return compareTo(JDK1_7) >= 0;
|
||||
}
|
||||
public static SourceVersion toSourceVersion(Source source) {
|
||||
switch(source) {
|
||||
case JDK1_2:
|
||||
|
@ -120,6 +120,7 @@ public class Symtab {
|
||||
public final Type cloneableType;
|
||||
public final Type serializableType;
|
||||
public final Type methodHandleType;
|
||||
public final Type polymorphicSignatureType;
|
||||
public final Type invokeDynamicType;
|
||||
public final Type throwableType;
|
||||
public final Type errorType;
|
||||
@ -291,24 +292,6 @@ public class Symtab {
|
||||
}
|
||||
}
|
||||
|
||||
public void synthesizeMHTypeIfMissing(final Type type) {
|
||||
final Completer completer = type.tsym.completer;
|
||||
if (completer != null) {
|
||||
type.tsym.completer = new Completer() {
|
||||
public void complete(Symbol sym) throws CompletionFailure {
|
||||
try {
|
||||
completer.complete(sym);
|
||||
} catch (CompletionFailure e) {
|
||||
sym.flags_field |= (PUBLIC | ABSTRACT);
|
||||
((ClassType) sym.type).supertype_field = objectType;
|
||||
// do not bother to create MH.type if not visibly declared
|
||||
// this sym just accumulates invoke(...) methods
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void synthesizeBoxTypeIfMissing(final Type type) {
|
||||
ClassSymbol sym = reader.enterClass(boxedName[type.tag]);
|
||||
final Completer completer = sym.completer;
|
||||
@ -426,6 +409,7 @@ public class Symtab {
|
||||
throwableType = enterClass("java.lang.Throwable");
|
||||
serializableType = enterClass("java.io.Serializable");
|
||||
methodHandleType = enterClass("java.dyn.MethodHandle");
|
||||
polymorphicSignatureType = enterClass("java.dyn.MethodHandle$PolymorphicSignature");
|
||||
invokeDynamicType = enterClass("java.dyn.InvokeDynamic");
|
||||
errorType = enterClass("java.lang.Error");
|
||||
illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException");
|
||||
@ -463,8 +447,7 @@ public class Symtab {
|
||||
|
||||
synthesizeEmptyInterfaceIfMissing(cloneableType);
|
||||
synthesizeEmptyInterfaceIfMissing(serializableType);
|
||||
synthesizeMHTypeIfMissing(methodHandleType);
|
||||
synthesizeMHTypeIfMissing(invokeDynamicType);
|
||||
synthesizeEmptyInterfaceIfMissing(polymorphicSignatureType);
|
||||
synthesizeBoxTypeIfMissing(doubleType);
|
||||
synthesizeBoxTypeIfMissing(floatType);
|
||||
synthesizeBoxTypeIfMissing(voidType);
|
||||
|
@ -122,7 +122,6 @@ public class Attr extends JCTree.Visitor {
|
||||
relax = (options.get("-retrofit") != null ||
|
||||
options.get("-relax") != null);
|
||||
useBeforeDeclarationWarning = options.get("useBeforeDeclarationWarning") != null;
|
||||
allowInvokedynamic = options.get("invokedynamic") != null;
|
||||
enableSunApiLintControl = options.get("enableSunApiLintControl") != null;
|
||||
}
|
||||
|
||||
@ -155,10 +154,6 @@ public class Attr extends JCTree.Visitor {
|
||||
*/
|
||||
boolean allowAnonOuterThis;
|
||||
|
||||
/** Switch: allow invokedynamic syntax
|
||||
*/
|
||||
boolean allowInvokedynamic;
|
||||
|
||||
/**
|
||||
* Switch: warn about use of variable before declaration?
|
||||
* RFE: 6425594
|
||||
@ -1377,9 +1372,15 @@ public class Attr extends JCTree.Visitor {
|
||||
// as a special case, MethodHandle.<T>invoke(abc) and InvokeDynamic.<T>foo(abc)
|
||||
// has type <T>, and T can be a primitive type.
|
||||
if (tree.meth.getTag() == JCTree.SELECT && !typeargtypes.isEmpty()) {
|
||||
Type selt = ((JCFieldAccess) tree.meth).selected.type;
|
||||
if ((selt == syms.methodHandleType && methName == names.invoke) || selt == syms.invokeDynamicType) {
|
||||
JCFieldAccess mfield = (JCFieldAccess) tree.meth;
|
||||
if ((mfield.selected.type.tsym != null &&
|
||||
(mfield.selected.type.tsym.flags() & POLYMORPHIC_SIGNATURE) != 0)
|
||||
||
|
||||
(mfield.sym != null &&
|
||||
(mfield.sym.flags() & POLYMORPHIC_SIGNATURE) != 0)) {
|
||||
assert types.isSameType(restype, typeargtypes.head) : mtype;
|
||||
assert mfield.selected.type == syms.methodHandleType
|
||||
|| mfield.selected.type == syms.invokeDynamicType;
|
||||
typeargtypesNonRefOK = true;
|
||||
}
|
||||
}
|
||||
|
@ -768,6 +768,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
&& s.owner.kind != MTH
|
||||
&& types.isSameType(c.type, syms.deprecatedType))
|
||||
s.flags_field |= Flags.DEPRECATED;
|
||||
// Internally to java.dyn, a @PolymorphicSignature annotation
|
||||
// translates to a classfile attribute.
|
||||
if (!c.type.isErroneous()
|
||||
&& types.isSameType(c.type, syms.polymorphicSignatureType)) {
|
||||
s.flags_field |= Flags.POLYMORPHIC_SIGNATURE;
|
||||
}
|
||||
if (!annotated.add(a.type.tsym))
|
||||
log.error(a.pos, "duplicate.annotation");
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class Resolve {
|
||||
JCDiagnostic.Factory diags;
|
||||
public final boolean boxingEnabled; // = source.allowBoxing();
|
||||
public final boolean varargsEnabled; // = source.allowVarargs();
|
||||
public final boolean allowInvokedynamic; // = options.get("invokedynamic");
|
||||
public final boolean allowPolymorphicSignature;
|
||||
private final boolean debugResolve;
|
||||
|
||||
public static Resolve instance(Context context) {
|
||||
@ -105,7 +105,7 @@ public class Resolve {
|
||||
varargsEnabled = source.allowVarargs();
|
||||
Options options = Options.instance(context);
|
||||
debugResolve = options.get("debugresolve") != null;
|
||||
allowInvokedynamic = options.get("invokedynamic") != null;
|
||||
allowPolymorphicSignature = source.allowPolymorphicSignature() || options.get("invokedynamic") != null;
|
||||
}
|
||||
|
||||
/** error symbols, which are returned when resolution fails
|
||||
@ -301,6 +301,7 @@ public class Resolve {
|
||||
boolean useVarargs,
|
||||
Warner warn)
|
||||
throws Infer.InferenceException {
|
||||
assert ((m.flags() & (POLYMORPHIC_SIGNATURE|HYPOTHETICAL)) != POLYMORPHIC_SIGNATURE);
|
||||
if (useVarargs && (m.flags() & VARARGS) == 0) return null;
|
||||
Type mt = types.memberType(site, m);
|
||||
|
||||
@ -575,6 +576,14 @@ public class Resolve {
|
||||
if (sym.kind == ERR) return bestSoFar;
|
||||
if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar;
|
||||
assert sym.kind < AMBIGUOUS;
|
||||
if ((sym.flags() & POLYMORPHIC_SIGNATURE) != 0 && allowPolymorphicSignature) {
|
||||
assert(site.tag == CLASS);
|
||||
// Never match a MethodHandle.invoke directly.
|
||||
if (useVarargs | allowBoxing | operator)
|
||||
return bestSoFar;
|
||||
// Supply an exactly-typed implicit method instead.
|
||||
sym = findPolymorphicSignatureInstance(env, sym.owner.type, sym.name, (MethodSymbol) sym, argtypes, typeargtypes);
|
||||
}
|
||||
try {
|
||||
if (rawInstantiate(env, site, sym, argtypes, typeargtypes,
|
||||
allowBoxing, useVarargs, Warner.noWarnings) == null) {
|
||||
@ -745,6 +754,14 @@ public class Resolve {
|
||||
boolean allowBoxing,
|
||||
boolean useVarargs,
|
||||
boolean operator) {
|
||||
Symbol bestSoFar = methodNotFound;
|
||||
if ((site.tsym.flags() & POLYMORPHIC_SIGNATURE) != 0 &&
|
||||
allowPolymorphicSignature &&
|
||||
site.tag == CLASS &&
|
||||
!(useVarargs | allowBoxing | operator)) {
|
||||
// supply an exactly-typed implicit method in java.dyn.InvokeDynamic
|
||||
bestSoFar = findPolymorphicSignatureInstance(env, site, name, null, argtypes, typeargtypes);
|
||||
}
|
||||
return findMethod(env,
|
||||
site,
|
||||
name,
|
||||
@ -752,7 +769,7 @@ public class Resolve {
|
||||
typeargtypes,
|
||||
site.tsym.type,
|
||||
true,
|
||||
methodNotFound,
|
||||
bestSoFar,
|
||||
allowBoxing,
|
||||
useVarargs,
|
||||
operator);
|
||||
@ -896,13 +913,14 @@ public class Resolve {
|
||||
* @param argtypes The method's value arguments.
|
||||
* @param typeargtypes The method's type arguments
|
||||
*/
|
||||
Symbol findImplicitMethod(Env<AttrContext> env,
|
||||
Type site,
|
||||
Name name,
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
assert allowInvokedynamic;
|
||||
assert site == syms.invokeDynamicType || (site == syms.methodHandleType && name == names.invoke);
|
||||
Symbol findPolymorphicSignatureInstance(Env<AttrContext> env,
|
||||
Type site,
|
||||
Name name,
|
||||
MethodSymbol spMethod, // sig. poly. method or null if none
|
||||
List<Type> argtypes,
|
||||
List<Type> typeargtypes) {
|
||||
assert allowPolymorphicSignature;
|
||||
//assert site == syms.invokeDynamicType || site == syms.methodHandleType : site;
|
||||
ClassSymbol c = (ClassSymbol) site.tsym;
|
||||
Scope implicit = c.members().next;
|
||||
if (implicit == null) {
|
||||
@ -917,12 +935,22 @@ public class Resolve {
|
||||
return methodNotFound;
|
||||
}
|
||||
List<Type> paramtypes = Type.map(argtypes, implicitArgType);
|
||||
long flags;
|
||||
List<Type> exType;
|
||||
if (spMethod != null) {
|
||||
exType = spMethod.getThrownTypes();
|
||||
flags = spMethod.flags() & AccessFlags;
|
||||
} else {
|
||||
// make it throw all exceptions
|
||||
//assert(site == syms.invokeDynamicType);
|
||||
exType = List.of(syms.throwableType);
|
||||
flags = PUBLIC | STATIC;
|
||||
}
|
||||
MethodType mtype = new MethodType(paramtypes,
|
||||
restype,
|
||||
List.<Type>nil(),
|
||||
exType,
|
||||
syms.methodClass);
|
||||
int flags = PUBLIC | ABSTRACT;
|
||||
if (site == syms.invokeDynamicType) flags |= STATIC;
|
||||
flags |= ABSTRACT | HYPOTHETICAL | POLYMORPHIC_SIGNATURE;
|
||||
Symbol m = null;
|
||||
for (Scope.Entry e = implicit.lookup(name);
|
||||
e.scope != null;
|
||||
@ -1337,14 +1365,6 @@ public class Resolve {
|
||||
methodResolutionCache.put(steps.head, sym);
|
||||
steps = steps.tail;
|
||||
}
|
||||
if (sym.kind >= AMBIGUOUS &&
|
||||
allowInvokedynamic &&
|
||||
(site == syms.invokeDynamicType ||
|
||||
site == syms.methodHandleType && name == names.invoke)) {
|
||||
// lookup failed; supply an exactly-typed implicit method
|
||||
sym = findImplicitMethod(env, site, name, argtypes, typeargtypes);
|
||||
env.info.varArgs = false;
|
||||
}
|
||||
if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
|
||||
MethodResolutionPhase errPhase =
|
||||
firstErroneousResolutionPhase();
|
||||
|
@ -1098,6 +1098,12 @@ public class ClassReader implements Completer {
|
||||
}
|
||||
},
|
||||
|
||||
new AttributeReader(names.PolymorphicSignature, V45_3/*S.B.V51*/, CLASS_OR_MEMBER_ATTRIBUTE) {
|
||||
void read(Symbol sym, int attrLen) {
|
||||
sym.flags_field |= POLYMORPHIC_SIGNATURE;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// The following attributes for a Code attribute are not currently handled
|
||||
// StackMapTable
|
||||
|
@ -651,6 +651,13 @@ public class ClassWriter extends ClassFile {
|
||||
endAttr(alenIdx);
|
||||
acount++;
|
||||
}
|
||||
if ((flags & POLYMORPHIC_SIGNATURE) != 0) {
|
||||
if (target.majorVersion < 51)
|
||||
throw new AssertionError("PolymorphicSignature attributes in java/dyn must be written with -target 7 (required major version is 51, current is"+target.majorVersion+")");
|
||||
int alenIdx = writeAttr(names.PolymorphicSignature);
|
||||
endAttr(alenIdx);
|
||||
acount++;
|
||||
}
|
||||
return acount;
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ public class Gen extends JCTree.Visitor {
|
||||
: options.get("-g:vars") != null;
|
||||
genCrt = options.get("-Xjcov") != null;
|
||||
debugCode = options.get("debugcode") != null;
|
||||
allowInvokedynamic = options.get("invokedynamic") != null;
|
||||
allowInvokedynamic = target.hasInvokedynamic() || options.get("invokedynamic") != null;
|
||||
|
||||
generateIproxies =
|
||||
target.requiresIproxy() ||
|
||||
|
@ -281,9 +281,6 @@ public class Main {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target.hasInvokedynamic()) {
|
||||
options.put("invokedynamic", "invokedynamic");
|
||||
}
|
||||
|
||||
// handle this here so it works even if no other options given
|
||||
String showClass = options.get("showClass");
|
||||
|
@ -103,6 +103,7 @@ public class Names {
|
||||
public final Name RuntimeInvisibleTypeAnnotations;
|
||||
public final Name RuntimeVisibleParameterAnnotations;
|
||||
public final Name RuntimeInvisibleParameterAnnotations;
|
||||
public final Name PolymorphicSignature;
|
||||
public final Name Value;
|
||||
public final Name EnclosingMethod;
|
||||
public final Name desiredAssertionStatus;
|
||||
@ -115,7 +116,6 @@ public class Names {
|
||||
public final Name value;
|
||||
public final Name getMessage;
|
||||
public final Name getClass;
|
||||
public final Name invoke;
|
||||
public final Name TYPE;
|
||||
public final Name TYPE_USE;
|
||||
public final Name TYPE_PARAMETER;
|
||||
@ -213,6 +213,7 @@ public class Names {
|
||||
RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
|
||||
RuntimeVisibleParameterAnnotations = fromString("RuntimeVisibleParameterAnnotations");
|
||||
RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
|
||||
PolymorphicSignature = fromString("PolymorphicSignature");
|
||||
Value = fromString("Value");
|
||||
EnclosingMethod = fromString("EnclosingMethod");
|
||||
|
||||
@ -227,7 +228,6 @@ public class Names {
|
||||
value = fromString("value");
|
||||
getMessage = fromString("getMessage");
|
||||
getClass = fromString("getClass");
|
||||
invoke = fromString("invoke");
|
||||
|
||||
TYPE = fromString("TYPE");
|
||||
TYPE_USE = fromString("TYPE_USE");
|
||||
|
@ -47,7 +47,7 @@ package meth;
|
||||
import java.dyn.InvokeDynamic;
|
||||
|
||||
public class InvokeDyn {
|
||||
void test() {
|
||||
void test() throws Throwable {
|
||||
Object x = "hello";
|
||||
InvokeDynamic.greet(x, "world", 123);
|
||||
InvokeDynamic.greet(x, "mundus", 456);
|
||||
|
@ -48,28 +48,56 @@ public class InvokeMH {
|
||||
void test(MethodHandle mh_SiO,
|
||||
MethodHandle mh_vS,
|
||||
MethodHandle mh_vi,
|
||||
MethodHandle mh_vv) {
|
||||
MethodHandle mh_vv) throws Throwable {
|
||||
Object o; String s; int i; // for return type testing
|
||||
|
||||
// next five must have sig = (String,int)Object
|
||||
mh_SiO.invoke("world", 123);
|
||||
mh_SiO.invoke("mundus", 456);
|
||||
mh_SiO.invokeExact("world", 123);
|
||||
mh_SiO.invokeExact("mundus", 456);
|
||||
Object k = "kosmos";
|
||||
mh_SiO.invoke((String)k, 789);
|
||||
o = mh_SiO.invoke((String)null, 000);
|
||||
o = mh_SiO.<Object>invoke("arda", -123);
|
||||
mh_SiO.invokeExact((String)k, 789);
|
||||
o = mh_SiO.invokeExact((String)null, 000);
|
||||
o = mh_SiO.<Object>invokeExact("arda", -123);
|
||||
|
||||
// sig = ()String
|
||||
s = mh_vS.<String>invoke();
|
||||
s = mh_vS.<String>invokeExact();
|
||||
|
||||
// sig = ()int
|
||||
i = mh_vi.<int>invoke();
|
||||
o = mh_vi.<int>invoke();
|
||||
//s = mh_vi.<int>invoke(); //BAD
|
||||
mh_vi.<int>invoke();
|
||||
i = mh_vi.<int>invokeExact();
|
||||
o = mh_vi.<int>invokeExact();
|
||||
//s = mh_vi.<int>invokeExact(); //BAD
|
||||
mh_vi.<int>invokeExact();
|
||||
|
||||
// sig = ()void
|
||||
//o = mh_vv.<void>invoke(); //BAD
|
||||
mh_vv.<void>invoke();
|
||||
//o = mh_vv.<void>invokeExact(); //BAD
|
||||
mh_vv.<void>invokeExact();
|
||||
}
|
||||
|
||||
void testGen(MethodHandle mh_SiO,
|
||||
MethodHandle mh_vS,
|
||||
MethodHandle mh_vi,
|
||||
MethodHandle mh_vv) throws Throwable {
|
||||
Object o; String s; int i; // for return type testing
|
||||
|
||||
// next five must have sig = (*,*)*
|
||||
mh_SiO.invokeGeneric((Object)"world", (Object)123);
|
||||
mh_SiO.<void>invokeGeneric((Object)"mundus", (Object)456);
|
||||
Object k = "kosmos";
|
||||
mh_SiO.invokeGeneric(k, 789);
|
||||
o = mh_SiO.invokeGeneric(null, 000);
|
||||
o = mh_SiO.<Object>invokeGeneric("arda", -123);
|
||||
|
||||
// sig = ()String
|
||||
o = mh_vS.invokeGeneric();
|
||||
|
||||
// sig = ()int
|
||||
i = mh_vi.<int>invokeGeneric();
|
||||
o = mh_vi.invokeGeneric();
|
||||
//s = mh_vi.<int>invokeGeneric(); //BAD
|
||||
mh_vi.<void>invokeGeneric();
|
||||
|
||||
// sig = ()void
|
||||
//o = mh_vv.<void>invokeGeneric(); //BAD
|
||||
o = mh_vv.invokeGeneric();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user