Thu, 26 Mar 2015 11:34:50 +0100
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
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Tue Jan 13 10:25:24 2015 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Mar 26 11:34:50 2015 +0100 1.3 @@ -1883,7 +1883,7 @@ 1.4 * Translate a symbol of a given kind into something suitable for the 1.5 * synthetic lambda body 1.6 */ 1.7 - Symbol translate(Name name, final Symbol sym, LambdaSymbolKind skind) { 1.8 + Symbol translate(final Symbol sym, LambdaSymbolKind skind) { 1.9 Symbol ret; 1.10 switch (skind) { 1.11 case CAPTURED_THIS: 1.12 @@ -1891,7 +1891,7 @@ 1.13 break; 1.14 case TYPE_VAR: 1.15 // Just erase the type var 1.16 - ret = new VarSymbol(sym.flags(), name, 1.17 + ret = new VarSymbol(sym.flags(), sym.name, 1.18 types.erasure(sym.type), sym.owner); 1.19 1.20 /* this information should also be kept for LVT generation at Gen 1.21 @@ -1900,7 +1900,7 @@ 1.22 ((VarSymbol)ret).pos = ((VarSymbol)sym).pos; 1.23 break; 1.24 case CAPTURED_VAR: 1.25 - ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, name, types.erasure(sym.type), translatedSym) { 1.26 + ret = new VarSymbol(SYNTHETIC | FINAL | PARAMETER, sym.name, types.erasure(sym.type), translatedSym) { 1.27 @Override 1.28 public Symbol baseSymbol() { 1.29 //keep mapping with original captured symbol 1.30 @@ -1909,16 +1909,16 @@ 1.31 }; 1.32 break; 1.33 case LOCAL_VAR: 1.34 - ret = new VarSymbol(sym.flags() & FINAL, name, sym.type, translatedSym); 1.35 + ret = new VarSymbol(sym.flags() & FINAL, sym.name, sym.type, translatedSym); 1.36 ((VarSymbol) ret).pos = ((VarSymbol) sym).pos; 1.37 break; 1.38 case PARAM: 1.39 - ret = new VarSymbol((sym.flags() & FINAL) | PARAMETER, name, types.erasure(sym.type), translatedSym); 1.40 + ret = new VarSymbol((sym.flags() & FINAL) | PARAMETER, sym.name, types.erasure(sym.type), translatedSym); 1.41 ((VarSymbol) ret).pos = ((VarSymbol) sym).pos; 1.42 break; 1.43 default: 1.44 - ret = makeSyntheticVar(FINAL, name, types.erasure(sym.type), translatedSym); 1.45 - ((VarSymbol) ret).pos = ((VarSymbol) sym).pos; 1.46 + Assert.error(skind.name()); 1.47 + throw new AssertionError(); 1.48 } 1.49 if (ret != sym) { 1.50 ret.setDeclarationAttributes(sym.getRawAttributes()); 1.51 @@ -1929,27 +1929,8 @@ 1.52 1.53 void addSymbol(Symbol sym, LambdaSymbolKind skind) { 1.54 Map<Symbol, Symbol> transMap = getSymbolMap(skind); 1.55 - Name preferredName; 1.56 - switch (skind) { 1.57 - case CAPTURED_THIS: 1.58 - preferredName = names.fromString("encl$" + transMap.size()); 1.59 - break; 1.60 - case CAPTURED_VAR: 1.61 - preferredName = names.fromString("cap$" + transMap.size()); 1.62 - break; 1.63 - case LOCAL_VAR: 1.64 - preferredName = sym.name; 1.65 - break; 1.66 - case PARAM: 1.67 - preferredName = sym.name; 1.68 - break; 1.69 - case TYPE_VAR: 1.70 - preferredName = sym.name; 1.71 - break; 1.72 - default: throw new AssertionError(); 1.73 - } 1.74 if (!transMap.containsKey(sym)) { 1.75 - transMap.put(sym, translate(preferredName, sym, skind)); 1.76 + transMap.put(sym, translate(sym, skind)); 1.77 } 1.78 } 1.79
2.1 --- a/src/share/classes/com/sun/tools/javac/jvm/Code.java Tue Jan 13 10:25:24 2015 +0100 2.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/Code.java Thu Mar 26 11:34:50 2015 +0100 2.3 @@ -2172,7 +2172,11 @@ 2.4 boolean keepLocalVariables = varDebugInfo || 2.5 (var.sym.isExceptionParameter() && var.sym.hasTypeAnnotations()); 2.6 if (!keepLocalVariables) return; 2.7 - if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return; 2.8 + //don't keep synthetic vars, unless they are lambda method parameters 2.9 + boolean ignoredSyntheticVar = (var.sym.flags() & Flags.SYNTHETIC) != 0 && 2.10 + ((var.sym.owner.flags() & Flags.LAMBDA_METHOD) == 0 || 2.11 + (var.sym.flags() & Flags.PARAMETER) == 0); 2.12 + if (ignoredSyntheticVar) return; 2.13 if (varBuffer == null) 2.14 varBuffer = new LocalVar[20]; 2.15 else
3.1 --- a/test/tools/javac/MethodParameters/LambdaTest.out Tue Jan 13 10:25:24 2015 +0100 3.2 +++ b/test/tools/javac/MethodParameters/LambdaTest.out Thu Mar 26 11:34:50 2015 +0100 3.3 @@ -2,6 +2,6 @@ 3.4 LambdaTest.<init>() 3.5 LambdaTest.foo(i) 3.6 LambdaTest.lambda$static$1(x1/*synthetic*/)/*synthetic*/ 3.7 -LambdaTest.lambda$null$0(final cap$0/*synthetic*/, x2/*synthetic*/)/*synthetic*/ 3.8 +LambdaTest.lambda$null$0(final x1/*synthetic*/, x2/*synthetic*/)/*synthetic*/ 3.9 static interface LambdaTest$I -- inner 3.10 LambdaTest$I.m(x)
4.1 --- a/test/tools/javac/lambda/LocalVariableTable.java Tue Jan 13 10:25:24 2015 +0100 4.2 +++ b/test/tools/javac/lambda/LocalVariableTable.java Thu Mar 26 11:34:50 2015 +0100 4.3 @@ -23,7 +23,7 @@ 4.4 4.5 /* 4.6 * @test 4.7 - * @bug 8025998 8026749 4.8 + * @bug 8025998 8026749 8054220 8058227 4.9 * @summary Missing LV table in lambda bodies 4.10 * @compile -g LocalVariableTable.java 4.11 * @run main LocalVariableTable 4.12 @@ -183,7 +183,7 @@ 4.13 Run1 r = (a) -> { int x = a; }; 4.14 } 4.15 4.16 - @Expect({ "a", "x" }) 4.17 + @Expect({ "a", "x", "v" }) 4.18 static class Lambda_Args1_Local1_Captured1 { 4.19 void m() { 4.20 int v = 0; 4.21 @@ -191,7 +191,7 @@ 4.22 } 4.23 } 4.24 4.25 - @Expect({ "a1", "a2", "x1", "x2", "this" }) 4.26 + @Expect({ "a1", "a2", "x1", "x2", "this", "v1", "v2" }) 4.27 static class Lambda_Args2_Local2_Captured2_this { 4.28 int v; 4.29 void m() { 4.30 @@ -204,7 +204,7 @@ 4.31 } 4.32 } 4.33 4.34 - @Expect({ "e" }) 4.35 + @Expect({ "e", "c" }) 4.36 static class Lambda_Try_Catch { 4.37 private static Runnable asUncheckedRunnable(Closeable c) { 4.38 return () -> {