提交 887350b0 编写于 作者: J jrose

6939134: JSR 292 adjustments to method handle invocation

Summary: split MethodHandle.invoke into invokeExact and invokeGeneric
Reviewed-by: twisti
上级 c8e0d291
......@@ -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();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册