--- a/meth.patch Tue Jan 20 23:10:57 2009 -0800
+++ b/meth.patch Tue Jan 20 23:11:25 2009 -0800
@@ -1,3 +1,5 @@ diff --git a/src/share/classes/com/sun/t
+6754038: writing libraries in Java for non-Java languages requires method handle invocation
+
diff --git a/src/share/classes/com/sun/tools/classfile/OpCodes.java b/src/share/classes/com/sun/tools/classfile/OpCodes.java
--- a/src/share/classes/com/sun/tools/classfile/OpCodes.java
+++ b/src/share/classes/com/sun/tools/classfile/OpCodes.java
@@ -22,7 +24,7 @@ diff --git a/src/share/classes/com/sun/t
diff --git a/src/share/classes/com/sun/tools/javac/code/Symtab.java b/src/share/classes/com/sun/tools/javac/code/Symtab.java
--- a/src/share/classes/com/sun/tools/javac/code/Symtab.java
+++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java
-@@ -120,6 +120,8 @@
+@@ -119,6 +119,8 @@
public final Type stringBuilderType;
public final Type cloneableType;
public final Type serializableType;
@@ -31,7 +33,7 @@ diff --git a/src/share/classes/com/sun/t
public final Type throwableType;
public final Type errorType;
public final Type illegalArgumentExceptionType;
-@@ -290,6 +292,24 @@
+@@ -289,6 +291,24 @@
}
}
@@ -56,7 +58,7 @@ diff --git a/src/share/classes/com/sun/t
public void synthesizeBoxTypeIfMissing(final Type type) {
ClassSymbol sym = reader.enterClass(boxedName[type.tag]);
final Completer completer = sym.completer;
-@@ -403,6 +423,8 @@
+@@ -405,6 +425,8 @@
cloneableType = enterClass("java.lang.Cloneable");
throwableType = enterClass("java.lang.Throwable");
serializableType = enterClass("java.io.Serializable");
@@ -65,7 +67,7 @@ diff --git a/src/share/classes/com/sun/t
errorType = enterClass("java.lang.Error");
illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException");
exceptionType = enterClass("java.lang.Exception");
-@@ -439,6 +461,8 @@
+@@ -441,6 +463,8 @@
synthesizeEmptyInterfaceIfMissing(cloneableType);
synthesizeEmptyInterfaceIfMissing(serializableType);
@@ -85,17 +87,17 @@ diff --git a/src/share/classes/com/sun/t
}
/** Switch: relax some constraints for retrofit mode.
-@@ -148,6 +149,10 @@
- * objects during constructor call?
+@@ -149,6 +150,10 @@
*/
boolean allowAnonOuterThis;
-+
+
+ /** Switch: allow invokedynamic syntax
+ */
+ boolean allowInvokedynamic;
-
++
/**
* Switch: warn about use of variable before declaration?
+ * RFE: 6425594
@@ -438,14 +443,22 @@
}
@@ -139,12 +141,10 @@ diff --git a/src/share/classes/com/sun/t
// ... and attribute the method using as a prototype a methodtype
// whose formal argument types is exactly the list of actual
-@@ -1316,6 +1331,20 @@
- BoundKind.EXTENDS,
- syms.boundClass)),
+@@ -1318,6 +1333,20 @@
restype.tsym);
-+ }
-+
+ }
+
+ // as a special case, MethodHandle.<T>invoke(abc) and Dynamic.<T>foo(abc)
+ // has type <T>, and T can be a primitive type.
+ if (tree.meth.getTag() == JCTree.SELECT && !typeargtypes.isEmpty()) {
@@ -157,10 +157,12 @@ diff --git a/src/share/classes/com/sun/t
+
+ if (!typeargtypesNonRefOK) {
+ chk.checkRefTypes(tree.typeargs, typeargtypes);
- }
-
++ }
++
// Check that value of resulting type is admissible in the
-@@ -1919,7 +1948,8 @@
+ // current context. Also, capture the return type
+ result = check(tree, capture(restype), VAL, pkind, pt);
+@@ -1921,7 +1950,8 @@
// Check if type-qualified fields or methods are static (JLS)
if ((sym.flags() & STATIC) == 0 &&
sym.name != names._super &&
@@ -184,14 +186,12 @@ diff --git a/src/share/classes/com/sun/t
+ return syms.errType;
+ }
log.error(pos, "type.found.req", found, required);
- return syms.errType;
- }
-@@ -545,6 +551,20 @@
- diags.fragment("type.req.ref"),
- t);
+ return types.createErrorType(found instanceof Type ? (Type)found : syms.errType);
+ }
+@@ -547,6 +553,20 @@
}
-+ }
-+
+ }
+
+ /** Check that each type is a reference type, i.e. a class, interface or array type
+ * or a type variable.
+ * @param trees Original trees, used for error reporting.
@@ -204,29 +204,31 @@ diff --git a/src/share/classes/com/sun/t
+ tl = tl.tail;
+ }
+ return types;
- }
-
++ }
++
/** Check that type is a null or reference type.
+ * @param pos Position to be used for error reporting.
+ * @param t The type to be checked.
diff --git a/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/share/classes/com/sun/tools/javac/comp/Resolve.java
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java
-@@ -62,6 +62,7 @@
+@@ -67,6 +67,7 @@
JCDiagnostic.Factory diags;
public final boolean boxingEnabled; // = source.allowBoxing();
public final boolean varargsEnabled; // = source.allowVarargs();
-+ public final String invokedynamicString; // = options.get("invokedynamic");
++ public final boolean allowInvokedynamic; // = options.get("invokedynamic");
private final boolean debugResolve;
public static Resolve instance(Context context) {
-@@ -99,6 +100,7 @@
+@@ -104,6 +105,7 @@
varargsEnabled = source.allowVarargs();
Options options = Options.instance(context);
debugResolve = options.get("debugresolve") != null;
-+ invokedynamicString = options.get("invokedynamic");
++ allowInvokedynamic = options.get("invokedynamic") != null;
}
/** error symbols, which are returned when resolution fails
-@@ -852,6 +854,83 @@
+@@ -858,6 +860,76 @@
return bestSoFar;
}
@@ -245,9 +247,8 @@ diff --git a/src/share/classes/com/sun/t
+ Name name,
+ List<Type> argtypes,
+ List<Type> typeargtypes) {
-+ assert invokedynamicString != null;
++ assert allowInvokedynamic;
+ assert site == syms.dynamicType || (site == syms.methodHandleType && name == names.invoke);
-+ boolean isTransitionalStatic = (site == syms.dynamicType && invokedynamicString.equals("invokestatic"));
+ ClassSymbol c = (ClassSymbol) site.tsym;
+ Scope implicit = c.members().next;
+ if (implicit == null) {
@@ -262,17 +263,11 @@ diff --git a/src/share/classes/com/sun/t
+ return methodNotFound;
+ }
+ List<Type> paramtypes = Type.map(argtypes, implicitArgType);
-+ if (site == syms.dynamicType && invokedynamicString.equals("invokeinterface")) {
-+ // force leading arg to object, so it can act as receiver
-+ if (paramtypes.isEmpty())
-+ return methodNotFound;
-+ paramtypes.head = syms.objectType;
-+ }
+ MethodType mtype = new MethodType(paramtypes,
+ restype,
+ List.<Type>nil(),
+ syms.methodClass);
-+ int flags = PUBLIC | ABSTRACT | (isTransitionalStatic ? STATIC : 0);
++ int flags = PUBLIC | ABSTRACT;
+ Symbol m = null;
+ for (Scope.Entry e = implicit.lookup(name);
+ e.scope != null;
@@ -310,21 +305,21 @@ diff --git a/src/share/classes/com/sun/t
/** Load toplevel or member class with given fully qualified name and
* verify that it is accessible.
* @param env The current environment.
-@@ -1226,6 +1305,14 @@
- sym = findMethod(env, site, name, argtypes, typeargtypes, true,
- env.info.varArgs=true, false);
+@@ -1242,6 +1314,14 @@
+ methodResolutionCache.put(steps.head, sym);
+ steps = steps.tail;
}
+ if (sym.kind >= AMBIGUOUS &&
-+ invokedynamicString != null &&
++ allowInvokedynamic &&
+ (site == syms.dynamicType ||
+ 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) {
- sym = access(sym, pos, site, name, true, argtypes, typeargtypes);
- }
+ if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error
+ MethodResolutionPhase errPhase =
+ firstErroneousResolutionPhase();
diff --git a/src/share/classes/com/sun/tools/javac/jvm/ByteCodes.java b/src/share/classes/com/sun/tools/javac/jvm/ByteCodes.java
--- a/src/share/classes/com/sun/tools/javac/jvm/ByteCodes.java
+++ b/src/share/classes/com/sun/tools/javac/jvm/ByteCodes.java
@@ -340,7 +335,7 @@ diff --git a/src/share/classes/com/sun/t
diff --git a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
+++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
-@@ -474,6 +474,7 @@
+@@ -471,6 +471,7 @@
if (value instanceof MethodSymbol) {
MethodSymbol m = (MethodSymbol)value;
poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
@@ -351,28 +346,26 @@ diff --git a/src/share/classes/com/sun/t
diff --git a/src/share/classes/com/sun/tools/javac/jvm/Code.java b/src/share/classes/com/sun/tools/javac/jvm/Code.java
--- a/src/share/classes/com/sun/tools/javac/jvm/Code.java
+++ b/src/share/classes/com/sun/tools/javac/jvm/Code.java
-@@ -453,6 +453,21 @@
- if (!alive) return;
- emit2(meth);
- state.pop(argsize + 1);
-+ state.push(mtype.getReturnType());
-+ }
-+
+@@ -456,6 +456,19 @@
+ state.push(mtype.getReturnType());
+ }
+
+ /** Emit an invokedynamic instruction.
+ */
-+ public void emitInvokedynamic(int meth, Type mtype) {
-+ // N.B. this format is totally speculative
-+ // current plan of record is to introduce invokedynamic in a way that
-+ // does not break the verifier (via invokeinterface or invokestatic)
++ public void emitInvokedynamic(int desc, Type mtype) {
++ // N.B. this format is under consideration by the JSR 292 EG
+ int argsize = width(mtype.getParameterTypes());
+ emitop(invokedynamic);
+ if (!alive) return;
-+ emit2(meth);
++ emit2(desc);
+ emit2(0);
+ state.pop(argsize);
- state.push(mtype.getReturnType());
- }
-
++ state.push(mtype.getReturnType());
++ }
++
+ /** Emit an opcode with no operand field.
+ */
+ public void emitop0(int op) {
diff --git a/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/share/classes/com/sun/tools/javac/jvm/Gen.java
--- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java
+++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java
@@ -380,7 +373,7 @@ diff --git a/src/share/classes/com/sun/t
: options.get("-g:vars") != null;
genCrt = options.get("-Xjcov") != null;
debugCode = options.get("debugcode") != null;
-+ invokedynamicString = options.get("invokedynamic");
++ allowInvokedynamic = options.get("invokedynamic") != null;
generateIproxies =
target.requiresIproxy() ||
@@ -388,32 +381,17 @@ diff --git a/src/share/classes/com/sun/t
private final boolean varDebugInfo;
private final boolean genCrt;
private final boolean debugCode;
-+ private final String invokedynamicString;
++ private final boolean allowInvokedynamic;
/** Default limit of (approximate) size of finalizer to inline.
* Zero means always use jsr. 100 or greater means never use
-@@ -2140,6 +2142,24 @@
+@@ -2140,6 +2142,9 @@
}
result = items.
makeImmediateItem(sym.type, ((VarSymbol) sym).getConstValue());
-+ } else if (invokedynamicString != null && sym.kind == MTH && ssym == syms.dynamicType.tsym) {
-+ System.out.println("invokedynamic "+sym);//@@
++ } else if (allowInvokedynamic && sym.kind == MTH && ssym == syms.dynamicType.tsym) {
+ base.drop();
-+ if (invokedynamicString.equals("invokedynamic")) {
-+ // native form
-+ result = items.makeDynamicItem(sym);
-+ } else if (invokedynamicString.equals("invokestatic")) {
-+ // invokestatic transitional encoding
-+ result = items.makeStaticItem(sym);
-+ } else if (invokedynamicString.equals("invokeinterface")) {
-+ // invokeinterface transitional encoding
-+ Symbol sym1 = sym.clone(sym.owner);
-+ MethodType type1 = (MethodType) sym1.type.clone();
-+ type1.argtypes = type1.argtypes.tail; // drop receiver from type
-+ sym1.type = type1;
-+ result = items.makeMemberItem(sym1, false);
-+ } else
-+ assert false : invokedynamicString;
++ result = items.makeDynamicItem(sym);
} else {
if (!accessSuper)
sym = binaryQualifier(sym, tree.selected.type);
@@ -421,24 +399,23 @@ diff --git a/src/share/classes/com/sun/t
--- a/src/share/classes/com/sun/tools/javac/jvm/Items.java
+++ b/src/share/classes/com/sun/tools/javac/jvm/Items.java
@@ -139,6 +139,13 @@
- */
- Item makeStaticItem(Symbol member) {
return new StaticItem(member);
-+ }
-+
+ }
+
+ /** Make an item representing a dynamically invoked method.
+ * @param member The represented symbol.
+ */
+ Item makeDynamicItem(Symbol member) {
+ return new DynamicItem(member);
- }
-
++ }
++
/** Make an item representing an instance variable or method.
-@@ -460,6 +467,37 @@
- return "static(" + member + ")";
+ * @param member The represented symbol.
+ * @param nonvirtual Is the reference not virtual? (true for constructors
+@@ -457,6 +464,38 @@
}
}
-+
+
+ /** An item representing a dynamic call site.
+ */
+ class DynamicItem extends StaticItem {
@@ -460,7 +437,8 @@ diff --git a/src/share/classes/com/sun/t
+ // assert target.hasNativeInvokeDynamic();
+ MethodType mtype = (MethodType)member.erasure(types);
+ int rescode = Code.typecode(mtype.restype);
-+ code.emitInvokedynamic(pool.put(member), mtype);
++ ClassFile.NameAndType descr = new ClassFile.NameAndType(member.name, mtype);
++ code.emitInvokedynamic(pool.put(descr), mtype);
+ return stackItem[rescode];
+ }
+
@@ -469,37 +447,20 @@ diff --git a/src/share/classes/com/sun/t
+ }
+ }
+
-
++
/** An item representing an instance variable or method.
*/
+ class MemberItem extends Item {
diff --git a/src/share/classes/com/sun/tools/javac/jvm/Target.java b/src/share/classes/com/sun/tools/javac/jvm/Target.java
--- a/src/share/classes/com/sun/tools/javac/jvm/Target.java
+++ b/src/share/classes/com/sun/tools/javac/jvm/Target.java
-@@ -62,6 +62,11 @@
-
- /** JDK 6. */
- JDK1_6("1.6", 50, 0),
-+
-+ /** Support for the JSR292 prototype compiler (targeting 1.7 VMs
-+ * augmented with a few support classes). This is a transitional
-+ * option that will not be supported in the product. */
-+ JSR292("jsr292", 50, 0),
-
- /** JDK 7. */
- JDK1_7("1.7", 51, 0);
-@@ -253,6 +258,18 @@
+@@ -253,6 +253,12 @@
return compareTo(JDK1_5) >= 0;
}
-+ /** Does the VM support method handles and at least emulated invokedynamic?
++ /** Does the VM support an invokedynamic instruction?
+ */
-+ public boolean hasMethodHandles() {
-+ return compareTo(JSR292) >= 0;
-+ }
-+
-+ /** Does the VM support a native invokedynamic instruction?
-+ */
-+ public boolean hasNativeInvokeDynamic() {
++ public boolean hasInvokedynamic() {
+ return compareTo(JDK1_7) >= 0;
+ }
+
@@ -509,7 +470,7 @@ diff --git a/src/share/classes/com/sun/t
diff --git a/src/share/classes/com/sun/tools/javac/main/Main.java b/src/share/classes/com/sun/tools/javac/main/Main.java
--- a/src/share/classes/com/sun/tools/javac/main/Main.java
+++ b/src/share/classes/com/sun/tools/javac/main/Main.java
-@@ -267,13 +267,21 @@
+@@ -268,14 +268,19 @@
}
return null;
} else {
@@ -524,27 +485,17 @@ diff --git a/src/share/classes/com/sun/t
+ options.put("-target", target.name);
}
}
-+ }
-+ if (target.hasMethodHandles() && options.get("invokedynamic") == null) {
-+ if (target.hasNativeInvokeDynamic())
-+ options.put("invokedynamic", "invokedynamic");
-+ else
-+ options.put("invokedynamic", "invokestatic"); // transitional form
}
++ if (target.hasInvokedynamic()) {
++ options.put("invokedynamic", "invokedynamic");
++ }
return filenames.toList();
}
-diff --git a/src/share/classes/com/sun/tools/javac/parser/Parser.java b/src/share/classes/com/sun/tools/javac/parser/Parser.java
---- a/src/share/classes/com/sun/tools/javac/parser/Parser.java
-+++ b/src/share/classes/com/sun/tools/javac/parser/Parser.java
-@@ -331,6 +331,7 @@
- */
- JCExpression illegal(int pos) {
- setErrorEndPos(S.pos());
-+ Thread.dumpStack();//@@
- if ((mode & EXPR) != 0)
- return syntaxError(pos, "illegal.start.of.expr");
- else
-@@ -1067,7 +1068,13 @@
+ // where
+diff --git a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
+--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
++++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
+@@ -1027,7 +1027,13 @@
return illegal(pos);
}
} else {
@@ -559,54 +510,60 @@ diff --git a/src/share/classes/com/sun/t
}
break;
default:
-diff --git a/src/share/classes/com/sun/tools/javac/util/Name.java b/src/share/classes/com/sun/tools/javac/util/Name.java
---- a/src/share/classes/com/sun/tools/javac/util/Name.java
-+++ b/src/share/classes/com/sun/tools/javac/util/Name.java
-@@ -437,6 +437,8 @@
- java_lang_Cloneable = fromString("java.lang.Cloneable");
- java_io_Serializable = fromString("java.io.Serializable");
- java_lang_Enum = fromString("java.lang.Enum");
-+ java_dyn_MethodHandle = fromString("java.dyn.MethodHandle");
-+ java_dyn_Dynamic = fromString("java.dyn.Dynamic");
- package_info = fromString("package-info");
- serialVersionUID = fromString("serialVersionUID");
- ConstantValue = fromString("ConstantValue");
-@@ -478,6 +480,7 @@
- value = fromString("value");
- getMessage = fromString("getMessage");
- getClass = fromString("getClass");
-+ invoke = fromString("invoke");
-
- TYPE = fromString("TYPE");
- FIELD = fromString("FIELD");
-@@ -571,6 +574,8 @@
- public final Name java_io_Serializable;
- public final Name serialVersionUID;
- public final Name java_lang_Enum;
-+ public final Name java_dyn_MethodHandle;
-+ public final Name java_dyn_Dynamic;
- public final Name package_info;
- public final Name ConstantValue;
- public final Name LineNumberTable;
-@@ -612,6 +617,7 @@
- public final Name value;
- public final Name getMessage;
- public final Name getClass;
-+ public final Name invoke;
-
- public final Name TYPE;
- public final Name FIELD;
+diff --git a/src/share/classes/com/sun/tools/javac/util/Names.java b/src/share/classes/com/sun/tools/javac/util/Names.java
+--- a/src/share/classes/com/sun/tools/javac/util/Names.java
++++ b/src/share/classes/com/sun/tools/javac/util/Names.java
+@@ -73,6 +73,8 @@
+ public final Name java_io_Serializable;
+ public final Name serialVersionUID;
+ public final Name java_lang_Enum;
++ public final Name java_dyn_MethodHandle;
++ public final Name java_dyn_Dynamic;
+ public final Name package_info;
+ public final Name ConstantValue;
+ public final Name LineNumberTable;
+@@ -111,6 +113,7 @@
+ public final Name value;
+ public final Name getMessage;
+ public final Name getClass;
++ public final Name invoke;
+ public final Name TYPE;
+ public final Name FIELD;
+ public final Name METHOD;
+@@ -175,6 +178,8 @@
+ java_lang_Cloneable = fromString("java.lang.Cloneable");
+ java_io_Serializable = fromString("java.io.Serializable");
+ java_lang_Enum = fromString("java.lang.Enum");
++ java_dyn_MethodHandle = fromString("java.dyn.MethodHandle");
++ java_dyn_Dynamic = fromString("java.dyn.Dynamic");
+ package_info = fromString("package-info");
+ serialVersionUID = fromString("serialVersionUID");
+ ConstantValue = fromString("ConstantValue");
+@@ -216,6 +221,7 @@
+ value = fromString("value");
+ getMessage = fromString("getMessage");
+ getClass = fromString("getClass");
++ invoke = fromString("invoke");
+
+ TYPE = fromString("TYPE");
+ FIELD = fromString("FIELD");
diff --git a/src/share/classes/com/sun/tools/javap/CodeWriter.java b/src/share/classes/com/sun/tools/javap/CodeWriter.java
--- a/src/share/classes/com/sun/tools/javap/CodeWriter.java
+++ b/src/share/classes/com/sun/tools/javap/CodeWriter.java
-@@ -256,6 +256,7 @@
- return 3;
+@@ -263,6 +263,13 @@
+ printConstant(index);
+ return 5;
}
- case opc_invokeinterface:
+ case opc_invokedynamic:
++ {
++ int index = attr.getUnsignedShort(pc + 1);
++ print("\t#" + index + "; //");
++ printConstant(index);
++ return 5;
++ }
+ case opc_multianewarray:
{
int index = attr.getUnsignedShort(pc + 1);
- int nargs = attr.getUnsignedByte(pc + 3);
diff --git a/test/tools/javac/meth/InvokeDyn.java b/test/tools/javac/meth/InvokeDyn.java
new file mode 100644
--- /dev/null