8054220: Debugger doesn't show variables *outside* lambda
8058227: Debugger has no access to outer variables inside Lambda
Summary: Put local variables captured by lambda into the lambda method's LocalVariableTable.
Reviewed-by: mcimadamore, rfield
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Mar 25 10:29:14 2015 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Mar 26 11:34:50 2015 +0100
@@ -1885,7 +1885,7 @@
* Translate a symbol of a given kind into something suitable for the
* synthetic lambda body
*/
- Symbol translate(Name name, final Symbol sym, LambdaSymbolKind skind) {
+ Symbol translate(final Symbol sym, LambdaSymbolKind skind) {
Symbol ret;
switch (skind) {
case CAPTURED_THIS:
@@ -1893,7 +1893,7 @@
break;
case TYPE_VAR:
// Just erase the type var
- ret = new VarSymbol(sym.flags(), name,
+ ret = new VarSymbol(sym.flags(), sym.name,
types.erasure(sym.type), sym.owner);
/* this information should also be kept for LVT generation at Gen
@@ -1902,7 +1902,7 @@
((VarSymbol)ret).pos = ((VarSymbol)sym).pos;
break;
case CAPTURED_VAR:
- ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, name, types.erasure(sym.type), translatedSym) {
+ ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, sym.name, types.erasure(sym.type), translatedSym) {
@Override
public Symbol baseSymbol() {
//keep mapping with original captured symbol
@@ -1911,16 +1911,16 @@
};
break;
case LOCAL_VAR:
- ret = new VarSymbol(sym.flags() & FINAL, name, sym.type, translatedSym);
+ ret = new VarSymbol(sym.flags() & FINAL, sym.name, sym.type, translatedSym);
((VarSymbol) ret).pos = ((VarSymbol) sym).pos;
break;
case PARAM:
- ret = new VarSymbol((sym.flags() & FINAL) | PARAMETER, name, types.erasure(sym.type), translatedSym);
+ ret = new VarSymbol((sym.flags() & FINAL) | PARAMETER, sym.name, types.erasure(sym.type), translatedSym);
((VarSymbol) ret).pos = ((VarSymbol) sym).pos;
break;
default:
- ret = makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym);
- ((VarSymbol) ret).pos = ((VarSymbol) sym).pos;
+ Assert.error(skind.name());
+ throw new AssertionError();
}
if (ret != sym) {
ret.setDeclarationAttributes(sym.getRawAttributes());
@@ -1931,27 +1931,8 @@
void addSymbol(Symbol sym, LambdaSymbolKind skind) {
Map<Symbol, Symbol> transMap = getSymbolMap(skind);
- Name preferredName;
- switch (skind) {
- case CAPTURED_THIS:
- preferredName = names.fromString("encl$" + transMap.size());
- break;
- case CAPTURED_VAR:
- preferredName = names.fromString("cap$" + transMap.size());
- break;
- case LOCAL_VAR:
- preferredName = sym.name;
- break;
- case PARAM:
- preferredName = sym.name;
- break;
- case TYPE_VAR:
- preferredName = sym.name;
- break;
- default: throw new AssertionError();
- }
if (!transMap.containsKey(sym)) {
- transMap.put(sym, translate(preferredName, sym, skind));
+ transMap.put(sym, translate(sym, skind));
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java Wed Mar 25 10:29:14 2015 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java Thu Mar 26 11:34:50 2015 +0100
@@ -2166,7 +2166,11 @@
boolean keepLocalVariables = varDebugInfo ||
(var.sym.isExceptionParameter() && var.sym.hasTypeAnnotations());
if (!keepLocalVariables) return;
- if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
+ //don't keep synthetic vars, unless they are lambda method parameters
+ boolean ignoredSyntheticVar = (var.sym.flags() & Flags.SYNTHETIC) != 0 &&
+ ((var.sym.owner.flags() & Flags.LAMBDA_METHOD) == 0 ||
+ (var.sym.flags() & Flags.PARAMETER) == 0);
+ if (ignoredSyntheticVar) return;
if (varBuffer == null)
varBuffer = new LocalVar[20];
else
--- a/langtools/test/tools/javac/MethodParameters/LambdaTest.out Wed Mar 25 10:29:14 2015 +0300
+++ b/langtools/test/tools/javac/MethodParameters/LambdaTest.out Thu Mar 26 11:34:50 2015 +0100
@@ -2,6 +2,6 @@
LambdaTest.<init>()
LambdaTest.foo(i)
LambdaTest.lambda$static$1(x1/*synthetic*/)/*synthetic*/
-LambdaTest.lambda$null$0(final cap$0/*synthetic*/, x2/*synthetic*/)/*synthetic*/
+LambdaTest.lambda$null$0(final x1/*synthetic*/, x2/*synthetic*/)/*synthetic*/
static interface LambdaTest$I -- inner
LambdaTest$I.m(x)
--- a/langtools/test/tools/javac/lambda/LocalVariableTable.java Wed Mar 25 10:29:14 2015 +0300
+++ b/langtools/test/tools/javac/lambda/LocalVariableTable.java Thu Mar 26 11:34:50 2015 +0100
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8025998 8026749
+ * @bug 8025998 8026749 8054220 8058227
* @summary Missing LV table in lambda bodies
* @compile -g LocalVariableTable.java
* @run main LocalVariableTable
@@ -183,7 +183,7 @@
Run1 r = (a) -> { int x = a; };
}
- @Expect({ "a", "x" })
+ @Expect({ "a", "x", "v" })
static class Lambda_Args1_Local1_Captured1 {
void m() {
int v = 0;
@@ -191,7 +191,7 @@
}
}
- @Expect({ "a1", "a2", "x1", "x2", "this" })
+ @Expect({ "a1", "a2", "x1", "x2", "this", "v1", "v2" })
static class Lambda_Args2_Local2_Captured2_this {
int v;
void m() {
@@ -204,7 +204,7 @@
}
}
- @Expect({ "e" })
+ @Expect({ "e", "c" })
static class Lambda_Try_Catch {
private static Runnable asUncheckedRunnable(Closeable c) {
return () -> {