From alex.buckley at oracle.com Wed Nov 2 21:28:35 2016 From: alex.buckley at oracle.com (Alex Buckley) Date: Wed, 02 Nov 2016 14:28:35 -0700 Subject: spec clarification: wildcard array element signature In-Reply-To: References: Message-ID: <581A5A83.9020907@oracle.com> On 10/22/2016 8:15 PM, Liam Miller-Cushon wrote: > When javac compiles the following program, it writes field i's signature > as "LA<[*>.I;". > > I don't think the grammar in JVMS 4.7.9.1 allows for the element type of > an array to be a wildcard. Is that a spec bug? > > class A { class I {} } > class Test { > class B extends A {} > B.I i; > } Liam, are you calling Field.getGenericType() on i and getting a surprising result, perhaps a ParameterizedType whose getActualTypeArguments() blows up? Alex From cushon at google.com Thu Nov 3 00:29:59 2016 From: cushon at google.com (Liam Miller-Cushon) Date: Wed, 2 Nov 2016 17:29:59 -0700 Subject: spec clarification: wildcard array element signature In-Reply-To: <581A5A83.9020907@oracle.com> References: <581A5A83.9020907@oracle.com> Message-ID: On Wed, Nov 2, 2016 at 2:28 PM, Alex Buckley wrote: > Liam, are you calling Field.getGenericType() on i and getting a surprising > result, perhaps a ParameterizedType whose getActualTypeArguments() blows up? I noticed this because it crashes ASM [1], not because of an issue with reflection. But accessing it reflectively as you describe does blow up: ((ParameterizedType) Test.class.getField("i").getGenericType()).getActualTypeArguments() ... GenericSignatureFormatError: Signature Parse error: Expected Field Type Signature Remaining input: *>.I; at sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:124) at sun.reflect.generics.parser.SignatureParser.parseFieldTypeSignature(SignatureParser.java:297) If you're interested in pursuing the first option Maurizio described, I'd be happy to help assess the compatibility impact on our code. [1] http://forge.ow2.org/tracker/?func=detail&aid=317776&group_id=23&atid=100023 -------------- next part -------------- An HTML attachment was scrubbed... URL: From bsrbnd at gmail.com Thu Nov 3 12:28:13 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Thu, 3 Nov 2016 13:28:13 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> Message-ID: Here is a short summary of this issue. 1) The problem related to issue 8143388 changeset (which is probably a new issue) discovered here: http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010452.html is solved by the fix proposed here: http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010487.html 2) The optimization expected in issue 8147527 is obtained with the following patch: http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010448.html 3) I've added two additional checks (for the optimization) that verify if this$n: a) is synthetic b) matches the exact regex "this\$\d+" (instead of startsWith("this$")). The following example (derived from issue 8147527 with some additional cases) shows the result of the optimization: class Issue8147527 extends p.P { public static void main(String[] args) { Issue8147527 self = new Issue8147527(); self.testAll(); } private void testAll() { System.out.println(test()); System.out.println(i); Inner in = new Inner(); System.out.println(in.test()); System.out.println(i); System.out.println(testParent()); System.out.println(super.j); System.out.println(in.testParent()); System.out.println(super.j); } Integer i=0; private Integer test() { i++; return this.i++; } private Integer testParent() { j++; return super.j++; } class Inner { private Integer test() { i++; return Issue8147527.this.i++; } private Integer testParent() { j++; return Issue8147527.super.j++; } } } package p; public class P { protected Integer j=20; } The desugared code looks like this (as expected in issue 8147527): class Issue8147527$Inner { private Integer test() { (let /*synthetic*/ final Integer $647942 = this$0.i in (let /*synthetic*/ final Integer $29472086 = this$0.i = Integer.valueOf((int)(this$0.i.intValue() + 1)) in $647942)); return (let /*synthetic*/ final Integer $8278885 = (Integer)this$0.i in (let /*synthetic*/ final Integer $16578475 = this$0.i = Integer.valueOf((int)(this$0.i.intValue() + 1)) in $8278885)); } private Integer testParent() { (let /*synthetic*/ final Integer $798605 = Issue8147527.access$200(this$0) in (let /*synthetic*/ final Integer $5995540 = Issue8147527.access$302(this$0, Integer.valueOf((int)(Issue8147527.access$400(this$0).intValue() + 1))) in $798605)); return (let /*synthetic*/ final Integer $33017129 = (Integer)Issue8147527.access$501(this$0) in (let /*synthetic*/ final Integer $25625839 = Issue8147527.access$603(this$0, Integer.valueOf((int)(Issue8147527.access$701(this$0).intValue() + 1))) in $33017129)); } } class Issue8147527 extends p.P { private Integer test() { (let /*synthetic*/ final Integer $21617 = i in (let /*synthetic*/ final Integer $20066205 = i = Integer.valueOf((int)(i.intValue() + 1)) in $21617)); return (let /*synthetic*/ final Integer $32619253 = (Integer)this.i in (let /*synthetic*/ final Integer $27442939 = this.i = Integer.valueOf((int)(this.i.intValue() + 1)) in $32619253)); } private Integer testParent() { (let /*synthetic*/ final Integer $4208220 = j in (let /*synthetic*/ final Integer $32359562 = j = Integer.valueOf((int)(j.intValue() + 1)) in $4208220)); return (let /*synthetic*/ final Integer $20049680 = (Integer)super.j in (let /*synthetic*/ final Integer $28368043 = super.j = Integer.valueOf((int)(super.j.intValue() + 1)) in $20049680)); } } Putting all (1, 2 and 3) together gives the patch below. Bernard diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -926,7 +926,7 @@ ClassSymbol accOwner = refSuper && protAccess // For access via qualified super (T.super.x), place the // access symbol on T. - ? (ClassSymbol)((JCFieldAccess) tree).selected.type.tsym + ? (ClassSymbol)((JCFieldAccess)((JCFieldAccess) tree).selected).selected.type.tsym // Otherwise pretend that the owner of an accessed // protected symbol is the enclosing class of the current // class which is a subclass of the symbol's owner. @@ -1100,6 +1100,7 @@ tree = make.at(tree.pos).Ident(sym); } JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null; + base = refSuper ? translate(base) : base; switch (sym.kind) { case TYP: if (sym.owner.kind != PCK) { @@ -2209,16 +2210,20 @@ */ JCExpression abstractRval(JCExpression rval, Type type, TreeBuilder builder) { rval = TreeInfo.skipParens(rval); + boolean synthetic = false; switch (rval.getTag()) { case LITERAL: return builder.build(rval); case IDENT: JCIdent id = (JCIdent) rval; + synthetic = (id.sym.flags() & SYNTHETIC) != 0; if ((id.sym.flags() & FINAL) != 0 && id.sym.owner.kind == MTH) return builder.build(rval); } Name name = TreeInfo.name(rval); - if (name == names._super) + String thisDollarN = names._this + "\\" + target.syntheticNameChar() + "\\d+"; + boolean matchesThisDollar = synthetic && name != null && name.toString().matches(thisDollarN); + if (name == names._super || name == names._this || matchesThisDollar) return builder.build(rval); VarSymbol var = new VarSymbol(FINAL|SYNTHETIC, @@ -3837,7 +3842,7 @@ tree.selected.hasTag(SELECT) && TreeInfo.name(tree.selected) == names._super && !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass); - tree.selected = translate(tree.selected); + if (!qualifiedSuperAccess) tree.selected = translate(tree.selected); if (tree.name == names._class) { result = classOf(tree.selected); } From jan.lahoda at oracle.com Thu Nov 3 13:45:57 2016 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Thu, 3 Nov 2016 14:45:57 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> Message-ID: <581B3F95.7060505@oracle.com> Hi Bernard, Thanks for looking at this. For the avoidance of the modification of tree.selected in Lower.visitSelect, what I meant was more that we would create a new instance of JCFieldAccess, to carry the new select. Might be easier that trying to work with the existing select. I think it might be useful to have a set of tests covering the usecases, so that we can more easily test patches (we will need tests eventually anyway). I can look at that, unless you want to. On 3.11.2016 13:28, bsrbnd wrote: > Here is a short summary of this issue. > > 1) The problem related to issue 8143388 changeset (which is probably a > new issue) discovered here: > http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010452.html > > is solved by the fix proposed here: > http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010487.html > > 2) The optimization expected in issue 8147527 is obtained with the > following patch: > http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010448.html > > 3) I've added two additional checks (for the optimization) that verify > if this$n: > a) is synthetic > b) matches the exact regex "this\$\d+" (instead of startsWith("this$")). Offhand, this seems a little bit scary. Jan > > The following example (derived from issue 8147527 with some additional > cases) shows the result of the optimization: > > class Issue8147527 extends p.P { > public static void main(String[] args) { > Issue8147527 self = new Issue8147527(); > self.testAll(); > } > > private void testAll() { > System.out.println(test()); > System.out.println(i); > > Inner in = new Inner(); > System.out.println(in.test()); > System.out.println(i); > > System.out.println(testParent()); > System.out.println(super.j); > > System.out.println(in.testParent()); > System.out.println(super.j); > } > > Integer i=0; > private Integer test() { > i++; > return this.i++; > } > private Integer testParent() { > j++; > return super.j++; > } > > class Inner { > private Integer test() { > i++; > return Issue8147527.this.i++; > } > private Integer testParent() { > j++; > return Issue8147527.super.j++; > } > } > } > > package p; > > public class P { > protected Integer j=20; > } > > The desugared code looks like this (as expected in issue 8147527): > > class Issue8147527$Inner { > > private Integer test() { > (let /*synthetic*/ final Integer $647942 = this$0.i in (let > /*synthetic*/ final Integer $29472086 = this$0.i = > Integer.valueOf((int)(this$0.i.intValue() + 1)) in $647942)); > return (let /*synthetic*/ final Integer $8278885 = > (Integer)this$0.i in (let /*synthetic*/ final Integer $16578475 = > this$0.i = Integer.valueOf((int)(this$0.i.intValue() + 1)) in > $8278885)); > } > > private Integer testParent() { > (let /*synthetic*/ final Integer $798605 = > Issue8147527.access$200(this$0) in (let /*synthetic*/ final Integer > $5995540 = Issue8147527.access$302(this$0, > Integer.valueOf((int)(Issue8147527.access$400(this$0).intValue() + > 1))) in $798605)); > return (let /*synthetic*/ final Integer $33017129 = > (Integer)Issue8147527.access$501(this$0) in (let /*synthetic*/ final > Integer $25625839 = Issue8147527.access$603(this$0, > Integer.valueOf((int)(Issue8147527.access$701(this$0).intValue() + > 1))) in $33017129)); > } > } > > class Issue8147527 extends p.P { > > private Integer test() { > (let /*synthetic*/ final Integer $21617 = i in (let > /*synthetic*/ final Integer $20066205 = i = > Integer.valueOf((int)(i.intValue() + 1)) in $21617)); > return (let /*synthetic*/ final Integer $32619253 = > (Integer)this.i in (let /*synthetic*/ final Integer $27442939 = this.i > = Integer.valueOf((int)(this.i.intValue() + 1)) in $32619253)); > } > > private Integer testParent() { > (let /*synthetic*/ final Integer $4208220 = j in (let > /*synthetic*/ final Integer $32359562 = j = > Integer.valueOf((int)(j.intValue() + 1)) in $4208220)); > return (let /*synthetic*/ final Integer $20049680 = > (Integer)super.j in (let /*synthetic*/ final Integer $28368043 = > super.j = Integer.valueOf((int)(super.j.intValue() + 1)) in > $20049680)); > } > } > > Putting all (1, 2 and 3) together gives the patch below. > > Bernard > > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > @@ -926,7 +926,7 @@ > ClassSymbol accOwner = refSuper && protAccess > // For access via qualified super (T.super.x), place the > // access symbol on T. > - ? (ClassSymbol)((JCFieldAccess) tree).selected.type.tsym > + ? (ClassSymbol)((JCFieldAccess)((JCFieldAccess) > tree).selected).selected.type.tsym > // Otherwise pretend that the owner of an accessed > // protected symbol is the enclosing class of the current > // class which is a subclass of the symbol's owner. > @@ -1100,6 +1100,7 @@ > tree = make.at(tree.pos).Ident(sym); > } > JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) > tree).selected : null; > + base = refSuper ? translate(base) : base; > switch (sym.kind) { > case TYP: > if (sym.owner.kind != PCK) { > @@ -2209,16 +2210,20 @@ > */ > JCExpression abstractRval(JCExpression rval, Type type, > TreeBuilder builder) { > rval = TreeInfo.skipParens(rval); > + boolean synthetic = false; > switch (rval.getTag()) { > case LITERAL: > return builder.build(rval); > case IDENT: > JCIdent id = (JCIdent) rval; > + synthetic = (id.sym.flags() & SYNTHETIC) != 0; > if ((id.sym.flags() & FINAL) != 0 && id.sym.owner.kind == MTH) > return builder.build(rval); > } > Name name = TreeInfo.name(rval); > - if (name == names._super) > + String thisDollarN = names._this + "\\" + > target.syntheticNameChar() + "\\d+"; > + boolean matchesThisDollar = synthetic && name != null && > name.toString().matches(thisDollarN); > + if (name == names._super || name == names._this || matchesThisDollar) > return builder.build(rval); > VarSymbol var = > new VarSymbol(FINAL|SYNTHETIC, > @@ -3837,7 +3842,7 @@ > tree.selected.hasTag(SELECT) && > TreeInfo.name(tree.selected) == names._super && > !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, > currentClass); > - tree.selected = translate(tree.selected); > + if (!qualifiedSuperAccess) tree.selected = translate(tree.selected); > if (tree.name == names._class) { > result = classOf(tree.selected); > } > From cushon at google.com Thu Nov 3 22:26:25 2016 From: cushon at google.com (Liam Miller-Cushon) Date: Thu, 3 Nov 2016 15:26:25 -0700 Subject: handling invalid ConstantValue attributes Message-ID: javac silently accepts class files containing ConstantValue attributes of the incorrect type, or outside of the allowed ranges for int, short, char, byte, and booleans. I expected javac to either reject the invalid bytecode, or convert the constants to their canonical representation (e.g. constant booleans should always be 0 or 1). ecj rejects constants with the wrong type, and normalizes values outside of the expected range. I couldn't find anything in the spec for this, is it up to the implementation? Would it be possible to change javac's behaviour here? === Dump.java import java.nio.file.Files; import java.nio.file.Paths; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Opcodes; public class Dump { public static void main(String[] args) throws Exception { Files.write(Paths.get("Lib.class"), dump()); } static byte[] dump() { ClassWriter cw = new ClassWriter(0); cw.visit(52, Opcodes.ACC_SUPER, "Lib", null, "java/lang/Object", null); cw.visitField( Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, "A", "Z", null, "hello"); cw.visitField( Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, "B", "Z", null, 2); cw.visitEnd(); return cw.toByteArray(); } } === === Test.java class Test { static final boolean ONE = Lib.A; static final boolean TWO = Lib.B; } === === Test2.java class Test2 { static final boolean ONE = Lib.A || true; } === $ javac -cp asm-debug-all-5.1.jar Dump.java $ java -cp asm-debug-all-5.1.jar:. Dump $ javac Test.java $ javap -v Test ... static final boolean ONE; descriptor: Z flags: ACC_STATIC, ACC_FINAL ConstantValue: String hello static final boolean TWO; descriptor: Z flags: ACC_STATIC, ACC_FINAL ConstantValue: int 2 $ javac Test2.java ... java.lang.AssertionError: java.lang.ClassCastException: java.lang.String (in module: java.base) cannot be cast to java.lang.Number (in module: java.base) at com.sun.tools.javac.code.Symbol$VarSymbol.getConstValue(jdk.compiler at 9-ea /Symbol.java:1530) at com.sun.tools.javac.comp.Attr.visitVarDef(jdk.compiler at 9-ea /Attr.java:1122) ... Caused by: java.lang.ClassCastException: java.lang.String (in module: java.base) cannot be cast to java.lang.Number (in module: java.base) at com.sun.tools.javac.comp.ConstFold.intValue(jdk.compiler at 9-ea /ConstFold.java:71) at com.sun.tools.javac.comp.ConstFold.fold2(jdk.compiler at 9-ea /ConstFold.java:187) at com.sun.tools.javac.comp.Attr.visitBinary(jdk.compiler at 9-ea /Attr.java:3211) -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Thu Nov 3 22:35:22 2016 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Thu, 03 Nov 2016 15:35:22 -0700 Subject: handling invalid ConstantValue attributes In-Reply-To: References: Message-ID: <581BBBAA.4080908@oracle.com> Well, javac should never give a stacktrace, so any time that it does is worthy of a bug report. -- Jon On 11/03/2016 03:26 PM, Liam Miller-Cushon wrote: > javac silently accepts class files containing ConstantValue attributes > of the incorrect > type, or outside of the allowed ranges for int, short, char, byte, and > booleans. > > I expected javac to either reject the invalid bytecode, or convert the > constants to > their canonical representation (e.g. constant booleans should always > be 0 or 1). > > ecj rejects constants with the wrong type, and normalizes values > outside of the > expected range. > > I couldn't find anything in the spec for this, is it up to the > implementation? Would it > be possible to change javac's behaviour here? > > === Dump.java > import java.nio.file.Files; > import java.nio.file.Paths; > import org.objectweb.asm.ClassWriter; > import org.objectweb.asm.Opcodes; > > public class Dump { > > public static void main(String[] args) throws Exception { > Files.write(Paths.get("Lib.class"), dump()); > } > > static byte[] dump() { > ClassWriter cw = new ClassWriter(0); > cw.visit(52, Opcodes.ACC_SUPER, "Lib", null, "java/lang/Object", > null); > cw.visitField( > Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, > "A", "Z", null, "hello"); > cw.visitField( > Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, > "B", "Z", null, 2); > cw.visitEnd(); > return cw.toByteArray(); > } > } > === > > === Test.java > class Test { > static final boolean ONE = Lib.A; > static final boolean TWO = Lib.B; > } > === > > === Test2.java > class Test2 { > static final boolean ONE = Lib.A || true; > } > === > > > $ javac -cp asm-debug-all-5.1.jar Dump.java > $ java -cp asm-debug-all-5.1.jar:. Dump > $ javac Test.java > $ javap -v Test > ... > static final boolean ONE; > descriptor: Z > flags: ACC_STATIC, ACC_FINAL > ConstantValue: String hello > > static final boolean TWO; > descriptor: Z > flags: ACC_STATIC, ACC_FINAL > ConstantValue: int 2 > > $ javac Test2.java > ... > java.lang.AssertionError: java.lang.ClassCastException: > java.lang.String (in module: java.base) cannot be cast to > java.lang.Number (in module: java.base) > at > com.sun.tools.javac.code.Symbol$VarSymbol.getConstValue(jdk.compiler at 9-ea/Symbol.java:1530) > at > com.sun.tools.javac.comp.Attr.visitVarDef(jdk.compiler at 9-ea/Attr.java:1122) > ... > Caused by: java.lang.ClassCastException: java.lang.String (in module: > java.base) cannot be cast to java.lang.Number (in module: java.base) > at > com.sun.tools.javac.comp.ConstFold.intValue(jdk.compiler at 9-ea/ConstFold.java:71) > at > com.sun.tools.javac.comp.ConstFold.fold2(jdk.compiler at 9-ea/ConstFold.java:187) > at > com.sun.tools.javac.comp.Attr.visitBinary(jdk.compiler at 9-ea/Attr.java:3211) -------------- next part -------------- An HTML attachment was scrubbed... URL: From alex.buckley at oracle.com Thu Nov 3 22:52:48 2016 From: alex.buckley at oracle.com (Alex Buckley) Date: Thu, 03 Nov 2016 15:52:48 -0700 Subject: handling invalid ConstantValue attributes In-Reply-To: References: Message-ID: <581BBFC0.1050407@oracle.com> In Lib.class, the field A contains a ConstantValue attribute that is ill-formed, since the attribute points to a CONSTANT_String c.p. entry that is not appropriate for a Z-typed field (per JVMS8 4.7.2). A class file reader such as javac must reject Lib.class on this basis. In Lib.class, the field B contains a ConstantValue attribute that is not ill-formed, since the attribute points to a CONSTANT_Integer c.p. entry that is appropriate for a Z-typed field. A class file reader such as javac must not reject Lib.class on this basis. However, javac should handle an out-of-band value in the CONSTANT_Integer c.p. entry as a quality-of-implementation detail. Alex On 11/3/2016 3:26 PM, Liam Miller-Cushon wrote: > javac silently accepts class files containing ConstantValue attributes > of the incorrect > type, or outside of the allowed ranges for int, short, char, byte, and > booleans. > > I expected javac to either reject the invalid bytecode, or convert the > constants to > their canonical representation (e.g. constant booleans should always be > 0 or 1). > > ecj rejects constants with the wrong type, and normalizes values outside > of the > expected range. > > I couldn't find anything in the spec for this, is it up to the > implementation? Would it > be possible to change javac's behaviour here? > > === Dump.java > import java.nio.file.Files; > import java.nio.file.Paths; > import org.objectweb.asm.ClassWriter; > import org.objectweb.asm.Opcodes; > > public class Dump { > > public static void main(String[] args) throws Exception { > Files.write(Paths.get("Lib.class"), dump()); > } > > static byte[] dump() { > ClassWriter cw = new ClassWriter(0); > cw.visit(52, Opcodes.ACC_SUPER, "Lib", null, "java/lang/Object", null); > cw.visitField( > Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, > "A", "Z", null, "hello"); > cw.visitField( > Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, > "B", "Z", null, 2); > cw.visitEnd(); > return cw.toByteArray(); > } > } > === > > === Test.java > class Test { > static final boolean ONE = Lib.A; > static final boolean TWO = Lib.B; > } > === > > === Test2.java > class Test2 { > static final boolean ONE = Lib.A || true; > } > === > > > $ javac -cp asm-debug-all-5.1.jar Dump.java > $ java -cp asm-debug-all-5.1.jar:. Dump > $ javac Test.java > $ javap -v Test > ... > static final boolean ONE; > descriptor: Z > flags: ACC_STATIC, ACC_FINAL > ConstantValue: String hello > > static final boolean TWO; > descriptor: Z > flags: ACC_STATIC, ACC_FINAL > ConstantValue: int 2 > > $ javac Test2.java > ... > java.lang.AssertionError: java.lang.ClassCastException: java.lang.String > (in module: java.base) cannot be cast to java.lang.Number (in module: > java.base) > at > com.sun.tools.javac.code.Symbol$VarSymbol.getConstValue(jdk.compiler at 9-ea/Symbol.java:1530) > at > com.sun.tools.javac.comp.Attr.visitVarDef(jdk.compiler at 9-ea/Attr.java:1122) > ... > Caused by: java.lang.ClassCastException: java.lang.String (in module: > java.base) cannot be cast to java.lang.Number (in module: java.base) > at > com.sun.tools.javac.comp.ConstFold.intValue(jdk.compiler at 9-ea/ConstFold.java:71) > at > com.sun.tools.javac.comp.ConstFold.fold2(jdk.compiler at 9-ea/ConstFold.java:187) > at > com.sun.tools.javac.comp.Attr.visitBinary(jdk.compiler at 9-ea/Attr.java:3211) From alex.buckley at oracle.com Thu Nov 3 23:24:53 2016 From: alex.buckley at oracle.com (Alex Buckley) Date: Thu, 03 Nov 2016 16:24:53 -0700 Subject: spec clarification: wildcard array element signature In-Reply-To: <5474bf92-130f-36aa-8435-03e392be4f0c@oracle.com> References: <580E52CC.4030408@oracle.com> <5474bf92-130f-36aa-8435-03e392be4f0c@oracle.com> Message-ID: <581BC745.5050803@oracle.com> On 10/24/2016 2:35 PM, Maurizio Cimadamore wrote: > On 24/10/16 19:28, Alex Buckley wrote: > Regarding the other issue about wildcards being replaced in supertypes, > I think there are two options - none of which is particularly appealing: > > 1. fix javac (and other compilers) so that the signature attribute only > speaks about types in the source code, w/o attempting to do any > membership computation - this should ensure that non-denotable types > should not crop up in the process - unfortunately, doing so will change > the signature attribute of real code out there - and the compatibility > impact potentially large (the difference will be visible in core > reflection). The Signature attribute, in particular a class type signature (JVMS8 4.7.9.1), is defined in terms of binary names, as alluded to by your comment about Field.getGenericType aligning with Field.getType. Therefore, Signature must be able to encode A.I (so to speak) rather than the B.I type literally found in source code. That means rejecting option 1, and choosing option 2: > 2. keep javac as is - live with 'weird' signatures and plug resulting > soundness issues (esp. around separate compilation) ? Which means a change to the JVMS TypeArgument production, and corresponding enhancement to ParameterizedType.getActualTypeArguments() [thanks Liam]. Dan, any objection to this? Alex From jonathan.gibbons at oracle.com Thu Nov 3 23:46:05 2016 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Thu, 03 Nov 2016 16:46:05 -0700 Subject: handling invalid ConstantValue attributes In-Reply-To: <581BBFC0.1050407@oracle.com> References: <581BBFC0.1050407@oracle.com> Message-ID: <581BCC3D.4050608@oracle.com> A corresponding RFE/enhancement to javap would be to report any such issues. It is already somewhat fault tolerant, and will print "???" or similar as needed, but more cross-referencing and checking could be done. -- Jon On 11/03/2016 03:52 PM, Alex Buckley wrote: > In Lib.class, the field A contains a ConstantValue attribute that is > ill-formed, since the attribute points to a CONSTANT_String c.p. entry > that is not appropriate for a Z-typed field (per JVMS8 4.7.2). A class > file reader such as javac must reject Lib.class on this basis. > > In Lib.class, the field B contains a ConstantValue attribute that is > not ill-formed, since the attribute points to a CONSTANT_Integer c.p. > entry that is appropriate for a Z-typed field. A class file reader > such as javac must not reject Lib.class on this basis. However, javac > should handle an out-of-band value in the CONSTANT_Integer c.p. entry > as a quality-of-implementation detail. > > Alex > > On 11/3/2016 3:26 PM, Liam Miller-Cushon wrote: >> javac silently accepts class files containing ConstantValue attributes >> of the incorrect >> type, or outside of the allowed ranges for int, short, char, byte, and >> booleans. >> >> I expected javac to either reject the invalid bytecode, or convert the >> constants to >> their canonical representation (e.g. constant booleans should always be >> 0 or 1). >> >> ecj rejects constants with the wrong type, and normalizes values outside >> of the >> expected range. >> >> I couldn't find anything in the spec for this, is it up to the >> implementation? Would it >> be possible to change javac's behaviour here? >> >> === Dump.java >> import java.nio.file.Files; >> import java.nio.file.Paths; >> import org.objectweb.asm.ClassWriter; >> import org.objectweb.asm.Opcodes; >> >> public class Dump { >> >> public static void main(String[] args) throws Exception { >> Files.write(Paths.get("Lib.class"), dump()); >> } >> >> static byte[] dump() { >> ClassWriter cw = new ClassWriter(0); >> cw.visit(52, Opcodes.ACC_SUPER, "Lib", null, "java/lang/Object", >> null); >> cw.visitField( >> Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, >> "A", "Z", null, "hello"); >> cw.visitField( >> Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, >> "B", "Z", null, 2); >> cw.visitEnd(); >> return cw.toByteArray(); >> } >> } >> === >> >> === Test.java >> class Test { >> static final boolean ONE = Lib.A; >> static final boolean TWO = Lib.B; >> } >> === >> >> === Test2.java >> class Test2 { >> static final boolean ONE = Lib.A || true; >> } >> === >> >> >> $ javac -cp asm-debug-all-5.1.jar Dump.java >> $ java -cp asm-debug-all-5.1.jar:. Dump >> $ javac Test.java >> $ javap -v Test >> ... >> static final boolean ONE; >> descriptor: Z >> flags: ACC_STATIC, ACC_FINAL >> ConstantValue: String hello >> >> static final boolean TWO; >> descriptor: Z >> flags: ACC_STATIC, ACC_FINAL >> ConstantValue: int 2 >> >> $ javac Test2.java >> ... >> java.lang.AssertionError: java.lang.ClassCastException: java.lang.String >> (in module: java.base) cannot be cast to java.lang.Number (in module: >> java.base) >> at >> com.sun.tools.javac.code.Symbol$VarSymbol.getConstValue(jdk.compiler at 9-ea/Symbol.java:1530) >> >> at >> com.sun.tools.javac.comp.Attr.visitVarDef(jdk.compiler at 9-ea/Attr.java:1122) >> >> ... >> Caused by: java.lang.ClassCastException: java.lang.String (in module: >> java.base) cannot be cast to java.lang.Number (in module: java.base) >> at >> com.sun.tools.javac.comp.ConstFold.intValue(jdk.compiler at 9-ea/ConstFold.java:71) >> >> at >> com.sun.tools.javac.comp.ConstFold.fold2(jdk.compiler at 9-ea/ConstFold.java:187) >> >> at >> com.sun.tools.javac.comp.Attr.visitBinary(jdk.compiler at 9-ea/Attr.java:3211) >> From cushon at google.com Fri Nov 4 17:15:35 2016 From: cushon at google.com (Liam Miller-Cushon) Date: Fri, 4 Nov 2016 10:15:35 -0700 Subject: handling invalid ConstantValue attributes In-Reply-To: <581BCC3D.4050608@oracle.com> References: <581BBFC0.1050407@oracle.com> <581BCC3D.4050608@oracle.com> Message-ID: Thanks. What do you think the best option is for handling out of range constants? Should javac do narrowing conversions? On Thu, Nov 3, 2016 at 4:46 PM, Jonathan Gibbons < jonathan.gibbons at oracle.com> wrote: > A corresponding RFE/enhancement to javap would be to report any such > issues. It is already somewhat fault tolerant, and will print "???" or > similar as needed, but more cross-referencing and checking could be done. > > -- Jon > > > On 11/03/2016 03:52 PM, Alex Buckley wrote: > >> In Lib.class, the field A contains a ConstantValue attribute that is >> ill-formed, since the attribute points to a CONSTANT_String c.p. entry that >> is not appropriate for a Z-typed field (per JVMS8 4.7.2). A class file >> reader such as javac must reject Lib.class on this basis. >> >> In Lib.class, the field B contains a ConstantValue attribute that is not >> ill-formed, since the attribute points to a CONSTANT_Integer c.p. entry >> that is appropriate for a Z-typed field. A class file reader such as javac >> must not reject Lib.class on this basis. However, javac should handle an >> out-of-band value in the CONSTANT_Integer c.p. entry as a >> quality-of-implementation detail. >> >> Alex >> >> On 11/3/2016 3:26 PM, Liam Miller-Cushon wrote: >> >>> javac silently accepts class files containing ConstantValue attributes >>> of the incorrect >>> type, or outside of the allowed ranges for int, short, char, byte, and >>> booleans. >>> >>> I expected javac to either reject the invalid bytecode, or convert the >>> constants to >>> their canonical representation (e.g. constant booleans should always be >>> 0 or 1). >>> >>> ecj rejects constants with the wrong type, and normalizes values outside >>> of the >>> expected range. >>> >>> I couldn't find anything in the spec for this, is it up to the >>> implementation? Would it >>> be possible to change javac's behaviour here? >>> >>> === Dump.java >>> import java.nio.file.Files; >>> import java.nio.file.Paths; >>> import org.objectweb.asm.ClassWriter; >>> import org.objectweb.asm.Opcodes; >>> >>> public class Dump { >>> >>> public static void main(String[] args) throws Exception { >>> Files.write(Paths.get("Lib.class"), dump()); >>> } >>> >>> static byte[] dump() { >>> ClassWriter cw = new ClassWriter(0); >>> cw.visit(52, Opcodes.ACC_SUPER, "Lib", null, "java/lang/Object", >>> null); >>> cw.visitField( >>> Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, >>> "A", "Z", null, "hello"); >>> cw.visitField( >>> Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_PUBLIC, >>> "B", "Z", null, 2); >>> cw.visitEnd(); >>> return cw.toByteArray(); >>> } >>> } >>> === >>> >>> === Test.java >>> class Test { >>> static final boolean ONE = Lib.A; >>> static final boolean TWO = Lib.B; >>> } >>> === >>> >>> === Test2.java >>> class Test2 { >>> static final boolean ONE = Lib.A || true; >>> } >>> === >>> >>> >>> $ javac -cp asm-debug-all-5.1.jar Dump.java >>> $ java -cp asm-debug-all-5.1.jar:. Dump >>> $ javac Test.java >>> $ javap -v Test >>> ... >>> static final boolean ONE; >>> descriptor: Z >>> flags: ACC_STATIC, ACC_FINAL >>> ConstantValue: String hello >>> >>> static final boolean TWO; >>> descriptor: Z >>> flags: ACC_STATIC, ACC_FINAL >>> ConstantValue: int 2 >>> >>> $ javac Test2.java >>> ... >>> java.lang.AssertionError: java.lang.ClassCastException: java.lang.String >>> (in module: java.base) cannot be cast to java.lang.Number (in module: >>> java.base) >>> at >>> com.sun.tools.javac.code.Symbol$VarSymbol.getConstValue(jdk. >>> compiler at 9-ea/Symbol.java:1530) >>> at >>> com.sun.tools.javac.comp.Attr.visitVarDef(jdk.compiler at 9-ea/Attr.java:1122) >>> >>> ... >>> Caused by: java.lang.ClassCastException: java.lang.String (in module: >>> java.base) cannot be cast to java.lang.Number (in module: java.base) >>> at >>> com.sun.tools.javac.comp.ConstFold.intValue(jdk.compiler at 9-ea/ConstFold.java:71) >>> >>> at >>> com.sun.tools.javac.comp.ConstFold.fold2(jdk.compiler at 9-ea/ConstFold.java:187) >>> >>> at >>> com.sun.tools.javac.comp.Attr.visitBinary(jdk.compiler at 9-ea/Attr.java:3211) >>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From bsrbnd at gmail.com Sun Nov 6 13:38:42 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Sun, 6 Nov 2016 14:38:42 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: <581B3F95.7060505@oracle.com> References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> Message-ID: Hi Jan, 2016-11-03 14:45 GMT+01:00 Jan Lahoda : > Hi Bernard, > > Thanks for looking at this. For the avoidance of the modification of > tree.selected in Lower.visitSelect, what I meant was more that we would > create a new instance of JCFieldAccess, to carry the new select. Might be > easier that trying to work with the existing select. > > I think it might be useful to have a set of tests covering the usecases, so > that we can more easily test patches (we will need tests eventually anyway). > I can look at that, unless you want to. > > On 3.11.2016 13:28, bsrbnd wrote: >> >> Here is a short summary of this issue. >> >> 1) The problem related to issue 8143388 changeset (which is probably a >> new issue) discovered here: >> >> http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010452.html >> >> is solved by the fix proposed here: >> >> http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010487.html >> >> 2) The optimization expected in issue 8147527 is obtained with the >> following patch: >> >> http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010448.html >> >> 3) I've added two additional checks (for the optimization) that verify >> if this$n: >> a) is synthetic >> b) matches the exact regex "this\$\d+" (instead of startsWith("this$")). > > > Offhand, this seems a little bit scary. > > Jan > > Next is a safer patch (including the optimization) which ensures that Lower.visitSelect(): 1) creates a new node, even if based on the original tree, by cloning it; 2) doesn't modify the original tree (Issue8147527.super.i) by restoring "tree.selected". Notice that it would perhaps be better to clone the tree at the start of Lower.visitSelect(), letting the original node unmodified. But I encountered a problem that I haven't solved yet. For the optimization, the handling of "this$n" in Lower.abstractRval() isn't needed anymore, which looks better because "this$n" shouldn't appear when building the "let expression" as it is translated after lowerBoxedPostop() in Lower.visitUnary(). Bernard diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2218,7 +2218,7 @@ return builder.build(rval); } Name name = TreeInfo.name(rval); - if (name == names._super) + if (name == names._super || name == names._this) return builder.build(rval); VarSymbol var = new VarSymbol(FINAL|SYNTHETIC, @@ -3837,6 +3837,7 @@ tree.selected.hasTag(SELECT) && TreeInfo.name(tree.selected) == names._super && !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, currentClass); + JCExpression original = tree.selected; tree.selected = translate(tree.selected); if (tree.name == names._class) { result = classOf(tree.selected); @@ -3853,6 +3854,9 @@ } else result = access(tree.sym, tree, enclOp, qualifiedSuperAccess); + + result = result == tree ? (JCExpression)tree.clone() : result; + tree.selected = original; } public void visitLetExpr(LetExpr tree) { >> >> The following example (derived from issue 8147527 with some additional >> cases) shows the result of the optimization: >> >> class Issue8147527 extends p.P { >> public static void main(String[] args) { >> Issue8147527 self = new Issue8147527(); >> self.testAll(); >> } >> >> private void testAll() { >> System.out.println(test()); >> System.out.println(i); >> >> Inner in = new Inner(); >> System.out.println(in.test()); >> System.out.println(i); >> >> System.out.println(testParent()); >> System.out.println(super.j); >> >> System.out.println(in.testParent()); >> System.out.println(super.j); >> } >> >> Integer i=0; >> private Integer test() { >> i++; >> return this.i++; >> } >> private Integer testParent() { >> j++; >> return super.j++; >> } >> >> class Inner { >> private Integer test() { >> i++; >> return Issue8147527.this.i++; >> } >> private Integer testParent() { >> j++; >> return Issue8147527.super.j++; >> } >> } >> } >> >> package p; >> >> public class P { >> protected Integer j=20; >> } >> >> The desugared code looks like this (as expected in issue 8147527): >> >> class Issue8147527$Inner { >> >> private Integer test() { >> (let /*synthetic*/ final Integer $647942 = this$0.i in (let >> /*synthetic*/ final Integer $29472086 = this$0.i = >> Integer.valueOf((int)(this$0.i.intValue() + 1)) in $647942)); >> return (let /*synthetic*/ final Integer $8278885 = >> (Integer)this$0.i in (let /*synthetic*/ final Integer $16578475 = >> this$0.i = Integer.valueOf((int)(this$0.i.intValue() + 1)) in >> $8278885)); >> } >> >> private Integer testParent() { >> (let /*synthetic*/ final Integer $798605 = >> Issue8147527.access$200(this$0) in (let /*synthetic*/ final Integer >> $5995540 = Issue8147527.access$302(this$0, >> Integer.valueOf((int)(Issue8147527.access$400(this$0).intValue() + >> 1))) in $798605)); >> return (let /*synthetic*/ final Integer $33017129 = >> (Integer)Issue8147527.access$501(this$0) in (let /*synthetic*/ final >> Integer $25625839 = Issue8147527.access$603(this$0, >> Integer.valueOf((int)(Issue8147527.access$701(this$0).intValue() + >> 1))) in $33017129)); >> } >> } >> >> class Issue8147527 extends p.P { >> >> private Integer test() { >> (let /*synthetic*/ final Integer $21617 = i in (let >> /*synthetic*/ final Integer $20066205 = i = >> Integer.valueOf((int)(i.intValue() + 1)) in $21617)); >> return (let /*synthetic*/ final Integer $32619253 = >> (Integer)this.i in (let /*synthetic*/ final Integer $27442939 = this.i >> = Integer.valueOf((int)(this.i.intValue() + 1)) in $32619253)); >> } >> >> private Integer testParent() { >> (let /*synthetic*/ final Integer $4208220 = j in (let >> /*synthetic*/ final Integer $32359562 = j = >> Integer.valueOf((int)(j.intValue() + 1)) in $4208220)); >> return (let /*synthetic*/ final Integer $20049680 = >> (Integer)super.j in (let /*synthetic*/ final Integer $28368043 = >> super.j = Integer.valueOf((int)(super.j.intValue() + 1)) in >> $20049680)); >> } >> } >> >> Putting all (1, 2 and 3) together gives the patch below. >> >> Bernard >> >> diff --git >> a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >> b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >> @@ -926,7 +926,7 @@ >> ClassSymbol accOwner = refSuper && protAccess >> // For access via qualified super (T.super.x), place the >> // access symbol on T. >> - ? (ClassSymbol)((JCFieldAccess) tree).selected.type.tsym >> + ? (ClassSymbol)((JCFieldAccess)((JCFieldAccess) >> tree).selected).selected.type.tsym >> // Otherwise pretend that the owner of an accessed >> // protected symbol is the enclosing class of the current >> // class which is a subclass of the symbol's owner. >> @@ -1100,6 +1100,7 @@ >> tree = make.at(tree.pos).Ident(sym); >> } >> JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) >> tree).selected : null; >> + base = refSuper ? translate(base) : base; >> switch (sym.kind) { >> case TYP: >> if (sym.owner.kind != PCK) { >> @@ -2209,16 +2210,20 @@ >> */ >> JCExpression abstractRval(JCExpression rval, Type type, >> TreeBuilder builder) { >> rval = TreeInfo.skipParens(rval); >> + boolean synthetic = false; >> switch (rval.getTag()) { >> case LITERAL: >> return builder.build(rval); >> case IDENT: >> JCIdent id = (JCIdent) rval; >> + synthetic = (id.sym.flags() & SYNTHETIC) != 0; >> if ((id.sym.flags() & FINAL) != 0 && id.sym.owner.kind == >> MTH) >> return builder.build(rval); >> } >> Name name = TreeInfo.name(rval); >> - if (name == names._super) >> + String thisDollarN = names._this + "\\" + >> target.syntheticNameChar() + "\\d+"; >> + boolean matchesThisDollar = synthetic && name != null && >> name.toString().matches(thisDollarN); >> + if (name == names._super || name == names._this || >> matchesThisDollar) >> return builder.build(rval); >> VarSymbol var = >> new VarSymbol(FINAL|SYNTHETIC, >> @@ -3837,7 +3842,7 @@ >> tree.selected.hasTag(SELECT) && >> TreeInfo.name(tree.selected) == names._super && >> >> !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, >> currentClass); >> - tree.selected = translate(tree.selected); >> + if (!qualifiedSuperAccess) tree.selected = >> translate(tree.selected); >> if (tree.name == names._class) { >> result = classOf(tree.selected); >> } >> > From bsrbnd at gmail.com Mon Nov 7 12:59:02 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Mon, 7 Nov 2016 13:59:02 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> Message-ID: Hi, 2016-11-06 14:38 GMT+01:00 bsrbnd : > Hi Jan, > > 2016-11-03 14:45 GMT+01:00 Jan Lahoda : >> Hi Bernard, >> >> Thanks for looking at this. For the avoidance of the modification of >> tree.selected in Lower.visitSelect, what I meant was more that we would >> create a new instance of JCFieldAccess, to carry the new select. Might be >> easier that trying to work with the existing select. >> >> I think it might be useful to have a set of tests covering the usecases, so >> that we can more easily test patches (we will need tests eventually anyway). >> I can look at that, unless you want to. >> >> On 3.11.2016 13:28, bsrbnd wrote: >>> >>> Here is a short summary of this issue. >>> >>> 1) The problem related to issue 8143388 changeset (which is probably a >>> new issue) discovered here: >>> >>> http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010452.html >>> >>> is solved by the fix proposed here: >>> >>> http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010487.html >>> >>> 2) The optimization expected in issue 8147527 is obtained with the >>> following patch: >>> >>> http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010448.html >>> >>> 3) I've added two additional checks (for the optimization) that verify >>> if this$n: >>> a) is synthetic >>> b) matches the exact regex "this\$\d+" (instead of startsWith("this$")). >> >> >> Offhand, this seems a little bit scary. >> >> Jan >> >> > Next is a safer patch (including the optimization) which ensures that > Lower.visitSelect(): > 1) creates a new node, even if based on the original tree, by cloning it; > 2) doesn't modify the original tree (Issue8147527.super.i) by > restoring "tree.selected". > > Notice that it would perhaps be better to clone the tree at the start > of Lower.visitSelect(), letting the original node unmodified. But I > encountered a problem that I haven't solved yet. > The problem is that the enclosing operation refers to the original node which fails Lower.accessCode(). The following patch is a possible solution. I don't know if this is better than the previous one: http://mail.openjdk.java.net/pipermail/compiler-dev/2016-November/010504.html Both of them correct the problem (all javac tests have been run for the first one). What do you think of these solutions? Bernard diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -921,7 +921,7 @@ * package? * @param refSuper Is access via a (qualified) C.super? */ - MethodSymbol accessSymbol(Symbol sym, JCTree tree, JCTree enclOp, + MethodSymbol accessSymbol(Symbol sym, JCTree tree, JCTree original, JCTree enclOp, boolean protAccess, boolean refSuper) { ClassSymbol accOwner = refSuper && protAccess // For access via qualified super (T.super.x), place the @@ -954,7 +954,7 @@ List thrown; // The thrown exceptions of the access method. switch (vsym.kind) { case VAR: - acode = accessCode(tree, enclOp); + acode = accessCode(original, enclOp); if (acode >= AccessCode.FIRSTASGOP.code) { OperatorSymbol operator = binaryAccessOperator(acode, enclOp.getTag()); if (operator.opcode == string_add) @@ -1085,6 +1085,9 @@ * @param refSuper Is access via a (qualified) C.super? */ JCExpression access(Symbol sym, JCExpression tree, JCExpression enclOp, boolean refSuper) { + return access(sym, tree, tree, enclOp, refSuper); + } + JCExpression access(Symbol sym, JCExpression tree, JCExpression original, JCExpression enclOp, boolean refSuper) { // Access a free variable via its proxy, or its proxy's proxy while (sym.kind == VAR && sym.owner.kind == MTH && sym.owner.enclClass() != currentClass) { @@ -1167,7 +1170,7 @@ args = args.prepend(base); base = null; // so we don't duplicate code } - Symbol access = accessSymbol(sym, tree, + Symbol access = accessSymbol(sym, tree, original, enclOp, protAccess, refSuper); JCExpression receiver = make.Select( @@ -2218,7 +2221,7 @@ return builder.build(rval); } Name name = TreeInfo.name(rval); - if (name == names._super) + if (name == names._super || name == names._this) return builder.build(rval); VarSymbol var = new VarSymbol(FINAL|SYNTHETIC, @@ -3829,7 +3832,8 @@ result = tree; } - public void visitSelect(JCFieldAccess tree) { + public void visitSelect(JCFieldAccess fieldAccess) { + JCFieldAccess tree = (JCFieldAccess)fieldAccess.clone(); // need to special case-access of the form C.super.x // these will always need an access method, unless C // is a default interface subclassed by the current class. @@ -3852,7 +3856,7 @@ result = makeThis(tree.pos(), tree.selected.type.tsym); } else - result = access(tree.sym, tree, enclOp, qualifiedSuperAccess); + result = access(tree.sym, tree, fieldAccess, enclOp, qualifiedSuperAccess); } public void visitLetExpr(LetExpr tree) { > For the optimization, the handling of "this$n" in Lower.abstractRval() > isn't needed anymore, which looks better because "this$n" shouldn't > appear when building the "let expression" as it is translated after > lowerBoxedPostop() in Lower.visitUnary(). > > Bernard > > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > @@ -2218,7 +2218,7 @@ > return builder.build(rval); > } > Name name = TreeInfo.name(rval); > - if (name == names._super) > + if (name == names._super || name == names._this) > return builder.build(rval); > VarSymbol var = > new VarSymbol(FINAL|SYNTHETIC, > @@ -3837,6 +3837,7 @@ > tree.selected.hasTag(SELECT) && > TreeInfo.name(tree.selected) == names._super && > !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, > currentClass); > + JCExpression original = tree.selected; > tree.selected = translate(tree.selected); > if (tree.name == names._class) { > result = classOf(tree.selected); > @@ -3853,6 +3854,9 @@ > } > else > result = access(tree.sym, tree, enclOp, qualifiedSuperAccess); > + > + result = result == tree ? (JCExpression)tree.clone() : result; > + tree.selected = original; > } > > public void visitLetExpr(LetExpr tree) { > >>> >>> The following example (derived from issue 8147527 with some additional >>> cases) shows the result of the optimization: >>> >>> class Issue8147527 extends p.P { >>> public static void main(String[] args) { >>> Issue8147527 self = new Issue8147527(); >>> self.testAll(); >>> } >>> >>> private void testAll() { >>> System.out.println(test()); >>> System.out.println(i); >>> >>> Inner in = new Inner(); >>> System.out.println(in.test()); >>> System.out.println(i); >>> >>> System.out.println(testParent()); >>> System.out.println(super.j); >>> >>> System.out.println(in.testParent()); >>> System.out.println(super.j); >>> } >>> >>> Integer i=0; >>> private Integer test() { >>> i++; >>> return this.i++; >>> } >>> private Integer testParent() { >>> j++; >>> return super.j++; >>> } >>> >>> class Inner { >>> private Integer test() { >>> i++; >>> return Issue8147527.this.i++; >>> } >>> private Integer testParent() { >>> j++; >>> return Issue8147527.super.j++; >>> } >>> } >>> } >>> >>> package p; >>> >>> public class P { >>> protected Integer j=20; >>> } >>> >>> The desugared code looks like this (as expected in issue 8147527): >>> >>> class Issue8147527$Inner { >>> >>> private Integer test() { >>> (let /*synthetic*/ final Integer $647942 = this$0.i in (let >>> /*synthetic*/ final Integer $29472086 = this$0.i = >>> Integer.valueOf((int)(this$0.i.intValue() + 1)) in $647942)); >>> return (let /*synthetic*/ final Integer $8278885 = >>> (Integer)this$0.i in (let /*synthetic*/ final Integer $16578475 = >>> this$0.i = Integer.valueOf((int)(this$0.i.intValue() + 1)) in >>> $8278885)); >>> } >>> >>> private Integer testParent() { >>> (let /*synthetic*/ final Integer $798605 = >>> Issue8147527.access$200(this$0) in (let /*synthetic*/ final Integer >>> $5995540 = Issue8147527.access$302(this$0, >>> Integer.valueOf((int)(Issue8147527.access$400(this$0).intValue() + >>> 1))) in $798605)); >>> return (let /*synthetic*/ final Integer $33017129 = >>> (Integer)Issue8147527.access$501(this$0) in (let /*synthetic*/ final >>> Integer $25625839 = Issue8147527.access$603(this$0, >>> Integer.valueOf((int)(Issue8147527.access$701(this$0).intValue() + >>> 1))) in $33017129)); >>> } >>> } >>> >>> class Issue8147527 extends p.P { >>> >>> private Integer test() { >>> (let /*synthetic*/ final Integer $21617 = i in (let >>> /*synthetic*/ final Integer $20066205 = i = >>> Integer.valueOf((int)(i.intValue() + 1)) in $21617)); >>> return (let /*synthetic*/ final Integer $32619253 = >>> (Integer)this.i in (let /*synthetic*/ final Integer $27442939 = this.i >>> = Integer.valueOf((int)(this.i.intValue() + 1)) in $32619253)); >>> } >>> >>> private Integer testParent() { >>> (let /*synthetic*/ final Integer $4208220 = j in (let >>> /*synthetic*/ final Integer $32359562 = j = >>> Integer.valueOf((int)(j.intValue() + 1)) in $4208220)); >>> return (let /*synthetic*/ final Integer $20049680 = >>> (Integer)super.j in (let /*synthetic*/ final Integer $28368043 = >>> super.j = Integer.valueOf((int)(super.j.intValue() + 1)) in >>> $20049680)); >>> } >>> } >>> >>> Putting all (1, 2 and 3) together gives the patch below. >>> >>> Bernard >>> >>> diff --git >>> a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >>> b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >>> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >>> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >>> @@ -926,7 +926,7 @@ >>> ClassSymbol accOwner = refSuper && protAccess >>> // For access via qualified super (T.super.x), place the >>> // access symbol on T. >>> - ? (ClassSymbol)((JCFieldAccess) tree).selected.type.tsym >>> + ? (ClassSymbol)((JCFieldAccess)((JCFieldAccess) >>> tree).selected).selected.type.tsym >>> // Otherwise pretend that the owner of an accessed >>> // protected symbol is the enclosing class of the current >>> // class which is a subclass of the symbol's owner. >>> @@ -1100,6 +1100,7 @@ >>> tree = make.at(tree.pos).Ident(sym); >>> } >>> JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) >>> tree).selected : null; >>> + base = refSuper ? translate(base) : base; >>> switch (sym.kind) { >>> case TYP: >>> if (sym.owner.kind != PCK) { >>> @@ -2209,16 +2210,20 @@ >>> */ >>> JCExpression abstractRval(JCExpression rval, Type type, >>> TreeBuilder builder) { >>> rval = TreeInfo.skipParens(rval); >>> + boolean synthetic = false; >>> switch (rval.getTag()) { >>> case LITERAL: >>> return builder.build(rval); >>> case IDENT: >>> JCIdent id = (JCIdent) rval; >>> + synthetic = (id.sym.flags() & SYNTHETIC) != 0; >>> if ((id.sym.flags() & FINAL) != 0 && id.sym.owner.kind == >>> MTH) >>> return builder.build(rval); >>> } >>> Name name = TreeInfo.name(rval); >>> - if (name == names._super) >>> + String thisDollarN = names._this + "\\" + >>> target.syntheticNameChar() + "\\d+"; >>> + boolean matchesThisDollar = synthetic && name != null && >>> name.toString().matches(thisDollarN); >>> + if (name == names._super || name == names._this || >>> matchesThisDollar) >>> return builder.build(rval); >>> VarSymbol var = >>> new VarSymbol(FINAL|SYNTHETIC, >>> @@ -3837,7 +3842,7 @@ >>> tree.selected.hasTag(SELECT) && >>> TreeInfo.name(tree.selected) == names._super && >>> >>> !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, >>> currentClass); >>> - tree.selected = translate(tree.selected); >>> + if (!qualifiedSuperAccess) tree.selected = >>> translate(tree.selected); >>> if (tree.name == names._class) { >>> result = classOf(tree.selected); >>> } >>> >> From bsrbnd at gmail.com Mon Nov 7 21:48:08 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Mon, 7 Nov 2016 22:48:08 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> Message-ID: Hi, Another solution would be to clone the nodes as the unary boxed operation is expanded. This way, there is no reused tree at all and Lower.visitSelect() has no need to be modified. It's probably the easiest solution which is also the one that makes most sense (I think). Below is a fix including the optimization. Bernard diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2218,7 +2218,7 @@ return builder.build(rval); } Name name = TreeInfo.name(rval); - if (name == names._super) + if (name == names._super || name == names._this) return builder.build(rval); VarSymbol var = new VarSymbol(FINAL|SYNTHETIC, @@ -3205,7 +3205,7 @@ newTag, tree.type, tree.rhs.type); - JCExpression expr = lhs; + JCExpression expr = (JCExpression)lhs.clone(); if (expr.type != tree.type) expr = make.TypeCast(tree.type, expr); JCBinary opResult = make.Binary(newTag, expr, tree.rhs); @@ -3292,7 +3292,7 @@ ? make.TypeCast(tree.arg.type, tmp1) : tmp1; JCExpression update = makeAssignop(opcode, - lhs, + (JCExpression)lhs.clone(), make.Literal(1)); return makeComma(update, tmp2); } 2016-11-07 13:59 GMT+01:00 bsrbnd : > Hi, > > 2016-11-06 14:38 GMT+01:00 bsrbnd : >> Hi Jan, >> >> 2016-11-03 14:45 GMT+01:00 Jan Lahoda : >>> Hi Bernard, >>> >>> Thanks for looking at this. For the avoidance of the modification of >>> tree.selected in Lower.visitSelect, what I meant was more that we would >>> create a new instance of JCFieldAccess, to carry the new select. Might be >>> easier that trying to work with the existing select. >>> >>> I think it might be useful to have a set of tests covering the usecases, so >>> that we can more easily test patches (we will need tests eventually anyway). >>> I can look at that, unless you want to. >>> >>> On 3.11.2016 13:28, bsrbnd wrote: >>>> >>>> Here is a short summary of this issue. >>>> >>>> 1) The problem related to issue 8143388 changeset (which is probably a >>>> new issue) discovered here: >>>> >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010452.html >>>> >>>> is solved by the fix proposed here: >>>> >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010487.html >>>> >>>> 2) The optimization expected in issue 8147527 is obtained with the >>>> following patch: >>>> >>>> http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010448.html >>>> >>>> 3) I've added two additional checks (for the optimization) that verify >>>> if this$n: >>>> a) is synthetic >>>> b) matches the exact regex "this\$\d+" (instead of startsWith("this$")). >>> >>> >>> Offhand, this seems a little bit scary. >>> >>> Jan >>> >>> >> Next is a safer patch (including the optimization) which ensures that >> Lower.visitSelect(): >> 1) creates a new node, even if based on the original tree, by cloning it; >> 2) doesn't modify the original tree (Issue8147527.super.i) by >> restoring "tree.selected". >> >> Notice that it would perhaps be better to clone the tree at the start >> of Lower.visitSelect(), letting the original node unmodified. But I >> encountered a problem that I haven't solved yet. >> > The problem is that the enclosing operation refers to the original > node which fails Lower.accessCode(). The following patch is a possible > solution. I don't know if this is better than the previous one: > > http://mail.openjdk.java.net/pipermail/compiler-dev/2016-November/010504.html > > Both of them correct the problem (all javac tests have been run for > the first one). > What do you think of these solutions? > > Bernard > > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > @@ -921,7 +921,7 @@ > * package? > * @param refSuper Is access via a (qualified) C.super? > */ > - MethodSymbol accessSymbol(Symbol sym, JCTree tree, JCTree enclOp, > + MethodSymbol accessSymbol(Symbol sym, JCTree tree, JCTree > original, JCTree enclOp, > boolean protAccess, boolean refSuper) { > ClassSymbol accOwner = refSuper && protAccess > // For access via qualified super (T.super.x), place the > @@ -954,7 +954,7 @@ > List thrown; // The thrown exceptions of the > access method. > switch (vsym.kind) { > case VAR: > - acode = accessCode(tree, enclOp); > + acode = accessCode(original, enclOp); > if (acode >= AccessCode.FIRSTASGOP.code) { > OperatorSymbol operator = binaryAccessOperator(acode, > enclOp.getTag()); > if (operator.opcode == string_add) > @@ -1085,6 +1085,9 @@ > * @param refSuper Is access via a (qualified) C.super? > */ > JCExpression access(Symbol sym, JCExpression tree, JCExpression > enclOp, boolean refSuper) { > + return access(sym, tree, tree, enclOp, refSuper); > + } > + JCExpression access(Symbol sym, JCExpression tree, JCExpression > original, JCExpression enclOp, boolean refSuper) { > // Access a free variable via its proxy, or its proxy's proxy > while (sym.kind == VAR && sym.owner.kind == MTH && > sym.owner.enclClass() != currentClass) { > @@ -1167,7 +1170,7 @@ > args = args.prepend(base); > base = null; // so we don't duplicate code > } > - Symbol access = accessSymbol(sym, tree, > + Symbol access = accessSymbol(sym, tree, original, > enclOp, protAccess, > refSuper); > JCExpression receiver = make.Select( > @@ -2218,7 +2221,7 @@ > return builder.build(rval); > } > Name name = TreeInfo.name(rval); > - if (name == names._super) > + if (name == names._super || name == names._this) > return builder.build(rval); > VarSymbol var = > new VarSymbol(FINAL|SYNTHETIC, > @@ -3829,7 +3832,8 @@ > result = tree; > } > > - public void visitSelect(JCFieldAccess tree) { > + public void visitSelect(JCFieldAccess fieldAccess) { > + JCFieldAccess tree = (JCFieldAccess)fieldAccess.clone(); > // need to special case-access of the form C.super.x > // these will always need an access method, unless C > // is a default interface subclassed by the current class. > @@ -3852,7 +3856,7 @@ > result = makeThis(tree.pos(), tree.selected.type.tsym); > } > else > - result = access(tree.sym, tree, enclOp, qualifiedSuperAccess); > + result = access(tree.sym, tree, fieldAccess, enclOp, > qualifiedSuperAccess); > } > > public void visitLetExpr(LetExpr tree) { > >> For the optimization, the handling of "this$n" in Lower.abstractRval() >> isn't needed anymore, which looks better because "this$n" shouldn't >> appear when building the "let expression" as it is translated after >> lowerBoxedPostop() in Lower.visitUnary(). >> >> Bernard >> >> diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >> b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >> @@ -2218,7 +2218,7 @@ >> return builder.build(rval); >> } >> Name name = TreeInfo.name(rval); >> - if (name == names._super) >> + if (name == names._super || name == names._this) >> return builder.build(rval); >> VarSymbol var = >> new VarSymbol(FINAL|SYNTHETIC, >> @@ -3837,6 +3837,7 @@ >> tree.selected.hasTag(SELECT) && >> TreeInfo.name(tree.selected) == names._super && >> !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, >> currentClass); >> + JCExpression original = tree.selected; >> tree.selected = translate(tree.selected); >> if (tree.name == names._class) { >> result = classOf(tree.selected); >> @@ -3853,6 +3854,9 @@ >> } >> else >> result = access(tree.sym, tree, enclOp, qualifiedSuperAccess); >> + >> + result = result == tree ? (JCExpression)tree.clone() : result; >> + tree.selected = original; >> } >> >> public void visitLetExpr(LetExpr tree) { >> >>>> >>>> The following example (derived from issue 8147527 with some additional >>>> cases) shows the result of the optimization: >>>> >>>> class Issue8147527 extends p.P { >>>> public static void main(String[] args) { >>>> Issue8147527 self = new Issue8147527(); >>>> self.testAll(); >>>> } >>>> >>>> private void testAll() { >>>> System.out.println(test()); >>>> System.out.println(i); >>>> >>>> Inner in = new Inner(); >>>> System.out.println(in.test()); >>>> System.out.println(i); >>>> >>>> System.out.println(testParent()); >>>> System.out.println(super.j); >>>> >>>> System.out.println(in.testParent()); >>>> System.out.println(super.j); >>>> } >>>> >>>> Integer i=0; >>>> private Integer test() { >>>> i++; >>>> return this.i++; >>>> } >>>> private Integer testParent() { >>>> j++; >>>> return super.j++; >>>> } >>>> >>>> class Inner { >>>> private Integer test() { >>>> i++; >>>> return Issue8147527.this.i++; >>>> } >>>> private Integer testParent() { >>>> j++; >>>> return Issue8147527.super.j++; >>>> } >>>> } >>>> } >>>> >>>> package p; >>>> >>>> public class P { >>>> protected Integer j=20; >>>> } >>>> >>>> The desugared code looks like this (as expected in issue 8147527): >>>> >>>> class Issue8147527$Inner { >>>> >>>> private Integer test() { >>>> (let /*synthetic*/ final Integer $647942 = this$0.i in (let >>>> /*synthetic*/ final Integer $29472086 = this$0.i = >>>> Integer.valueOf((int)(this$0.i.intValue() + 1)) in $647942)); >>>> return (let /*synthetic*/ final Integer $8278885 = >>>> (Integer)this$0.i in (let /*synthetic*/ final Integer $16578475 = >>>> this$0.i = Integer.valueOf((int)(this$0.i.intValue() + 1)) in >>>> $8278885)); >>>> } >>>> >>>> private Integer testParent() { >>>> (let /*synthetic*/ final Integer $798605 = >>>> Issue8147527.access$200(this$0) in (let /*synthetic*/ final Integer >>>> $5995540 = Issue8147527.access$302(this$0, >>>> Integer.valueOf((int)(Issue8147527.access$400(this$0).intValue() + >>>> 1))) in $798605)); >>>> return (let /*synthetic*/ final Integer $33017129 = >>>> (Integer)Issue8147527.access$501(this$0) in (let /*synthetic*/ final >>>> Integer $25625839 = Issue8147527.access$603(this$0, >>>> Integer.valueOf((int)(Issue8147527.access$701(this$0).intValue() + >>>> 1))) in $33017129)); >>>> } >>>> } >>>> >>>> class Issue8147527 extends p.P { >>>> >>>> private Integer test() { >>>> (let /*synthetic*/ final Integer $21617 = i in (let >>>> /*synthetic*/ final Integer $20066205 = i = >>>> Integer.valueOf((int)(i.intValue() + 1)) in $21617)); >>>> return (let /*synthetic*/ final Integer $32619253 = >>>> (Integer)this.i in (let /*synthetic*/ final Integer $27442939 = this.i >>>> = Integer.valueOf((int)(this.i.intValue() + 1)) in $32619253)); >>>> } >>>> >>>> private Integer testParent() { >>>> (let /*synthetic*/ final Integer $4208220 = j in (let >>>> /*synthetic*/ final Integer $32359562 = j = >>>> Integer.valueOf((int)(j.intValue() + 1)) in $4208220)); >>>> return (let /*synthetic*/ final Integer $20049680 = >>>> (Integer)super.j in (let /*synthetic*/ final Integer $28368043 = >>>> super.j = Integer.valueOf((int)(super.j.intValue() + 1)) in >>>> $20049680)); >>>> } >>>> } >>>> >>>> Putting all (1, 2 and 3) together gives the patch below. >>>> >>>> Bernard >>>> >>>> diff --git >>>> a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >>>> b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >>>> --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >>>> +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java >>>> @@ -926,7 +926,7 @@ >>>> ClassSymbol accOwner = refSuper && protAccess >>>> // For access via qualified super (T.super.x), place the >>>> // access symbol on T. >>>> - ? (ClassSymbol)((JCFieldAccess) tree).selected.type.tsym >>>> + ? (ClassSymbol)((JCFieldAccess)((JCFieldAccess) >>>> tree).selected).selected.type.tsym >>>> // Otherwise pretend that the owner of an accessed >>>> // protected symbol is the enclosing class of the current >>>> // class which is a subclass of the symbol's owner. >>>> @@ -1100,6 +1100,7 @@ >>>> tree = make.at(tree.pos).Ident(sym); >>>> } >>>> JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) >>>> tree).selected : null; >>>> + base = refSuper ? translate(base) : base; >>>> switch (sym.kind) { >>>> case TYP: >>>> if (sym.owner.kind != PCK) { >>>> @@ -2209,16 +2210,20 @@ >>>> */ >>>> JCExpression abstractRval(JCExpression rval, Type type, >>>> TreeBuilder builder) { >>>> rval = TreeInfo.skipParens(rval); >>>> + boolean synthetic = false; >>>> switch (rval.getTag()) { >>>> case LITERAL: >>>> return builder.build(rval); >>>> case IDENT: >>>> JCIdent id = (JCIdent) rval; >>>> + synthetic = (id.sym.flags() & SYNTHETIC) != 0; >>>> if ((id.sym.flags() & FINAL) != 0 && id.sym.owner.kind == >>>> MTH) >>>> return builder.build(rval); >>>> } >>>> Name name = TreeInfo.name(rval); >>>> - if (name == names._super) >>>> + String thisDollarN = names._this + "\\" + >>>> target.syntheticNameChar() + "\\d+"; >>>> + boolean matchesThisDollar = synthetic && name != null && >>>> name.toString().matches(thisDollarN); >>>> + if (name == names._super || name == names._this || >>>> matchesThisDollar) >>>> return builder.build(rval); >>>> VarSymbol var = >>>> new VarSymbol(FINAL|SYNTHETIC, >>>> @@ -3837,7 +3842,7 @@ >>>> tree.selected.hasTag(SELECT) && >>>> TreeInfo.name(tree.selected) == names._super && >>>> >>>> !types.isDirectSuperInterface(((JCFieldAccess)tree.selected).selected.type.tsym, >>>> currentClass); >>>> - tree.selected = translate(tree.selected); >>>> + if (!qualifiedSuperAccess) tree.selected = >>>> translate(tree.selected); >>>> if (tree.name == names._class) { >>>> result = classOf(tree.selected); >>>> } >>>> >>> From cushon at google.com Wed Nov 9 00:31:02 2016 From: cushon at google.com (Liam Miller-Cushon) Date: Tue, 8 Nov 2016 16:31:02 -0800 Subject: MethodParameters attributes in v51 classfiles Message-ID: If -parameters is passed, javac will write MethodParameters attributes when source/target < 8. It also reports -Xlint:classfile warnings about MethodParameters attributes in < v52 classfiles: class X { void f(int a) {} } class Y { X x; } $ javac -source 7 -target 7 -parameters X.java $ javac -Xlint:classfile -sourcepath : Y.java ./X.class: warning: [classfile] MethodParameters attribute introduced in version 52.0 class files is ignored in version 51.0 class files Is that deliberate? I expected it to either not write the attribute for old classfile versions, or not warn about it. -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Wed Nov 9 00:40:13 2016 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 08 Nov 2016 16:40:13 -0800 Subject: MethodParameters attributes in v51 classfiles In-Reply-To: References: Message-ID: <5822706D.1000504@oracle.com> On 11/08/2016 04:31 PM, Liam Miller-Cushon wrote: > If -parameters is passed, javac will write MethodParameters attributes > when source/target < 8. It also reports -Xlint:classfile warnings > about MethodParameters attributes in < v52 classfiles: > > class X { > void f(int a) {} > } > class Y { > X x; > } > > $ javac -source 7 -target 7 -parameters X.java > $ javac -Xlint:classfile -sourcepath : Y.java > ./X.class: warning: [classfile] MethodParameters attribute introduced > in version 52.0 class files is ignored in version 51.0 class files > > Is that deliberate? I expected it to either not write the attribute > for old classfile versions, or not warn about it. Since the code that generates the warning is a general warning for any future attribute, and not specific to MethodParameters, it would seem more appropriate to not generate the attribute for versions for which it is not appropriate. -- Jon From cushon at google.com Wed Nov 9 01:22:36 2016 From: cushon at google.com (Liam Miller-Cushon) Date: Tue, 8 Nov 2016 17:22:36 -0800 Subject: MethodParameters attributes in v51 classfiles In-Reply-To: <5822706D.1000504@oracle.com> References: <5822706D.1000504@oracle.com> Message-ID: I'd be happy to have MethodParameters attributes in older class file versions, but not wanting to special-case future attribute diagnostics makes sense. This came up because of a bad interaction between future attribute diagnostics and rawtypes warnings. The same issue might affect other future attribute warnings or other diagnostic kinds, so it's probably worth tracking separately: public class A { public A(F f) {} } public class B { public void t(int i) {} } public class Test { public void f() { new A(new B()); } } javac -parameters -source 7 -target 7 A.java B.java javac -Xlint:all -sourcepath : Test.java ./A.class: warning: [classfile] MethodParameters attribute introduced in version 52.0 class files is ignored in version 51.0 class files ./B.class: warning: [classfile] MethodParameters attribute introduced in version 52.0 class files is ignored in version 51.0 class files 2 warnings An exception has occurred in the compiler (9-ea). Please file a bug against the Java compiler via the Java bug reporting page (http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com) for duplicates. Include your program and the following diagnostic in your report. Thank you. java.lang.AssertionError: Missing type variable in where clause: E at com.sun.tools.javac.util.RichDiagnosticFormatter.unique(jdk.compiler at 9-ea /RichDiagnosticFormatter.java:247) at com.sun.tools.javac.util.RichDiagnosticFormatter.access$100(jdk.compiler at 9-ea /RichDiagnosticFormatter.java:71) at com.sun.tools.javac.util.RichDiagnosticFormatter$RichPrinter.visitTypeVar(jdk.compiler at 9-ea /RichDiagnosticFormatter.java:398) at com.sun.tools.javac.util.RichDiagnosticFormatter$RichPrinter.visitTypeVar(jdk.compiler at 9-ea /RichDiagnosticFormatter.java:340) On Tue, Nov 8, 2016 at 4:40 PM, Jonathan Gibbons < jonathan.gibbons at oracle.com> wrote: > > > On 11/08/2016 04:31 PM, Liam Miller-Cushon wrote: > >> If -parameters is passed, javac will write MethodParameters attributes >> when source/target < 8. It also reports -Xlint:classfile warnings about >> MethodParameters attributes in < v52 classfiles: >> >> class X { >> void f(int a) {} >> } >> class Y { >> X x; >> } >> >> $ javac -source 7 -target 7 -parameters X.java >> $ javac -Xlint:classfile -sourcepath : Y.java >> ./X.class: warning: [classfile] MethodParameters attribute introduced in >> version 52.0 class files is ignored in version 51.0 class files >> >> Is that deliberate? I expected it to either not write the attribute for >> old classfile versions, or not warn about it. >> > > Since the code that generates the warning is a general warning for any > future attribute, and not specific to MethodParameters, it would seem more > appropriate to not generate the attribute for versions for which it is not > appropriate. > > -- Jon > -------------- next part -------------- An HTML attachment was scrubbed... URL: From bsrbnd at gmail.com Wed Nov 9 17:33:07 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Wed, 9 Nov 2016 18:33:07 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: <581B3F95.7060505@oracle.com> References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> Message-ID: Hi Jan, 2016-11-03 14:45 GMT+01:00 Jan Lahoda : > Hi Bernard, > > Thanks for looking at this. For the avoidance of the modification of > tree.selected in Lower.visitSelect, what I meant was more that we would > create a new instance of JCFieldAccess, to carry the new select. Might be > easier that trying to work with the existing select. > > I think it might be useful to have a set of tests covering the usecases, so > that we can more easily test patches (we will need tests eventually anyway). > I can look at that, unless you want to. > Please find next a test for the first problem. Bernard diff --git a/test/tools/javac/boxing/QualBoxedPostOp.java b/test/tools/javac/boxing/QualBoxedPostOp.java new file mode 100644 --- /dev/null +++ b/test/tools/javac/boxing/QualBoxedPostOp.java @@ -0,0 +1,51 @@ +/* + * @test + * @bug 8147527 + * @summary Qualified "this" and "super" boxed unary post operations. + */ +public class QualBoxedPostOp extends Parent { + public static void main(String[] args) { + new QualBoxedPostOp().testAll(); + } + + private void testAll() { + equals(test(), 0); + equals(i, 1); + + Inner in = new Inner(); + equals(in.test(), 1); + equals(i, 2); + + equals(testParent(), 10); + equals(super.i, 11); + + equals(in.testParent(), 11); + equals(super.i, 12); + } + + private void equals(int a, int b) { + if (a != b) throw new Error(); + } + + Integer i=0; + + private Integer test() { + return this.i++; + } + private Integer testParent() { + return super.i++; + } + + class Inner { + private Integer test() { + return QualBoxedPostOp.this.i++; + } + private Integer testParent() { + return QualBoxedPostOp.super.i++; + } + } +} + +class Parent { + protected Integer i=10; +} From bsrbnd at gmail.com Thu Nov 10 19:12:38 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Thu, 10 Nov 2016 20:12:38 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: <581B3F95.7060505@oracle.com> References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> Message-ID: Hi, 2016-11-03 14:45 GMT+01:00 Jan Lahoda : > Hi Bernard, > > Thanks for looking at this. For the avoidance of the modification of > tree.selected in Lower.visitSelect, what I meant was more that we would > create a new instance of JCFieldAccess, to carry the new select. Might be > easier that trying to work with the existing select. > > I think it might be useful to have a set of tests covering the usecases, so > that we can more easily test patches (we will need tests eventually anyway). > I can look at that, unless you want to. > Here below is a test (derived from issue 8143388 test) for the optimization of "this" and "this$n". Bernard diff --git a/test/tools/javac/boxing/BoxedPostOpOpti.java b/test/tools/javac/boxing/BoxedPostOpOpti.java new file mode 100644 --- /dev/null +++ b/test/tools/javac/boxing/BoxedPostOpOpti.java @@ -0,0 +1,77 @@ +/* + * @test + * @bug 8147527 + * @summary "this" and "this$n" code optimization for boxed unary post-operations. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jdeps/com.sun.tools.javap + * @build toolbox.ToolBox toolbox.JavacTask + * @run main BoxedPostOpOpti + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +import toolbox.JavacTask; +import toolbox.ToolBox; + +public class BoxedPostOpOpti { + public static void main(String... args) throws IOException { + new BoxedPostOpOpti().run(); + } + + void run() throws IOException { + ToolBox tb = new ToolBox(); + + Path expected = Paths.get("expected"); + Files.createDirectories(expected); + tb.cleanDirectory(expected); + new JavacTask(tb).sources( + "class C {" + + " Integer i=0;" + + " private Integer test() {" + + " return i++;" + + " }" + + " class Inner {" + + " private Integer test() {" + + " return i++;" + + " }" + + " }" + + "}" + ).outdir(expected).run(); + + Path actual = Paths.get("actual"); + Files.createDirectories(actual); + tb.cleanDirectory(actual); + new JavacTask(tb).sources( + "class C {" + + " Integer i=0;" + + " private Integer test() {" + + " return this.i++;" + + " }" + + " class Inner {" + + " private Integer test() {" + + " return C.this.i++;" + + " }" + + " }" + + "}" + ).outdir(actual).run(); + + String error = "", sep = ""; + for (Path p1: tb.findFiles(".class", expected)) { + for (Path p2: tb.findFiles(p1.getFileName().toString(), actual)) { + byte[] b1 = Files.readAllBytes(p1); + byte[] b2 = Files.readAllBytes(p2); + if (!Arrays.equals(b1, b2)) { + error += sep + p1 + " differs from " + p2; + sep = ", "; + } + } + } + if (error.length() > 0) throw new Error(error); + } +} From bsrbnd at gmail.com Sat Nov 12 16:58:08 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Sat, 12 Nov 2016 17:58:08 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: <581B3F95.7060505@oracle.com> References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> Message-ID: Hi, 2016-11-03 14:45 GMT+01:00 Jan Lahoda : > Hi Bernard, > > Thanks for looking at this. For the avoidance of the modification of > tree.selected in Lower.visitSelect, what I meant was more that we would > create a new instance of JCFieldAccess, to carry the new select. Might be > easier that trying to work with the existing select. > > I think it might be useful to have a set of tests covering the usecases, so > that we can more easily test patches (we will need tests eventually anyway). > I can look at that, unless you want to. > Next is a test (derived from issue 8143388 test, too) for the optimization of "super" and "this$n". In this case, the test() method has to be examined instruction by instruction as explained in comments within the test. Bernard diff --git a/test/tools/javac/boxing/BoxedPostOpOpti2.java b/test/tools/javac/boxing/BoxedPostOpOpti2.java new file mode 100644 --- /dev/null +++ b/test/tools/javac/boxing/BoxedPostOpOpti2.java @@ -0,0 +1,114 @@ +/* + * @test + * @bug 8147527 + * @summary "super" and "this$n" code optimization for boxed unary post-operations. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jdeps/com.sun.tools.javap + * jdk.jdeps/com.sun.tools.classfile + * @build toolbox.ToolBox toolbox.JavacTask + * @run main BoxedPostOpOpti2 + */ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; + +import toolbox.JavacTask; +import toolbox.ToolBox; + +import com.sun.tools.classfile.*; + +public class BoxedPostOpOpti2 { + public static void main(String... args) throws Exception { + new BoxedPostOpOpti2().run(); + } + + void run() throws Exception { + ToolBox tb = new ToolBox(); + + Path expected = Paths.get("expected"); + Files.createDirectories(expected); + tb.cleanDirectory(expected); + new JavacTask(tb).sources( + "package p1;" + + "public class P {" + + " protected Integer j=20;" + + "}", + "package p2;" + + "class C extends p1.P {" + + " private Integer test() {" + + " return j++;" + + " }" + + " class Inner {" + + " private Integer test() {" + + " return j++;" + + " }" + + " }" + + "}" + ).outdir(expected).run(); + + Path actual = Paths.get("actual"); + Files.createDirectories(actual); + tb.cleanDirectory(actual); + new JavacTask(tb).sources( + "package p1;" + + "public class P {" + + " protected Integer j=20;" + + "}", + "package p2;" + + "class C extends p1.P {" + + " private Integer test() {" + + " return super.j++;" + + " }" + + " class Inner {" + + " private Integer test() {" + + " return C.super.j++;" + + " }" + + " }" + + "}" + ).outdir(actual).run(); + + String error = "", sep = ""; + for (Path p1: tb.findFiles(".class", expected)) { + for (Path p2: tb.findFiles(p1.getFileName().toString(), actual)) { + ClassFile c1 = ClassFile.read(p1); + ClassFile c2 = ClassFile.read(p2); + Method m1 = test(c1), m2 = test(c2); + + if (m1 != null && m2 != null) { + Code_attribute code1 = (Code_attribute)m1.attributes.get(Attribute.Code); + Code_attribute code2 = (Code_attribute)m2.attributes.get(Attribute.Code); + + Iterator it1 = code1.getInstructions().iterator(); + Iterator it2 = code2.getInstructions().iterator(); + Instruction i1 = it1.next(), i2 = it2.next(); + boolean same = true; + for (; it1.hasNext() && it2.hasNext(); i1=it1.next(), i2=it2.next()) { + // Checks only matching of instruction's opcode since: + // - accessor's name might be different depending on "qualified super" selection. + // - accessed field might be different depending on "super" selection. + same &= i1.getOpcode().opcode == i2.getOpcode().opcode; + } + same &= !it1.hasNext() && !it2.hasNext(); + if (!same) { + error += sep + p1 + " differs from " + p2; + sep = ", "; + } + } + } + } + if (error.length() > 0) throw new Error(error); + } + + Method test(ClassFile c) throws ConstantPoolException { + for (Method m: c.methods) { + if (m.getName(c.constant_pool).equals("test")) + return m; + } + return null; + } +} From bsrbnd at gmail.com Mon Nov 14 10:48:32 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Mon, 14 Nov 2016 11:48:32 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: <581B3F95.7060505@oracle.com> References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> Message-ID: Hi, 2016-11-03 14:45 GMT+01:00 Jan Lahoda : > Hi Bernard, > > Thanks for looking at this. For the avoidance of the modification of > tree.selected in Lower.visitSelect, what I meant was more that we would > create a new instance of JCFieldAccess, to carry the new select. Might be > easier that trying to work with the existing select. > > I think it might be useful to have a set of tests covering the usecases, so > that we can more easily test patches (we will need tests eventually anyway). > I can look at that, unless you want to. > Here is a test that verifies the runtime behavior of the "super", "this" and "this$n" optimization. It failed previous to issue 8143388 changeset and still have to succeed after the optimization. Bernard diff --git a/test/tools/javac/boxing/BoxedPostOpOpti3.java b/test/tools/javac/boxing/BoxedPostOpOpti3.java new file mode 100644 --- /dev/null +++ b/test/tools/javac/boxing/BoxedPostOpOpti3.java @@ -0,0 +1,51 @@ +/* + * @test + * @bug 8147527 + * @summary Verifies the runtime behavior of "super", "this" and "this$n" optimization for boxed unary post-operations. + */ +public class BoxedPostOpOpti3 extends p.Parent { + public static void main(String[] args) { + new BoxedPostOpOpti3().testAll(); + } + + private void testAll() { + equals(test(), 1); + equals(i, 2); + + Inner in = new Inner(); + equals(in.test(), 3); + equals(i, 4); + + equals(testParent(), 21); + equals(super.j, 22); + + equals(in.testParent(), 23); + equals(super.j, 24); + } + + private void equals(int a, int b) { + if (a != b) throw new Error(); + } + + Integer i=0; + + private Integer test() { + i++; + return this.i++; + } + private Integer testParent() { + j++; + return super.j++; + } + + class Inner { + private Integer test() { + i++; + return BoxedPostOpOpti3.this.i++; + } + private Integer testParent() { + j++; + return BoxedPostOpOpti3.super.j++; + } + } +} diff --git a/test/tools/javac/boxing/p/Parent.java b/test/tools/javac/boxing/p/Parent.java new file mode 100644 --- /dev/null +++ b/test/tools/javac/boxing/p/Parent.java @@ -0,0 +1,5 @@ +package p; + +public class Parent { + protected Integer j=20; +} From bsrbnd at gmail.com Tue Nov 15 12:11:01 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Tue, 15 Nov 2016 13:11:01 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> Message-ID: Hi, 2016-11-07 22:48 GMT+01:00 bsrbnd : > Hi, > > Another solution would be to clone the nodes as the unary boxed > operation is expanded. > This way, there is no reused tree at all and Lower.visitSelect() has > no need to be modified. > It's probably the easiest solution which is also the one that makes > most sense (I think). > Below is a fix including the optimization. > Of course, a deep copy of the tree would be a conceptually better solution but more dangerous for a simple fix. Unfortunately, "TreeCopier" loses some information like symbols, etc... For this reason, I wrote a new class "TreeCloner" extending "TreeCopier" which performs a full cloning of the nodes while copying the tree. I've only implemented the necessary methods required by this issue, as shown in the following patch (all javac tests have been run). What do you think of all these solutions? Thanks, Bernard diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2218,7 +2218,7 @@ return builder.build(rval); } Name name = TreeInfo.name(rval); - if (name == names._super) + if (name == names._super || name == names._this) return builder.build(rval); VarSymbol var = new VarSymbol(FINAL|SYNTHETIC, @@ -3205,7 +3205,7 @@ newTag, tree.type, tree.rhs.type); - JCExpression expr = lhs; + JCExpression expr = new TreeCloner(make).copy(lhs); if (expr.type != tree.type) expr = make.TypeCast(tree.type, expr); JCBinary opResult = make.Binary(newTag, expr, tree.rhs); @@ -3292,7 +3292,7 @@ ? make.TypeCast(tree.arg.type, tmp1) : tmp1; JCExpression update = makeAssignop(opcode, - lhs, + new TreeCloner(make).copy(lhs), make.Literal(1)); return makeComma(update, tmp2); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCloner.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCloner.java new file mode 100644 --- /dev/null +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCloner.java @@ -0,0 +1,45 @@ +package com.sun.tools.javac.tree; + +import com.sun.source.tree.*; +import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.util.DefinedBy; +import com.sun.tools.javac.util.DefinedBy.Api; + +public class TreeCloner extends TreeCopier { + public TreeCloner(TreeMaker M) { + super(M); + } + + @DefinedBy(Api.COMPILER_TREE) + public JCTree visitIdentifier(IdentifierTree node, Void p) { + return (JCIdent)((JCIdent)node).clone(); + } + + @DefinedBy(Api.COMPILER_TREE) + public JCTree visitMemberSelect(MemberSelectTree node, Void p) { + JCFieldAccess t = (JCFieldAccess)((JCFieldAccess)node).clone(); + t.selected = copy(t.selected, p); + return t; + } + + @DefinedBy(Api.COMPILER_TREE) + public JCTree visitTypeCast(TypeCastTree node, Void p) { + JCTypeCast t = (JCTypeCast)((JCTypeCast)node).clone(); + t.clazz = copy(t.clazz, p); + t.expr = copy(t.expr, p); + return t; + } + + @DefinedBy(Api.COMPILER_TREE) + public JCTree visitArrayAccess(ArrayAccessTree node, Void p) { + JCArrayAccess t = (JCArrayAccess)((JCArrayAccess)node).clone(); + t.indexed = copy(t.indexed, p); + t.index = copy(t.index, p); + return t; + } + + @DefinedBy(Api.COMPILER_TREE) + public JCTree visitLiteral(LiteralTree node, Void p) { + return (JCLiteral)((JCLiteral)node).clone(); + } +} From jan.lahoda at oracle.com Tue Nov 15 15:59:09 2016 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Tue, 15 Nov 2016 16:59:09 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> Message-ID: <582B30CD.1070905@oracle.com> Hi Bernard, Sorry for delayed answer. I don't think there's a precedent in the current code in using JCTree.clone(), but I quite like it. I incline to think the shallow clones fit the needs here. I am attaching a patch that includes your patch, the original test broken by JDK-8143388 and a test that I tried to write to verify the desugaring (checks the trees after Lower). I'd like to go through the other tests to see which should be added, do some more testing (in particular the code in lowerBoxedPostop seems a little bit suspicious, as the newly-created type cast may be cloned) and send a request for review. Please let me know if there are some tests that should definitely be included, or if you'd have any other comments. Thank you for your work on this, Jan On 15.11.2016 13:11, bsrbnd wrote: > Hi, > > 2016-11-07 22:48 GMT+01:00 bsrbnd : >> Hi, >> >> Another solution would be to clone the nodes as the unary boxed >> operation is expanded. >> This way, there is no reused tree at all and Lower.visitSelect() has >> no need to be modified. >> It's probably the easiest solution which is also the one that makes >> most sense (I think). >> Below is a fix including the optimization. >> > Of course, a deep copy of the tree would be a conceptually better > solution but more dangerous for a simple fix. > Unfortunately, "TreeCopier" loses some information like symbols, etc... > For this reason, I wrote a new class "TreeCloner" extending > "TreeCopier" which performs a full cloning of the nodes while copying > the tree. > I've only implemented the necessary methods required by this issue, as > shown in the following patch (all javac tests have been run). > What do you think of all these solutions? > > Thanks, > Bernard > > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > @@ -2218,7 +2218,7 @@ > return builder.build(rval); > } > Name name = TreeInfo.name(rval); > - if (name == names._super) > + if (name == names._super || name == names._this) > return builder.build(rval); > VarSymbol var = > new VarSymbol(FINAL|SYNTHETIC, > @@ -3205,7 +3205,7 @@ > newTag, > > tree.type, > > tree.rhs.type); > - JCExpression expr = lhs; > + JCExpression expr = new TreeCloner(make).copy(lhs); > if (expr.type != tree.type) > expr = make.TypeCast(tree.type, expr); > JCBinary opResult = make.Binary(newTag, expr, > tree.rhs); > @@ -3292,7 +3292,7 @@ > ? make.TypeCast(tree.arg.type, tmp1) > : tmp1; > JCExpression update = makeAssignop(opcode, > - lhs, > + new > TreeCloner(make).copy(lhs), > make.Literal(1)); > return makeComma(update, tmp2); > } > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCloner.java > b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCloner.java > new file mode 100644 > --- /dev/null > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCloner.java > @@ -0,0 +1,45 @@ > +package com.sun.tools.javac.tree; > + > +import com.sun.source.tree.*; > +import com.sun.tools.javac.tree.JCTree.*; > +import com.sun.tools.javac.util.DefinedBy; > +import com.sun.tools.javac.util.DefinedBy.Api; > + > +public class TreeCloner extends TreeCopier { > + public TreeCloner(TreeMaker M) { > + super(M); > + } > + > + @DefinedBy(Api.COMPILER_TREE) > + public JCTree visitIdentifier(IdentifierTree node, Void p) { > + return (JCIdent)((JCIdent)node).clone(); > + } > + > + @DefinedBy(Api.COMPILER_TREE) > + public JCTree visitMemberSelect(MemberSelectTree node, Void p) { > + JCFieldAccess t = (JCFieldAccess)((JCFieldAccess)node).clone(); > + t.selected = copy(t.selected, p); > + return t; > + } > + > + @DefinedBy(Api.COMPILER_TREE) > + public JCTree visitTypeCast(TypeCastTree node, Void p) { > + JCTypeCast t = (JCTypeCast)((JCTypeCast)node).clone(); > + t.clazz = copy(t.clazz, p); > + t.expr = copy(t.expr, p); > + return t; > + } > + > + @DefinedBy(Api.COMPILER_TREE) > + public JCTree visitArrayAccess(ArrayAccessTree node, Void p) { > + JCArrayAccess t = (JCArrayAccess)((JCArrayAccess)node).clone(); > + t.indexed = copy(t.indexed, p); > + t.index = copy(t.index, p); > + return t; > + } > + > + @DefinedBy(Api.COMPILER_TREE) > + public JCTree visitLiteral(LiteralTree node, Void p) { > + return (JCLiteral)((JCLiteral)node).clone(); > + } > +} > -------------- next part -------------- # HG changeset patch # Parent 07ca23d6190c74e256be5874b9f865b456c48aba diff -r 07ca23d6190c src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Mon Nov 14 08:28:18 2016 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Mon Nov 14 11:24:23 2016 +0100 @@ -2218,7 +2218,7 @@ return builder.build(rval); } Name name = TreeInfo.name(rval); - if (name == names._super) + if (name == names._super || name == names._this) return builder.build(rval); VarSymbol var = new VarSymbol(FINAL|SYNTHETIC, @@ -3205,7 +3205,7 @@ newTag, tree.type, tree.rhs.type); - JCExpression expr = lhs; + JCExpression expr = (JCExpression) lhs.clone(); if (expr.type != tree.type) expr = make.TypeCast(tree.type, expr); JCBinary opResult = make.Binary(newTag, expr, tree.rhs); @@ -3292,7 +3292,7 @@ ? make.TypeCast(tree.arg.type, tmp1) : tmp1; JCExpression update = makeAssignop(opcode, - lhs, + (JCExpression) lhs.clone(), make.Literal(1)); return makeComma(update, tmp2); } diff -r 07ca23d6190c test/tools/javac/boxing/QualBoxedPostOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/boxing/QualBoxedPostOp.java Mon Nov 14 11:24:23 2016 +0100 @@ -0,0 +1,51 @@ +/* + * @test + * @bug 8147527 + * @summary Qualified "this" and "super" boxed unary post operations. + */ +public class QualBoxedPostOp extends Parent { + public static void main(String[] args) { + new QualBoxedPostOp().testAll(); + } + + private void testAll() { + equals(test(), 0); + equals(i, 1); + + Inner in = new Inner(); + equals(in.test(), 1); + equals(i, 2); + + equals(testParent(), 10); + equals(super.i, 11); + + equals(in.testParent(), 11); + equals(super.i, 12); + } + + private void equals(int a, int b) { + if (a != b) throw new Error(); + } + + Integer i=0; + + private Integer test() { + return this.i++; + } + private Integer testParent() { + return super.i++; + } + + class Inner { + private Integer test() { + return QualBoxedPostOp.this.i++; + } + private Integer testParent() { + return QualBoxedPostOp.super.i++; + } + } +} + +class Parent { + protected Integer i=10; +} diff -r 07ca23d6190c test/tools/javac/desugar/BoxingAndSuper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/desugar/BoxingAndSuper.java Mon Nov 14 11:24:23 2016 +0100 @@ -0,0 +1,282 @@ +/** + * @test + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.code + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + */ + + +import java.io.IOException; +import java.io.StringWriter; +import java.net.URI; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; + +import javax.tools.JavaCompiler; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import com.sun.source.tree.IdentifierTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskEvent.Kind; +import com.sun.source.util.TaskListener; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.comp.Lower; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCBlock; +import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCFieldAccess; +import com.sun.tools.javac.tree.JCTree.JCIdent; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; +import com.sun.tools.javac.tree.JCTree.JCModifiers; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.JCTree.LetExpr; +import com.sun.tools.javac.tree.JCTree.Tag; +import com.sun.tools.javac.tree.TreeCopier; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.Log.WriterKind; +import com.sun.tools.javac.util.Names; + +public class BoxingAndSuper { + public static void main(String... args) throws Exception { + new BoxingAndSuper().testSuper(); + new BoxingAndSuper().testThis(); + } + + public void testSuper() throws Exception { + String code = "class Test extends Parent {\n" + + " protected Integer i=20;\n" + + " class Inner {\n" + + " private Integer dump() {\n" + + " return Test.super.i++;\n" + + " }\n" + + " }\n" + + "}\n" + + "class Parent {\n" + + " protected Integer i=10;\n" + + "} "; + String expected = + "Test.Inner.dump()java.lang.Integer\n" + + "{\n" + + " return (let /*synthetic*/ final Integer $le0 = (Integer)Test.access$001(this$0) " + + "in (let /*synthetic*/ final Integer $le1 = Test.access$103(this$0, Integer.valueOf((int)(Test.access$201(this$0).intValue() + 1))) " + + "in $le0));\n" + + "}\n" + + "Test.access$001(Test)java.lang.Integer\n" + + "{\n" + + " return x0.i;\n" + + "}\n" + + "Test.access$103(Test,java.lang.Integer)java.lang.Integer\n" + + "{\n" + + " return x0.i = x1;\n" + + "}\n" + + "Test.access$201(Test)java.lang.Integer\n" + + "{\n" + + " return x0.i;\n" + + "}\n"; + runTest(code, expected); + } + + public void testThis() throws Exception { + String code = "public class Test {\n" + + " Integer i;\n" + + " private void dump() {\n" + + " i++;\n" + + " this.i++;\n" + + " }\n" + + "}"; + String expected = + "Test.dump()void\n" + + "{\n" + + " (let /*synthetic*/ final Integer $le0 = i in (let /*synthetic*/ final Integer $le1 = i = Integer.valueOf((int)(i.intValue() + 1)) in $le0));\n" + + " (let /*synthetic*/ final Integer $le2 = (Integer)this.i in (let /*synthetic*/ final Integer $le3 = this.i = Integer.valueOf((int)(this.i.intValue() + 1)) in $le2));\n" + + "}\n"; + runTest(code, expected); + } + + private void runTest(String code, String expectedDesugar) throws Exception { + JavacTool compiler = (JavacTool) ToolProvider.getSystemJavaCompiler(); + StringWriter out = new StringWriter(); + Context context = new Context(); + TestLower.preRegister(context); + JavacTask task = (JavacTask) compiler.getTask(out, null, null, Arrays.asList("-d", "."), null, Arrays.asList(new JFOImpl(new URI("mem:///Test.java"), code)), context); + + task.generate(); + + out.flush(); + + String actual = out.toString(); + + if (!expectedDesugar.equals(actual)) { + throw new IllegalStateException("Actual does not match expected: " + actual); + } + } + + private static final class TestLower extends Lower { + + public static void preRegister(Context context) { + context.put(lowerKey, new Context.Factory() { + public Lower make(Context c) { + return new TestLower(c); + } + }); + } + + private final TreeMaker make; + private final Names names; + private final Log log; + + public TestLower(Context context) { + super(context); + make = TreeMaker.instance(context); + names = Names.instance(context); + log = Log.instance(context); + } + + @Override + public List translateTopLevelClass(Env env, JCTree cdef, TreeMaker make) { + List result = super.translateTopLevelClass(env, cdef, make); + Map declarations = new HashMap<>(); + Set toDump = new TreeSet<>(symbolComparator); + + new TreeScanner() { + @Override + public void visitMethodDef(JCMethodDecl tree) { + if (tree.name.toString().startsWith("dump")) { + toDump.add(tree.sym); + } + declarations.put(tree.sym, tree); + super.visitMethodDef(tree); + } + }.scan(result); + + for (Symbol d : toDump) { + dump(d, declarations, new HashSet<>()); + } + + return result; + } + + private void dump(Symbol methodSym, Map declarations, Set alreadyPrinted) { + if (!alreadyPrinted.add(methodSym)) + return ; + + JCMethodDecl method = declarations.get(methodSym); + + if (method == null) { + return ; + } + + log.getWriter(WriterKind.NOTICE).println(symbol2String(methodSym)); + + JCBlock body = new TreeCopier(make) { + private final Map letExprRemap = new HashMap<>(); + private int i; + + @Override + public JCTree visitOther(Tree node, Void p) { + JCTree tree = (JCTree) node; + if (tree.hasTag(Tag.LETEXPR)) { + LetExpr le = (LetExpr) tree; + + for (JCVariableDecl var : le.defs) { + letExprRemap.put(var.name.toString(), "$le" + i++); + } + } + return super.visitOther(node, p); + } + + @Override + public JCTree visitVariable(VariableTree node, Void p) { + String newName = letExprRemap.get(node.getName().toString()); + if (newName != null) { + node = make.VarDef((JCModifiers) node.getModifiers(), names.fromString(newName), (JCExpression) node.getType(), (JCExpression) node.getInitializer()); + } + return super.visitVariable(node, p); + } + + @Override + public JCTree visitIdentifier(IdentifierTree node, Void p) { + String newName = letExprRemap.get(node.getName().toString()); + if (newName != null) { + node = make.Ident(names.fromString(newName)); + } + return super.visitIdentifier(node, p); + } + + @Override + public T copy(T tree, Void p) { + if (tree.hasTag(Tag.LETEXPR)) { + return (T) visitOther(tree, p); + } + return super.copy(tree, p); + } + + }.copy(method.body); + log.getWriter(WriterKind.NOTICE).println(body.toString()); + + Set invoked = new TreeSet<>(symbolComparator); + + new TreeScanner() { + @Override + public void visitApply(JCMethodInvocation tree) { + invoked.add(TreeInfo.symbol(tree.meth)); + super.visitApply(tree); + } + }.scan(method); + + for (Symbol search : invoked) { + dump(search, declarations, alreadyPrinted); + } + } + + private String symbol2String(Symbol sym) { + switch (sym.kind) { + case TYP: + return sym.getQualifiedName().toString(); + case MTH: + return symbol2String(sym.owner) + "." + sym.name + sym.type.toString(); + default: + throw new UnsupportedOperationException(); + } + } + + private final Comparator symbolComparator = (s1, s2) -> symbol2String(s1).compareTo(symbol2String(s2)); + } + + private static final class JFOImpl extends SimpleJavaFileObject { + + private final String code; + + public JFOImpl(URI uri, String code) { + super(uri, Kind.SOURCE); + this.code = code; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return code; + } + + } +} \ No newline at end of file From ogierke at pivotal.io Tue Nov 15 23:46:02 2016 From: ogierke at pivotal.io (Oliver Gierke) Date: Wed, 16 Nov 2016 00:46:02 +0100 Subject: Java 8 compiler bug? Message-ID: Hi all, I just ran in this code compiling fine with a JDK 8 if I define a compilation source and target of 1.6, but not if I define both values of 1.8. public class Ambiguity { public void foo(CriteriaBuilder builder) { Expression objectExpression = null; Expression> collectionOfObjectExpression = null; builder.isNotMember(objectExpression, collectionOfObjectExpression); // ^^^^^^^^^^^ - ambiguous } } CriteriaBuilder and all other types come from JPA. The method in question has two overloads: > Predicate isNotMember(Expression elem, Expression collection); > Predicate isNotMember(E elem, Expression collection); I fail to understand why the second method is even considered as that create a contradiction between the bound values of E (Expression) and C (Collection). I've prepared an example here [0]. Steps to reproduce: 1. Unzip 2. Run mvn clean compile -> fails 3. Change java.version property in pom.xml to 1.6 4. Run mvn clean compile -> succeeds $ java -version java version "1.8.0_112" Java(TM) SE Runtime Environment (build 1.8.0_112-b16) Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode) Is that a known issue, something I oversee or should I create a ticket for that? Cheers, Ollie -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 841 bytes Desc: Message signed with OpenPGP using GPGMail URL: From ogierke at pivotal.io Tue Nov 15 23:49:16 2016 From: ogierke at pivotal.io (Oliver Gierke) Date: Wed, 16 Nov 2016 00:49:16 +0100 Subject: Java 8 compiler bug? References: Message-ID: Sorry, I forgot the link to the reproducing example: https://dl.dropboxusercontent.com/u/25310722/compiler-ambiguity.zip > Anfang der weitergeleiteten Nachricht: > > Von: Oliver Gierke > Betreff: Java 8 compiler bug? > Datum: 16. November 2016 um 00:46:02 MEZ > An: compiler-dev at openjdk.java.net > > Hi all, > > I just ran in this code compiling fine with a JDK 8 if I define a compilation source and target of 1.6, but not if I define both values of 1.8. > > public class Ambiguity { > > public void foo(CriteriaBuilder builder) { > > Expression objectExpression = null; > Expression> collectionOfObjectExpression = null; > builder.isNotMember(objectExpression, collectionOfObjectExpression); > // ^^^^^^^^^^^ - ambiguous > } > } > > CriteriaBuilder and all other types come from JPA. The method in question has two overloads: > > > Predicate isNotMember(Expression elem, Expression collection); > > Predicate isNotMember(E elem, Expression collection); > > I fail to understand why the second method is even considered as that create a contradiction between the bound values of E (Expression) and C (Collection). > > I've prepared an example here [0]. Steps to reproduce: > > 1. Unzip > 2. Run mvn clean compile -> fails > 3. Change java.version property in pom.xml to 1.6 > 4. Run mvn clean compile -> succeeds > > $ java -version > java version "1.8.0_112" > Java(TM) SE Runtime Environment (build 1.8.0_112-b16) > Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode) > > Is that a known issue, something I oversee or should I create a ticket for that? > > Cheers, > Ollie > -- /** * @author Oliver Gierke - Senior Software Engineer * * @param email ogierke at pivotal.io * @param phone +49-151-50465477 * @param fax +49-351-418898439 * @param skype einsdreizehn * @see http://www.olivergierke.de */ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 841 bytes Desc: Message signed with OpenPGP using GPGMail URL: From jonathan.gibbons at oracle.com Tue Nov 15 23:54:52 2016 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 15 Nov 2016 15:54:52 -0800 Subject: Java 8 compiler bug? In-Reply-To: References: Message-ID: <582BA04C.5020508@oracle.com> Can you simplify your example down to something that doesn't require us to download a zip file? -- Jon On 11/15/2016 03:49 PM, Oliver Gierke wrote: > Sorry, I forgot the link to the reproducing example: > > https://dl.dropboxusercontent.com/u/25310722/compiler-ambiguity.zip > >> Anfang der weitergeleiteten Nachricht: >> >> Von: Oliver Gierke >> Betreff: Java 8 compiler bug? >> Datum: 16. November 2016 um 00:46:02 MEZ >> An: compiler-dev at openjdk.java.net >> >> Hi all, >> >> I just ran in this code compiling fine with a JDK 8 if I define a compilation source and target of 1.6, but not if I define both values of 1.8. >> >> public class Ambiguity { >> >> public void foo(CriteriaBuilder builder) { >> >> Expression objectExpression = null; >> Expression> collectionOfObjectExpression = null; >> builder.isNotMember(objectExpression, collectionOfObjectExpression); >> // ^^^^^^^^^^^ - ambiguous >> } >> } >> >> CriteriaBuilder and all other types come from JPA. The method in question has two overloads: >> >> > Predicate isNotMember(Expression elem, Expression collection); >> > Predicate isNotMember(E elem, Expression collection); >> >> I fail to understand why the second method is even considered as that create a contradiction between the bound values of E (Expression) and C (Collection). >> >> I've prepared an example here [0]. Steps to reproduce: >> >> 1. Unzip >> 2. Run mvn clean compile -> fails >> 3. Change java.version property in pom.xml to 1.6 >> 4. Run mvn clean compile -> succeeds >> >> $ java -version >> java version "1.8.0_112" >> Java(TM) SE Runtime Environment (build 1.8.0_112-b16) >> Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode) >> >> Is that a known issue, something I oversee or should I create a ticket for that? >> >> Cheers, >> Ollie >> > -- > /** > * @author Oliver Gierke - Senior Software Engineer > * > * @param email ogierke at pivotal.io > * @param phone +49-151-50465477 > * @param fax +49-351-418898439 > * @param skype einsdreizehn > * @see http://www.olivergierke.de > */ > From ogierke at pivotal.io Wed Nov 16 00:32:30 2016 From: ogierke at pivotal.io (Oliver Gierke) Date: Wed, 16 Nov 2016 01:32:30 +0100 Subject: Java 8 compiler bug? In-Reply-To: <582BA04C.5020508@oracle.com> References: <582BA04C.5020508@oracle.com> Message-ID: I wasn't sure whether any specialty of the types involved is causing the issue, that's why I kept the JPA dependency in the first place. But this piece of code shows the same characteristics: public class Ambiguity { public void foo(CriteriaBuilder builder) { Expression objectExpression = null; Expression> collectionOfObjectExpression = null; builder.isNotMember(objectExpression, collectionOfObjectExpression); } interface Expression {} interface CriteriaBuilder { > void isNotMember(E elem, Expression collection); > void isNotMember(Expression elem, Expression collection); } } > Am 16.11.2016 um 00:54 schrieb Jonathan Gibbons : > > Can you simplify your example down to something that doesn't require us to download a zip file? > > -- Jon > > On 11/15/2016 03:49 PM, Oliver Gierke wrote: >> Sorry, I forgot the link to the reproducing example: >> >> https://dl.dropboxusercontent.com/u/25310722/compiler-ambiguity.zip >> >>> Anfang der weitergeleiteten Nachricht: >>> >>> Von: Oliver Gierke >>> Betreff: Java 8 compiler bug? >>> Datum: 16. November 2016 um 00:46:02 MEZ >>> An: compiler-dev at openjdk.java.net >>> >>> Hi all, >>> >>> I just ran in this code compiling fine with a JDK 8 if I define a compilation source and target of 1.6, but not if I define both values of 1.8. >>> >>> public class Ambiguity { >>> >>> public void foo(CriteriaBuilder builder) { >>> >>> Expression objectExpression = null; >>> Expression> collectionOfObjectExpression = null; >>> builder.isNotMember(objectExpression, collectionOfObjectExpression); >>> // ^^^^^^^^^^^ - ambiguous >>> } >>> } >>> >>> CriteriaBuilder and all other types come from JPA. The method in question has two overloads: >>> >>> > Predicate isNotMember(Expression elem, Expression collection); >>> > Predicate isNotMember(E elem, Expression collection); >>> >>> I fail to understand why the second method is even considered as that create a contradiction between the bound values of E (Expression) and C (Collection). >>> >>> I've prepared an example here [0]. Steps to reproduce: >>> >>> 1. Unzip >>> 2. Run mvn clean compile -> fails >>> 3. Change java.version property in pom.xml to 1.6 >>> 4. Run mvn clean compile -> succeeds >>> >>> $ java -version >>> java version "1.8.0_112" >>> Java(TM) SE Runtime Environment (build 1.8.0_112-b16) >>> Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode) >>> >>> Is that a known issue, something I oversee or should I create a ticket for that? >>> >>> Cheers, >>> Ollie >>> >> -- >> /** >> * @author Oliver Gierke - Senior Software Engineer >> * >> * @param email ogierke at pivotal.io >> * @param phone +49-151-50465477 >> * @param fax +49-351-418898439 >> * @param skype einsdreizehn >> * @see http://www.olivergierke.de >> */ >> > -- /** * @author Oliver Gierke - Senior Software Engineer * * @param email ogierke at pivotal.io * @param phone +49-151-50465477 * @param fax +49-351-418898439 * @param skype einsdreizehn * @see http://www.olivergierke.de */ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 841 bytes Desc: Message signed with OpenPGP using GPGMail URL: From jonathan.gibbons at oracle.com Wed Nov 16 00:45:56 2016 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Tue, 15 Nov 2016 16:45:56 -0800 Subject: Java 8 compiler bug? In-Reply-To: References: <582BA04C.5020508@oracle.com> Message-ID: <582BAC44.2060400@oracle.com> Thanks for the reduced test case. -- Jon On 11/15/2016 04:32 PM, Oliver Gierke wrote: > I wasn't sure whether any specialty of the types involved is causing the issue, that's why I kept the JPA dependency in the first place. But this piece of code shows the same characteristics: > > public class Ambiguity { > > public void foo(CriteriaBuilder builder) { > > Expression objectExpression = null; > Expression> collectionOfObjectExpression = null; > builder.isNotMember(objectExpression, collectionOfObjectExpression); > } > > interface Expression {} > > interface CriteriaBuilder { > > > void isNotMember(E elem, Expression collection); > > > void isNotMember(Expression elem, Expression collection); > } > } > >> Am 16.11.2016 um 00:54 schrieb Jonathan Gibbons : >> >> Can you simplify your example down to something that doesn't require us to download a zip file? >> >> -- Jon >> >> On 11/15/2016 03:49 PM, Oliver Gierke wrote: >>> Sorry, I forgot the link to the reproducing example: >>> >>> https://dl.dropboxusercontent.com/u/25310722/compiler-ambiguity.zip >>> >>>> Anfang der weitergeleiteten Nachricht: >>>> >>>> Von: Oliver Gierke >>>> Betreff: Java 8 compiler bug? >>>> Datum: 16. November 2016 um 00:46:02 MEZ >>>> An: compiler-dev at openjdk.java.net >>>> >>>> Hi all, >>>> >>>> I just ran in this code compiling fine with a JDK 8 if I define a compilation source and target of 1.6, but not if I define both values of 1.8. >>>> >>>> public class Ambiguity { >>>> >>>> public void foo(CriteriaBuilder builder) { >>>> >>>> Expression objectExpression = null; >>>> Expression> collectionOfObjectExpression = null; >>>> builder.isNotMember(objectExpression, collectionOfObjectExpression); >>>> // ^^^^^^^^^^^ - ambiguous >>>> } >>>> } >>>> >>>> CriteriaBuilder and all other types come from JPA. The method in question has two overloads: >>>> >>>> > Predicate isNotMember(Expression elem, Expression collection); >>>> > Predicate isNotMember(E elem, Expression collection); >>>> >>>> I fail to understand why the second method is even considered as that create a contradiction between the bound values of E (Expression) and C (Collection). >>>> >>>> I've prepared an example here [0]. Steps to reproduce: >>>> >>>> 1. Unzip >>>> 2. Run mvn clean compile -> fails >>>> 3. Change java.version property in pom.xml to 1.6 >>>> 4. Run mvn clean compile -> succeeds >>>> >>>> $ java -version >>>> java version "1.8.0_112" >>>> Java(TM) SE Runtime Environment (build 1.8.0_112-b16) >>>> Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode) >>>> >>>> Is that a known issue, something I oversee or should I create a ticket for that? >>>> >>>> Cheers, >>>> Ollie >>>> >>> -- >>> /** >>> * @author Oliver Gierke - Senior Software Engineer >>> * >>> * @param email ogierke at pivotal.io >>> * @param phone +49-151-50465477 >>> * @param fax +49-351-418898439 >>> * @param skype einsdreizehn >>> * @see http://www.olivergierke.de >>> */ >>> > -- > /** > * @author Oliver Gierke - Senior Software Engineer > * > * @param email ogierke at pivotal.io > * @param phone +49-151-50465477 > * @param fax +49-351-418898439 > * @param skype einsdreizehn > * @see http://www.olivergierke.de > */ > From ogierke at pivotal.io Wed Nov 16 08:54:15 2016 From: ogierke at pivotal.io (Oliver Gierke) Date: Wed, 16 Nov 2016 09:54:15 +0100 Subject: Java 8 compiler bug? In-Reply-To: <582BAC44.2060400@oracle.com> References: <582BA04C.5020508@oracle.com> <582BAC44.2060400@oracle.com> Message-ID: I've just found myself running into another (but apparently similar issue), again using types from JPA. Here's a Gist example: public class Ambiguity { // JPA replica types interface Attribute {} interface PluralAttribute extends Attribute {} interface SetAttribute extends PluralAttribute, S> {} // User code static , T, S> void path(A attribute) {} static

, T, S> void path(P attribute) {} // Call creating ambiguity with source/target 1.8, compiling fine with source/target 1.6 public void bar(SetAttribute attribute) { path(attribute); } } > Am 16.11.2016 um 01:45 schrieb Jonathan Gibbons : > > Thanks for the reduced test case. > > -- Jon > > On 11/15/2016 04:32 PM, Oliver Gierke wrote: >> I wasn't sure whether any specialty of the types involved is causing the issue, that's why I kept the JPA dependency in the first place. But this piece of code shows the same characteristics: >> >> public class Ambiguity { >> >> public void foo(CriteriaBuilder builder) { >> >> Expression objectExpression = null; >> Expression> collectionOfObjectExpression = null; >> builder.isNotMember(objectExpression, collectionOfObjectExpression); >> } >> >> interface Expression {} >> >> interface CriteriaBuilder { >> >> > void isNotMember(E elem, Expression collection); >> >> > void isNotMember(Expression elem, Expression collection); >> } >> } >> >>> Am 16.11.2016 um 00:54 schrieb Jonathan Gibbons : >>> >>> Can you simplify your example down to something that doesn't require us to download a zip file? >>> >>> -- Jon >>> >>> On 11/15/2016 03:49 PM, Oliver Gierke wrote: >>>> Sorry, I forgot the link to the reproducing example: >>>> >>>> https://dl.dropboxusercontent.com/u/25310722/compiler-ambiguity.zip >>>> >>>>> Anfang der weitergeleiteten Nachricht: >>>>> >>>>> Von: Oliver Gierke >>>>> Betreff: Java 8 compiler bug? >>>>> Datum: 16. November 2016 um 00:46:02 MEZ >>>>> An: compiler-dev at openjdk.java.net >>>>> >>>>> Hi all, >>>>> >>>>> I just ran in this code compiling fine with a JDK 8 if I define a compilation source and target of 1.6, but not if I define both values of 1.8. >>>>> >>>>> public class Ambiguity { >>>>> >>>>> public void foo(CriteriaBuilder builder) { >>>>> >>>>> Expression objectExpression = null; >>>>> Expression> collectionOfObjectExpression = null; >>>>> builder.isNotMember(objectExpression, collectionOfObjectExpression); >>>>> // ^^^^^^^^^^^ - ambiguous >>>>> } >>>>> } >>>>> >>>>> CriteriaBuilder and all other types come from JPA. The method in question has two overloads: >>>>> >>>>> > Predicate isNotMember(Expression elem, Expression collection); >>>>> > Predicate isNotMember(E elem, Expression collection); >>>>> >>>>> I fail to understand why the second method is even considered as that create a contradiction between the bound values of E (Expression) and C (Collection). >>>>> >>>>> I've prepared an example here [0]. Steps to reproduce: >>>>> >>>>> 1. Unzip >>>>> 2. Run mvn clean compile -> fails >>>>> 3. Change java.version property in pom.xml to 1.6 >>>>> 4. Run mvn clean compile -> succeeds >>>>> >>>>> $ java -version >>>>> java version "1.8.0_112" >>>>> Java(TM) SE Runtime Environment (build 1.8.0_112-b16) >>>>> Java HotSpot(TM) 64-Bit Server VM (build 25.112-b16, mixed mode) >>>>> >>>>> Is that a known issue, something I oversee or should I create a ticket for that? >>>>> >>>>> Cheers, >>>>> Ollie >>>>> >>>> -- >>>> /** >>>> * @author Oliver Gierke - Senior Software Engineer >>>> * >>>> * @param email ogierke at pivotal.io >>>> * @param phone +49-151-50465477 >>>> * @param fax +49-351-418898439 >>>> * @param skype einsdreizehn >>>> * @see http://www.olivergierke.de >>>> */ >>>> >> -- >> /** >> * @author Oliver Gierke - Senior Software Engineer >> * >> * @param email ogierke at pivotal.io >> * @param phone +49-151-50465477 >> * @param fax +49-351-418898439 >> * @param skype einsdreizehn >> * @see http://www.olivergierke.de >> */ >> > -- /** * @author Oliver Gierke - Senior Software Engineer * * @param email ogierke at pivotal.io * @param phone +49-151-50465477 * @param fax +49-351-418898439 * @param skype einsdreizehn * @see http://www.olivergierke.de */ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 841 bytes Desc: Message signed with OpenPGP using GPGMail URL: From bsrbnd at gmail.com Wed Nov 16 10:18:10 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Wed, 16 Nov 2016 11:18:10 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: <582B30CD.1070905@oracle.com> References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> <582B30CD.1070905@oracle.com> Message-ID: Hi Jan, 2016-11-15 16:59 GMT+01:00 Jan Lahoda : > Hi Bernard, > > Sorry for delayed answer. > > I don't think there's a precedent in the current code in using > JCTree.clone(), but I quite like it. I incline to think the shallow clones > fit the needs here. > > I am attaching a patch that includes your patch, the original test broken by > JDK-8143388 and a test that I tried to write to verify the desugaring > (checks the trees after Lower). I'd like to go through the other tests to > see which should be added, do some more testing (in particular the code in > lowerBoxedPostop seems a little bit suspicious, as the newly-created type > cast may be cloned) and send a request for review. When I wrote this patch, I was more thinking of making a deep copy of the tree. But I realized that a shallow copy could be enough in our situation and would be a safer fix. In such a configuration, cloning only a type-cast doesn't make any sense, of course. The updated fix below is probably better even if this has no impact in our precise example. > Please let me know if > there are some tests that should definitely be included, or if you'd have > any other comments. "BoxedPostOpOpti" and "BoxedPostOpOpti2" verify the optimization of the generated code by comparing it with what's generated for "i++". I've thought of specifying explicitly the expected generated code, instead; but I thought it was too precise as it might perhaps change in the future. Thus, your solution of comparing the desugared code is probably better. Another difference is that you put "Parent" in the same package while I put it in another one as it was the subject of issue 8143388 (but this isn't really important for the optimization, I think). "BoxedPostOpOpti" tests also the optimization of "C.this.i++" which implies the correct handling of "this$0" without generating any accessor. "BoxedPostOpOpti2" verifies also the optimization of "super.j++" (with "P" in a separate package) which was done by issue 8143388 changset. "BoxedPostOpOpti3" checks the runtime behavior of issue 8143388 changset as the associated test verifies only the success of the compilation. This isn't absolutely necessary since the problem was not at runtime, but I thought it was safer to do so. > Thank you for your work on this, > Jan > Thank you, too. Bernard diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2218,7 +2218,7 @@ return builder.build(rval); } Name name = TreeInfo.name(rval); - if (name == names._super) + if (name == names._super || name == names._this) return builder.build(rval); VarSymbol var = new VarSymbol(FINAL|SYNTHETIC, @@ -3205,7 +3205,7 @@ newTag, tree.type, tree.rhs.type); - JCExpression expr = lhs; + JCExpression expr = (JCExpression)lhs.clone(); if (expr.type != tree.type) expr = make.TypeCast(tree.type, expr); JCBinary opResult = make.Binary(newTag, expr, tree.rhs); @@ -3288,9 +3288,10 @@ public JCExpression build(final JCExpression tmp2) { JCTree.Tag opcode = (tree.hasTag(POSTINC)) ? PLUS_ASG : MINUS_ASG; - JCTree lhs = cast - ? make.TypeCast(tree.arg.type, tmp1) - : tmp1; + JCExpression lhs = (JCExpression)tmp1.clone(); + lhs = cast + ? make.TypeCast(tree.arg.type, lhs) + : lhs; JCExpression update = makeAssignop(opcode, lhs, make.Literal(1)); From maurizio.cimadamore at oracle.com Thu Nov 17 12:44:00 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 17 Nov 2016 12:44:00 +0000 Subject: Java 8 compiler bug? In-Reply-To: References: Message-ID: On 15/11/16 23:46, Oliver Gierke wrote: > CriteriaBuilder and all other types come from JPA. The method in question has two overloads: > > > Predicate isNotMember(Expression elem, Expression collection); > > Predicate isNotMember(E elem, Expression collection); > > I fail to understand why the second method is even considered as that create a contradiction between the bound values of E (Expression) and C (Collection). Hi Oliver, I believe the JDK 8 behavior is correct here - let's just consider your second method - which is the one you have doubts about: > Predicate isNotMember(E elem, Expression collection); Now, you want to pass the following actual argument types to this method: arg1 = Expression arg2 = Expression> So, let's look at which constraints these argument cause trigger on our inference variables E and C. So, since Expression must be compatible with E - we have that Expression <: E Then, since also Expression> must be compatible with Expression we have that: Expression> <: C We also have another source of constraint - namely the declared bound: C <: Collection Now, from these constraints, (and this is the step that is new in Java 8 and newer), we can do _incorporation_ meaning we can derive more constraints by looking at useful patterns. There's one notable pattern here: Expression> <: C C <: Collection By transitivity, this should imply that: Expression> <: Collection which would then derive an additional constraint: E = Object. So, what you end up inferring is E = Object and C = Collection, and this inference is possible thanks to the transitivity treatment that is guaranteed by the incorporation step that is new in the Java 8 specifications (see section 18.3). Java 7 did not do anything special to enforce transitivity (which often result in far less precise inference results and spurious errors) - that meant that the only constraints the compiler had in 7 were: Expression <: E C <: Collection From which you infer E = Expression and C = Collection which is an answer incompatible with declared bounds - so Java 7 was able to discard your second method as not applicable. But it was doing so only because the Java 7 inference machinery was not able to find an answer to the inference problem. Maurizio From ogierke at pivotal.io Thu Nov 17 13:56:15 2016 From: ogierke at pivotal.io (Oliver Gierke) Date: Thu, 17 Nov 2016 14:56:15 +0100 Subject: Java 8 compiler bug? In-Reply-To: References: Message-ID: <044FA0F6-E362-45F3-AE13-8209FDBDBD49@pivotal.io> Hi Maurizio, answer inline? > Am 17.11.2016 um 13:44 schrieb Maurizio Cimadamore : > > On 15/11/16 23:46, Oliver Gierke wrote: >> CriteriaBuilder and all other types come from JPA. The method in question has two overloads: >> >> > Predicate isNotMember(Expression elem, Expression collection); >> > Predicate isNotMember(E elem, Expression collection); >> >> I fail to understand why the second method is even considered as that create a contradiction between the bound values of E (Expression) and C (Collection). > Hi Oliver, > I believe the JDK 8 behavior is correct here - let's just consider your second method - which is the one you have doubts about: > > > Predicate isNotMember(E elem, Expression collection); > > > Now, you want to pass the following actual argument types to this method: > > arg1 = Expression > arg2 = Expression> > > So, let's look at which constraints these argument cause trigger on our inference variables E and C. > > So, since Expression must be compatible with E - we have that > > Expression <: E > > Then, since also Expression> must be compatible with Expression we have that: > > Expression> <: C Is that correct? If the method parameter takes an Expression and we hand in an Expression>, C should be bound to Collection, not Expression>, right? This basically where my confusion comes from, as that would then render E to evaluate to Object for the second parameter which then contradicts the E derived for the first one, right? Cheers, Ollie -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 841 bytes Desc: Message signed with OpenPGP using GPGMail URL: From maurizio.cimadamore at oracle.com Thu Nov 17 16:12:19 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 17 Nov 2016 16:12:19 +0000 Subject: Java 8 compiler bug? In-Reply-To: <044FA0F6-E362-45F3-AE13-8209FDBDBD49@pivotal.io> References: <044FA0F6-E362-45F3-AE13-8209FDBDBD49@pivotal.io> Message-ID: On 17/11/16 13:56, Oliver Gierke wrote: > Hi Maurizio, > > answer inline? > >> Am 17.11.2016 um 13:44 schrieb Maurizio Cimadamore : >> >> On 15/11/16 23:46, Oliver Gierke wrote: >>> CriteriaBuilder and all other types come from JPA. The method in question has two overloads: >>> >>> > Predicate isNotMember(Expression elem, Expression collection); >>> > Predicate isNotMember(E elem, Expression collection); >>> >>> I fail to understand why the second method is even considered as that create a contradiction between the bound values of E (Expression) and C (Collection). >> Hi Oliver, >> I believe the JDK 8 behavior is correct here - let's just consider your second method - which is the one you have doubts about: >> >> > Predicate isNotMember(E elem, Expression collection); >> >> >> Now, you want to pass the following actual argument types to this method: >> >> arg1 = Expression >> arg2 = Expression> >> >> So, let's look at which constraints these argument cause trigger on our inference variables E and C. >> >> So, since Expression must be compatible with E - we have that >> >> Expression <: E >> >> Then, since also Expression> must be compatible with Expression we have that: >> >> Expression> <: C > Is that correct? If the method parameter takes an Expression and we hand in an Expression>, C should be bound to Collection, not Expression>, right? > > This basically where my confusion comes from, as that would then render E to evaluate to Object for the second parameter which then contradicts the E derived for the first one, right? > > Cheers, > Ollie > Let me reboot, as I made a bit of a mess :-) You have: Expression <: E and Expression> <: Expression The latter constraint produces: C = Collection And then you also have: C <: Collection Then from transitivity you get Collection <: Collection --> E = Object. Note that this answer is correct - as we needed a type for E that was _bigger_ than Expression, and Object is obviously one such type (being Object the biggest possible type). So, while I made a mistake in my derivation, the conclusion is still valid: the treatment of transitivity (new in Java 8) allows this inference to succeed, while the lack of it caused inference to fail in Java 5, 6,7. Maurizio From forax at univ-mlv.fr Thu Nov 17 17:19:51 2016 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 17 Nov 2016 17:19:51 +0000 Subject: Java 8 compiler bug? In-Reply-To: References: <044FA0F6-E362-45F3-AE13-8209FDBDBD49@pivotal.io> Message-ID: I think the main issue is that when the inference fails, the compiler instead of reporting an error continue using Object instead. Remi On November 17, 2016 5:12:19 PM GMT+01:00, Maurizio Cimadamore wrote: > > >On 17/11/16 13:56, Oliver Gierke wrote: >> Hi Maurizio, >> >> answer inline? >> >>> Am 17.11.2016 um 13:44 schrieb Maurizio Cimadamore >: >>> >>> On 15/11/16 23:46, Oliver Gierke wrote: >>>> CriteriaBuilder and all other types come from JPA. The method in >question has two overloads: >>>> >>>> > Predicate isNotMember(Expression >elem, Expression collection); >>>> > Predicate isNotMember(E elem, >Expression collection); >>>> >>>> I fail to understand why the second method is even considered as >that create a contradiction between the bound values of E >(Expression) and C (Collection). >>> Hi Oliver, >>> I believe the JDK 8 behavior is correct here - let's just consider >your second method - which is the one you have doubts about: >>> >>> > Predicate isNotMember(E elem, >Expression collection); >>> >>> >>> Now, you want to pass the following actual argument types to this >method: >>> >>> arg1 = Expression >>> arg2 = Expression> >>> >>> So, let's look at which constraints these argument cause trigger on >our inference variables E and C. >>> >>> So, since Expression must be compatible with E - we have >that >>> >>> Expression <: E >>> >>> Then, since also Expression> must be compatible >with Expression we have that: >>> >>> Expression> <: C >> Is that correct? If the method parameter takes an Expression and >we hand in an Expression>, C should be bound to >Collection, not Expression>, right? >> >> This basically where my confusion comes from, as that would then >render E to evaluate to Object for the second parameter which then >contradicts the E derived for the first one, right? >> >> Cheers, >> Ollie >> >Let me reboot, as I made a bit of a mess :-) > >You have: > >Expression <: E > > >and > >Expression> <: Expression > > > >The latter constraint produces: > >C = Collection > >And then you also have: > >C <: Collection > >Then from transitivity you get > >Collection <: Collection > >--> E = Object. > >Note that this answer is correct - as we needed a type for E that was >_bigger_ than Expression, and Object is obviously one such type > >(being Object the biggest possible type). > >So, while I made a mistake in my derivation, the conclusion is still >valid: the treatment of transitivity (new in Java 8) allows this >inference to succeed, while the lack of it caused inference to fail in >Java 5, 6,7. > >Maurizio -- Sent from my Android device with K-9 Mail. Please excuse my brevity. -------------- next part -------------- An HTML attachment was scrubbed... URL: From maurizio.cimadamore at oracle.com Thu Nov 17 18:16:02 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 17 Nov 2016 18:16:02 +0000 Subject: Java 8 compiler bug? In-Reply-To: References: <044FA0F6-E362-45F3-AE13-8209FDBDBD49@pivotal.io> Message-ID: On 17/11/16 17:19, Remi Forax wrote: > I think the main issue is that when the inference fails, the compiler > instead of reporting an error continue using Object instead. > Where is inference failing in JDK 8? I think the 'problem' here is that the code below: import java.util.*; class Test { void test() { Expression objectExpression = null; Expression> collectionOfObjectExpression = null; m(objectExpression, collectionOfObjectExpression); } interface Expression {} > void m(E elem, Expression collection) { } } succeeds with -source N where N >= 8 and fails otherwise - which is a consequence of Java 8 inference being more powerful. In the original example, the fact that there was an overload, combined with the fact that inference used to fail for one of the overloaded methods meant that the program passed in source N < 8 but fails with ambiguity after 8 because now overload resolution can consider both methods as being applicable. Maurizio > Remi > > > On November 17, 2016 5:12:19 PM GMT+01:00, Maurizio Cimadamore > wrote: > > > On 17/11/16 13:56, Oliver Gierke wrote: > > Hi Maurizio, answer inline? > > Am 17.11.2016 um 13:44 schrieb Maurizio Cimadamore > : On 15/11/16 23:46, > Oliver Gierke wrote: > > CriteriaBuilder and all other types come from JPA. The > method in question has two overloads: Collection> Predicate isNotMember(Expression > elem, Expression collection); Collection> Predicate isNotMember(E elem, > Expression collection); I fai! l to understand why > the second method is even considered as that create a > contradiction between the bound values of E > (Expression) and C (Collection). > > Hi Oliver, I believe the JDK 8 behavior is correct here - > let's just consider your second method - which is the one > you have doubts about: > > Predicate isNotMember(E elem, Expression collection); > Now, you want to pass the following actual argument types > to this method: arg1 = Expression arg2 = > Expression> So, let's look at which > constraints these argument cause trigger on our inference > variables E and C. So, since Expression must be > compatible with E - we have that Expression <: E > Then, since also Expression> must be > compatible with Expression we have that: > Expression> <: C > > Is that correct? If the method parameter takes an > Expression and we hand in an > Expression>, C should be bound to > Collection, not Expression>, right? > This basically where my confusion comes from, as that would > then render E to evaluate to Object for the second parameter > which then contradicts the E derived for the first one, right? > Cheers, Ollie > > > Let me reboot, as I made a bit of a mess :-) > > You have: > > Expression <: E > > > and > > Expression> <: Expression > > > > The latter constraint produces: > > C = Collection > > And then you also have: > > C <: Collection > > Th! > en from > transitivity you get > > Collection <: Collection > > --> E = Object. > > Note that this answer is correct - as we needed a type for E that was > _bigger_ than Expression, and Object is obviously one such type > (being Object the biggest possible type). > > So, while I made a mistake in my derivation, the conclusion is still > valid: the treatment of transitivity (new in Java 8) allows this > inference to succeed, while the lack of it caused inference to fail in > Java 5, 6,7. > > Maurizio > > > -- > Sent from my Android device with K-9 Mail. Please excuse my brevity. -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Thu Nov 17 19:18:02 2016 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 17 Nov 2016 20:18:02 +0100 (CET) Subject: Java 8 compiler bug? In-Reply-To: References: <044FA0F6-E362-45F3-AE13-8209FDBDBD49@pivotal.io> Message-ID: <1719305803.2736268.1479410282052.JavaMail.zimbra@u-pem.fr> > De: "Maurizio Cimadamore" > ?: "Remi Forax" , "Oliver Gierke" > Cc: compiler-dev at openjdk.java.net > Envoy?: Jeudi 17 Novembre 2016 19:16:02 > Objet: Re: Java 8 compiler bug? > On 17/11/16 17:19, Remi Forax wrote: >> I think the main issue is that when the inference fails, the compiler instead of >> reporting an error continue using Object instead. > Where is inference failing in JDK 8? I think the 'problem' here is that the code > below: > import java.util.*; > class Test { > void test() { > Expression objectExpression = null; > Expression> collectionOfObjectExpression = null; > m(objectExpression, collectionOfObjectExpression); > } > interface Expression {} > > void m(E elem, Expression collection) { } > } > succeeds with -source N where N >= 8 and fails otherwise - which is a > consequence of Java 8 inference being more powerful. In the original example, > the fact that there was an overload, combined with the fact that inference used > to fail for one of the overloaded methods meant that the program passed in > source N < 8 but fails with ambiguity after 8 because now overload resolution > can consider both methods as being applicable. > Maurizio Sorry, my mail was not specific enough, i agree with you, with N < 8, the inference fails -> instead of reporting an error, only one method becomes applicable -> it seems to work. I know it's too late but when the inference fails, instead of making a method non-acceptable, and silently choose the other overload, the compiler should have reported an error. IDEs/compilers should have a warning for that, because each time we make the inference smarter, diamond in 7, inference inside method call in 8 (auto-wildcard/declaration site variance in 10?), we introduce source incompatibilities. regards, R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: From bsrbnd at gmail.com Fri Nov 18 15:52:45 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Fri, 18 Nov 2016 16:52:45 +0100 Subject: [PATCH] 8147527: Non-optimal code generated for postfix unary operators In-Reply-To: References: <580E6B06.5000800@oracle.com> <580F4CDC.3020408@oracle.com> <581B3F95.7060505@oracle.com> <582B30CD.1070905@oracle.com> Message-ID: Hi, 2016-11-16 11:18 GMT+01:00 bsrbnd : > Hi Jan, > > 2016-11-15 16:59 GMT+01:00 Jan Lahoda : >> Hi Bernard, >> >> Sorry for delayed answer. >> >> I don't think there's a precedent in the current code in using >> JCTree.clone(), but I quite like it. I incline to think the shallow clones >> fit the needs here. >> >> I am attaching a patch that includes your patch, the original test broken by >> JDK-8143388 and a test that I tried to write to verify the desugaring >> (checks the trees after Lower). I'd like to go through the other tests to >> see which should be added, do some more testing (in particular the code in >> lowerBoxedPostop seems a little bit suspicious, as the newly-created type >> cast may be cloned) and send a request for review. > When I wrote this patch, I was more thinking of making a deep copy of > the tree. But I realized that a shallow copy could be enough in our > situation and would be a safer fix. In such a configuration, cloning > only a type-cast doesn't make any sense, of course. The updated fix > below is probably better even if this has no impact in our precise > example. > The following test shows the problem if the type-cast is cloned instead of "tmp1". Thus the updated fix I send previously seems to be important (I think). Bernard diff --git a/test/tools/javac/boxing/QualBoxedPostOp2.java b/test/tools/javac/boxing/QualBoxedPostOp2.java new file mode 100644 --- /dev/null +++ b/test/tools/javac/boxing/QualBoxedPostOp2.java @@ -0,0 +1,33 @@ +/* + * @test + * @bug 8147527 + * @summary Qualified "super" boxed unary post-operation using a type variable. + */ +public class QualBoxedPostOp2 extends Parent2 { + public static void main(String[] args) { + new QualBoxedPostOp2().testAll(); + } + + private void testAll() { + super.i = 10; + + equals(new Inner().testParent(), 10); + equals(super.i, 11); + } + + private void equals(int a, int b) { + if (a != b) throw new Error(); + } + + T i; + + class Inner { + private Integer testParent() { + return QualBoxedPostOp2.super.i++; + } + } +} + +class Parent2 { + protected T i; +} >> Please let me know if >> there are some tests that should definitely be included, or if you'd have >> any other comments. > "BoxedPostOpOpti" and "BoxedPostOpOpti2" verify the optimization of > the generated code by comparing it with what's generated for "i++". > I've thought of specifying explicitly the expected generated code, > instead; but I thought it was too precise as it might perhaps change > in the future. Thus, your solution of comparing the desugared code is > probably better. > > Another difference is that you put "Parent" in the same package while > I put it in another one as it was the subject of issue 8143388 (but > this isn't really important for the optimization, I think). > > "BoxedPostOpOpti" tests also the optimization of "C.this.i++" which > implies the correct handling of "this$0" without generating any > accessor. > > "BoxedPostOpOpti2" verifies also the optimization of "super.j++" (with > "P" in a separate package) which was done by issue 8143388 changset. > > "BoxedPostOpOpti3" checks the runtime behavior of issue 8143388 > changset as the associated test verifies only the success of the > compilation. This isn't absolutely necessary since the problem was not > at runtime, but I thought it was safer to do so. > >> Thank you for your work on this, >> Jan >> > Thank you, too. > > Bernard > > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java > @@ -2218,7 +2218,7 @@ > return builder.build(rval); > } > Name name = TreeInfo.name(rval); > - if (name == names._super) > + if (name == names._super || name == names._this) > return builder.build(rval); > VarSymbol var = > new VarSymbol(FINAL|SYNTHETIC, > @@ -3205,7 +3205,7 @@ > newTag, > > tree.type, > > tree.rhs.type); > - JCExpression expr = lhs; > + JCExpression expr = (JCExpression)lhs.clone(); > if (expr.type != tree.type) > expr = make.TypeCast(tree.type, expr); > JCBinary opResult = make.Binary(newTag, expr, > tree.rhs); > @@ -3288,9 +3288,10 @@ > public JCExpression build(final > JCExpression tmp2) { > JCTree.Tag opcode = (tree.hasTag(POSTINC)) > ? PLUS_ASG : MINUS_ASG; > - JCTree lhs = cast > - ? make.TypeCast(tree.arg.type, tmp1) > - : tmp1; > + JCExpression lhs = (JCExpression)tmp1.clone(); > + lhs = cast > + ? make.TypeCast(tree.arg.type, lhs) > + : lhs; > JCExpression update = makeAssignop(opcode, > lhs, > make.Literal(1)); From bsrbnd at gmail.com Sat Nov 19 15:28:40 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Sat, 19 Nov 2016 16:28:40 +0100 Subject: JDK 8147527 bis: Lower.makeComma() optimization and refactoring Message-ID: Hi, I would like to make one more comment aside this issue but related to it. Lower.makeComma() creates a temporary variable and discard it immediatly without using it. This should be avoided, too. The "let expression" for the simple case of "this.i++" should use only one temporary variable: class Issue8147527 { Integer i=0; private Integer test() { return this.i++; } } The patch, here below, is a suggestion of refactoring for this optimization (needs to be well tested). Thus, before this we had the following desugared and generated code: private Integer test() { return (let /*synthetic*/ final Integer $5222779 = (Integer)this.i in (let /*synthetic*/ final Integer $18695331 = this.i = Integer.valueOf((int)(this.i.intValue() + 1)) in $5222779)); } private java.lang.Integer test(); Code: 0: aload_0 1: getfield #3 // Field i:Ljava/lang/Integer; 4: astore_1 5: aload_0 6: aload_0 7: getfield #3 // Field i:Ljava/lang/Integer; 10: invokevirtual #4 // Method java/lang/Integer.intValue:()I 13: iconst_1 14: iadd 15: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 18: dup_x1 19: putfield #3 // Field i:Ljava/lang/Integer; 22: astore_2 23: aload_1 24: areturn } And after, we would have: private Integer test() { return (let /*synthetic*/ final Integer $5222779 = (Integer)this.i in (eval this.i = Integer.valueOf((int)(this.i.intValue() + 1)); in $5222779)); } private java.lang.Integer test(); Code: 0: aload_0 1: getfield #3 // Field i:Ljava/lang/Integer; 4: astore_1 5: aload_0 6: aload_0 7: getfield #3 // Field i:Ljava/lang/Integer; 10: invokevirtual #4 // Method java/lang/Integer.intValue:()I 13: iconst_1 14: iadd 15: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 18: putfield #3 // Field i:Ljava/lang/Integer; 21: aload_1 22: areturn } Which is much better, I think; we save space in the local variable array and reduce the number of instructions... What's your opinion on that, should something like this be included in a near future? Thanks, Bernard diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2208,6 +2208,10 @@ * in the let expression. */ JCExpression abstractRval(JCExpression rval, Type type, TreeBuilder builder) { + return abstractRval(rval, type, false, builder); + } + + JCExpression abstractRval(JCExpression rval, Type type, boolean discard, TreeBuilder builder) { rval = TreeInfo.skipParens(rval); switch (rval.getTag()) { case LITERAL: @@ -2218,8 +2222,18 @@ return builder.build(rval); } Name name = TreeInfo.name(rval); - if (name == names._super) + if (name == names._super || name == names._this) return builder.build(rval); + + if (discard) { + rval = convert(rval,type); + JCExpressionStatement eval = make.Exec(rval); + JCExpression built = builder.build(null); + JCExpression res = make.LetComma(eval, built); + res.type = built.type; + return res; + } + VarSymbol var = new VarSymbol(FINAL|SYNTHETIC, names.fromString( @@ -2283,11 +2297,7 @@ // evaluate and discard the first expression, then evaluate the second. JCExpression makeComma(final JCExpression expr1, final JCExpression expr2) { - return abstractRval(expr1, new TreeBuilder() { - public JCExpression build(final JCExpression discarded) { - return expr2; - } - }); + return abstractRval(expr1, expr1.type, true, (final JCExpression discarded) -> expr2); } /************************************************************************** @@ -3205,7 +3215,7 @@ newTag, tree.type, tree.rhs.type); - JCExpression expr = lhs; + JCExpression expr = (JCExpression)lhs.clone(); if (expr.type != tree.type) expr = make.TypeCast(tree.type, expr); JCBinary opResult = make.Binary(newTag, expr, tree.rhs); @@ -3288,9 +3298,10 @@ public JCExpression build(final JCExpression tmp2) { JCTree.Tag opcode = (tree.hasTag(POSTINC)) ? PLUS_ASG : MINUS_ASG; - JCTree lhs = cast - ? make.TypeCast(tree.arg.type, tmp1) - : tmp1; + JCExpression lhs = (JCExpression)tmp1.clone(); + lhs = cast + ? make.TypeCast(tree.arg.type, lhs) + : lhs; JCExpression update = makeAssignop(opcode, lhs, make.Literal(1)); @@ -3857,6 +3868,10 @@ public void visitLetExpr(LetExpr tree) { tree.defs = translateVarDefs(tree.defs); + if (tree instanceof LetComma) { + LetComma comma = (LetComma)tree; + comma.eval = translate(comma.eval); + } tree.expr = translate(tree.expr, tree.type); result = tree; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1574,9 +1574,9 @@ ((JCUnary) e).setTag(PREDEC); break; } - Assert.check(code.state.stacksize == 0); + int stacksize = code.state.stacksize; genExpr(tree.expr, tree.expr.type).drop(); - Assert.check(code.state.stacksize == 0); + Assert.check(code.state.stacksize == stacksize); } public void visitBreak(JCBreak tree) { @@ -2129,6 +2129,10 @@ letExprDepth++; int limit = code.nextreg; genStats(tree.defs, env); + if (tree instanceof LetComma) { + LetComma comma = (LetComma)tree; + genStat(comma.eval, env); + } result = genExpr(tree.expr, tree.expr.type).load(); code.endScopes(limit); letExprDepth--; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -2860,6 +2860,14 @@ } } + public static class LetComma extends LetExpr { + public JCExpressionStatement eval; + protected LetComma(JCExpressionStatement eval, JCExpression expr) { + super(List.nil(), expr); + this.eval = eval; + } + } + /** An interface for tree factories */ public interface Factory { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -1433,7 +1433,12 @@ public void visitLetExpr(LetExpr tree) { try { - print("(let " + tree.defs + " in " + tree.expr + ")"); + if (tree instanceof LetComma) { + LetComma comma = (LetComma)tree; + print("(eval " + comma.eval + " in " + comma.expr + ")"); + } + else + print("(let " + tree.defs + " in " + tree.expr + ")"); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -594,6 +594,12 @@ return tree; } + public LetComma LetComma(JCExpressionStatement eval, JCExpression expr) { + LetComma tree = new LetComma(eval, expr); + tree.pos = pos; + return tree; + } + /* *************************************************************************** * Derived building blocks. ****************************************************************************/ From bsrbnd at gmail.com Tue Nov 22 12:57:48 2016 From: bsrbnd at gmail.com (bsrbnd) Date: Tue, 22 Nov 2016 13:57:48 +0100 Subject: JDK 8147527 bis: Lower.makeComma() optimization and refactoring In-Reply-To: References: Message-ID: Hi, I rewrote this optimization a bit better, here under. Creating a new class to hold a "comma expression" is useless. I simply refactored "LetExpr" to use statements instead of variable declarations. I've also run all javac tests. Bernard 2016-11-19 16:28 GMT+01:00 bsrbnd : > Hi, > > I would like to make one more comment aside this issue but related to it. > Lower.makeComma() creates a temporary variable and discard it > immediatly without using it. > This should be avoided, too. The "let expression" for the simple case > of "this.i++" should use only one temporary variable: > > class Issue8147527 { > Integer i=0; > private Integer test() { > return this.i++; > } > } > > The patch, here below, is a suggestion of refactoring for this > optimization (needs to be well tested). > > Thus, before this we had the following desugared and generated code: > > private Integer test() { > return (let /*synthetic*/ final Integer $5222779 = > (Integer)this.i in (let /*synthetic*/ final Integer $18695331 = this.i > = Integer.valueOf((int)(this.i.intValue() + 1)) in $5222779)); > } > > private java.lang.Integer test(); > Code: > 0: aload_0 > 1: getfield #3 // Field i:Ljava/lang/Integer; > 4: astore_1 > 5: aload_0 > 6: aload_0 > 7: getfield #3 // Field i:Ljava/lang/Integer; > 10: invokevirtual #4 // Method > java/lang/Integer.intValue:()I > 13: iconst_1 > 14: iadd > 15: invokestatic #2 // Method > java/lang/Integer.valueOf:(I)Ljava/lang/Integer; > 18: dup_x1 > 19: putfield #3 // Field i:Ljava/lang/Integer; > 22: astore_2 > 23: aload_1 > 24: areturn > } > > And after, we would have: > > private Integer test() { > return (let /*synthetic*/ final Integer $5222779 = > (Integer)this.i in (eval this.i = > Integer.valueOf((int)(this.i.intValue() + 1)); in $5222779)); > } > > private java.lang.Integer test(); > Code: > 0: aload_0 > 1: getfield #3 // Field i:Ljava/lang/Integer; > 4: astore_1 > 5: aload_0 > 6: aload_0 > 7: getfield #3 // Field i:Ljava/lang/Integer; > 10: invokevirtual #4 // Method > java/lang/Integer.intValue:()I > 13: iconst_1 > 14: iadd > 15: invokestatic #2 // Method > java/lang/Integer.valueOf:(I)Ljava/lang/Integer; > 18: putfield #3 // Field i:Ljava/lang/Integer; > 21: aload_1 > 22: areturn > } > > Which is much better, I think; we save space in the local variable > array and reduce the number of instructions... > > What's your opinion on that, should something like this be included in > a near future? > > Thanks, > > Bernard > diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2218,7 +2218,7 @@ return builder.build(rval); } Name name = TreeInfo.name(rval); - if (name == names._super) + if (name == names._super || name == names._this) return builder.build(rval); VarSymbol var = new VarSymbol(FINAL|SYNTHETIC, @@ -2283,11 +2283,9 @@ // evaluate and discard the first expression, then evaluate the second. JCExpression makeComma(final JCExpression expr1, final JCExpression expr2) { - return abstractRval(expr1, new TreeBuilder() { - public JCExpression build(final JCExpression discarded) { - return expr2; - } - }); + JCExpression comma = make.LetExpr(make.Exec(expr1), expr2); + comma.type = expr2.type; + return comma; } /************************************************************************** @@ -3205,7 +3203,7 @@ newTag, tree.type, tree.rhs.type); - JCExpression expr = lhs; + JCExpression expr = (JCExpression)lhs.clone(); if (expr.type != tree.type) expr = make.TypeCast(tree.type, expr); JCBinary opResult = make.Binary(newTag, expr, tree.rhs); @@ -3288,9 +3286,10 @@ public JCExpression build(final JCExpression tmp2) { JCTree.Tag opcode = (tree.hasTag(POSTINC)) ? PLUS_ASG : MINUS_ASG; - JCTree lhs = cast - ? make.TypeCast(tree.arg.type, tmp1) - : tmp1; + JCExpression lhs = (JCExpression)tmp1.clone(); + lhs = cast + ? make.TypeCast(tree.arg.type, lhs) + : lhs; JCExpression update = makeAssignop(opcode, lhs, make.Literal(1)); @@ -3856,7 +3855,7 @@ } public void visitLetExpr(LetExpr tree) { - tree.defs = translateVarDefs(tree.defs); + tree.stmts = translate(tree.stmts); tree.expr = translate(tree.expr, tree.type); result = tree; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java @@ -506,7 +506,7 @@ @Override public void visitLetExpr(LetExpr tree) { SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); - sr.mergeWith(csp(tree.defs)); + sr.mergeWith(csp(tree.stmts)); sr.mergeWith(csp(tree.expr)); result = sr; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1574,9 +1574,9 @@ ((JCUnary) e).setTag(PREDEC); break; } - Assert.check(code.state.stacksize == 0); + Assert.check(letExprDepth != 0 || code.state.stacksize == 0); genExpr(tree.expr, tree.expr.type).drop(); - Assert.check(code.state.stacksize == 0); + Assert.check(letExprDepth != 0 || code.state.stacksize == 0); } public void visitBreak(JCBreak tree) { @@ -2128,7 +2128,7 @@ public void visitLetExpr(LetExpr tree) { letExprDepth++; int limit = code.nextreg; - genStats(tree.defs, env); + genStats(tree.stmts, env); result = genExpr(tree.expr, tree.expr.type).load(); code.endScopes(limit); letExprDepth--; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -2837,10 +2837,10 @@ /** (let int x = 3; in x+2) */ public static class LetExpr extends JCExpression { - public List defs; + public List stmts; public JCExpression expr; - protected LetExpr(List defs, JCExpression expr) { - this.defs = defs; + protected LetExpr(List stmts, JCExpression expr) { + this.stmts = stmts; this.expr = expr; } @Override @@ -2951,7 +2951,7 @@ JCProvides Provides(JCExpression serviceName, JCExpression implName); JCRequires Requires(boolean isPublic, JCExpression qualId); JCUses Uses(JCExpression qualId); - LetExpr LetExpr(List defs, JCExpression expr); + LetExpr LetExpr(List stmts, JCExpression expr); } /** A generic visitor class for trees. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -1433,7 +1433,7 @@ public void visitLetExpr(LetExpr tree) { try { - print("(let " + tree.defs + " in " + tree.expr + ")"); + print("(let " + tree.stmts + " in " + tree.expr + ")"); } catch (IOException e) { throw new UncheckedIOException(e); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -549,9 +549,9 @@ switch (tree.getTag()) { case LETEXPR: { LetExpr t = (LetExpr) node; - List defs = copy(t.defs, p); + List stmts = copy(t.stmts, p); JCExpression expr = copy(t.expr, p); - return M.at(t.pos).LetExpr(defs, expr); + return M.at(t.pos).LetExpr(stmts, expr); } default: throw new AssertionError("unknown tree tag: " + tree.getTag()); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -588,8 +588,8 @@ return tree; } - public LetExpr LetExpr(List defs, JCExpression expr) { - LetExpr tree = new LetExpr(defs, expr); + public LetExpr LetExpr(List stmts, JCExpression expr) { + LetExpr tree = new LetExpr(stmts, expr); tree.pos = pos; return tree; } @@ -609,8 +609,8 @@ defs); } - public LetExpr LetExpr(JCVariableDecl def, JCExpression expr) { - LetExpr tree = new LetExpr(List.of(def), expr); + public LetExpr LetExpr(JCStatement stmt, JCExpression expr) { + LetExpr tree = new LetExpr(List.of(stmt), expr); tree.pos = pos; return tree; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java @@ -360,7 +360,7 @@ } public void visitLetExpr(LetExpr tree) { - scan(tree.defs); + scan(tree.stmts); scan(tree.expr); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java @@ -419,7 +419,7 @@ } public void visitLetExpr(LetExpr tree) { - tree.defs = translateVarDefs(tree.defs); + tree.stmts = translate(tree.stmts); tree.expr = translate(tree.expr); result = tree; } From joe.darcy at oracle.com Tue Nov 22 14:43:36 2016 From: joe.darcy at oracle.com (joe darcy) Date: Tue, 22 Nov 2016 06:43:36 -0800 Subject: RFR JDK-8170170 Problem list ExternalEditorTest.java on all platforms In-Reply-To: <037601d2449f$4e5be5e0$eb13b1a0$@oracle.com> References: <037601d2449f$4e5be5e0$eb13b1a0$@oracle.com> Message-ID: <311927b1-a9c5-87b8-50dc-6e89e64c8c7c@oracle.com> Hello, Yes, given the failures seen on non-windows platforms too, this test is failing often enough to be universally problem listed. Thanks, -Joe On 11/22/2016 1:03 AM, Frank Yuan wrote: > Hi All > > > > This is a problem list update in langtools repo: > > diff -r f4b6b78a1200 test/ProblemList.txt > > --- a/test/ProblemList.txt Mon Nov 21 12:28:56 2016 -0800 > > +++ b/test/ProblemList.txt Tue Nov 22 16:34:24 2016 +0800 > > @@ -38,7 +38,7 @@ > > jdk/jshell/EditorPadTest.java 8161276 windows-all Test set-up cannot press > buttons > > jdk/jshell/ToolBasicTest.java 8139873 generic-all JShell tests failing > > -jdk/jshell/ExternalEditorTest.java 8170108 windows-all > > +jdk/jshell/ExternalEditorTest.java 8169828 generic-all > > > > Bug: https://bugs.openjdk.java.net/browse/JDK-8170170 > > > > Anyone would like to have a look? > > > > Thanks > > Frank > From cushon at google.com Wed Nov 23 03:34:50 2016 From: cushon at google.com (Liam Miller-Cushon) Date: Tue, 22 Nov 2016 19:34:50 -0800 Subject: reopen JDK-8063054? Message-ID: JDK-8063054 was marked 'cannot reproduce', but I'm still seeing this issue with 9-ea+145: $ cat Test.java class Test { void test(Box> b) { Number n = b.map(Box::get).get(); } } interface Func { T apply(S arg); } interface Box { T get(); Box map(Func f); } $ javac -Xlint:rawtypes Test.java Test.java:3: warning: [rawtypes] found raw type: Box Number n = b.map(Box::get).get(); ^ missing type arguments for generic class Box where T is a type-variable: T extends Object declared in interface Box 1 warning $ cat Test.java interface Consumer { void accept(T arg); } interface Parent

{ void foo(); } interface Child extends Parent {} class Test { static void m(T arg, Consumer f) {} public void test(Child c) { m(c, Parent::foo); } } $ javac -Xlint:rawtypes Test.java Test.java:8: warning: [rawtypes] found raw type: Parent public void test(Child c) { m(c, Parent::foo); } ^ missing type arguments for generic class Parent

where P is a type-variable: P extends Object declared in interface Parent 1 warning -------------- next part -------------- An HTML attachment was scrubbed... URL: From joe.darcy at oracle.com Wed Nov 23 04:05:18 2016 From: joe.darcy at oracle.com (joe darcy) Date: Tue, 22 Nov 2016 20:05:18 -0800 Subject: RFR 8170249/9, Problem list jdk/jshell/ToolFormatTest.java and jdk/jshell/ReplaceTest.java until 8170216 is fixed In-Reply-To: References: Message-ID: <67ee5fd1-4979-157c-4caf-9127b812943f@oracle.com> +1 Thanks, -Joe On 11/22/2016 7:38 PM, Felix Yang wrote: > Hi there, > > please review the change to problem following tests on Soalris > Sparcv9. They have been observed to be failing quite frequently on > Solaris Sparcv9 > > Thanks, > > Felix > > > diff -r 318dd5fce0ee test/ProblemList.txt > --- a/test/ProblemList.txt Tue Nov 22 16:31:03 2016 -0800 > +++ b/test/ProblemList.txt Tue Nov 22 19:20:36 2016 -0800 > @@ -39,6 +39,8 @@ > jdk/jshell/EditorPadTest.java 8161276 windows-all Test set-up > cannot press buttons > jdk/jshell/ToolBasicTest.java 8139873 generic-all JShell tests > failing > jdk/jshell/ExternalEditorTest.java 8170108 generic-all > +jdk/jshell/ToolFormatTest.java 8170216 solaris-sparcv9 > +jdk/jshell/ReplaceTest.java 8170216 solaris-sparcv9 > > ########################################################################### > > # > From maurizio.cimadamore at oracle.com Wed Nov 23 11:11:06 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 23 Nov 2016 11:11:06 +0000 Subject: reopen JDK-8063054? In-Reply-To: References: Message-ID: I'm seeing the warnings myself - Vicente can you take another look? Maurizio On 23/11/16 03:34, Liam Miller-Cushon wrote: > JDK-8063054 was marked 'cannot reproduce', but I'm still seeing this > issue with 9-ea+145: > > $ cat Test.java > class Test { > void test(Box> b) { > Number n = b.map(Box::get).get(); > } > } > > interface Func { T apply(S arg); } > > interface Box { > T get(); > Box map(Func f); > } > $ javac -Xlint:rawtypes Test.java > Test.java:3: warning: [rawtypes] found raw type: Box > Number n = b.map(Box::get).get(); > ^ > missing type arguments for generic class Box > where T is a type-variable: > T extends Object declared in interface Box > 1 warning > > $ cat Test.java > interface Consumer { void accept(T arg); } > interface Parent

{ void foo(); } > interface Child extends Parent {} > > class Test { > static void m(T arg, Consumer f) {} > > public void test(Child c) { m(c, Parent::foo); } > } > $ javac -Xlint:rawtypes Test.java > Test.java:8: warning: [rawtypes] found raw type: Parent > public void test(Child c) { m(c, Parent::foo); } > ^ > missing type arguments for generic class Parent

> where P is a type-variable: > P extends Object declared in interface Parent > 1 warning From erik.joelsson at oracle.com Wed Nov 23 12:29:30 2016 From: erik.joelsson at oracle.com (Erik Joelsson) Date: Wed, 23 Nov 2016 13:29:30 +0100 Subject: RFR: JDK-8170279: Langtools test/Makefile ignores failed tests Message-ID: <441605b1-0209-9e60-7fc9-fa09d9d8aa1b@oracle.com> After JDK-8167354, when a test fails in jtreg, the langtools test/Makefile ignores the result and exits with 0. This causes (at least) JPRT jobs to not fail when langtools tests fail. The reason for this is the added "| tee" construct which overrides the exit value from jtreg. Bug: https://bugs.openjdk.java.net/browse/JDK-8170279 Webrev: http://cr.openjdk.java.net/~erikj/8170279/webrev.langtools.01/ /Erik From Alan.Bateman at oracle.com Wed Nov 23 12:33:05 2016 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Wed, 23 Nov 2016 12:33:05 +0000 Subject: RFR: JDK-8170279: Langtools test/Makefile ignores failed tests In-Reply-To: <441605b1-0209-9e60-7fc9-fa09d9d8aa1b@oracle.com> References: <441605b1-0209-9e60-7fc9-fa09d9d8aa1b@oracle.com> Message-ID: <952c722e-a86e-f2d7-7551-8851be52cf96@oracle.com> On 23/11/2016 12:29, Erik Joelsson wrote: > After JDK-8167354, when a test fails in jtreg, the langtools > test/Makefile ignores the result and exits with 0. This causes (at > least) JPRT jobs to not fail when langtools tests fail. The reason for > this is the added "| tee" construct which overrides the exit value > from jtreg. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8170279 > > Webrev: http://cr.openjdk.java.net/~erikj/8170279/webrev.langtools.01/ This looks good, and a bit scary that this wasn't noticed until now. -Alan From tim.bell at oracle.com Wed Nov 23 15:25:24 2016 From: tim.bell at oracle.com (Tim Bell) Date: Wed, 23 Nov 2016 07:25:24 -0800 Subject: RFR: JDK-8170279: Langtools test/Makefile ignores failed tests In-Reply-To: <441605b1-0209-9e60-7fc9-fa09d9d8aa1b@oracle.com> References: <441605b1-0209-9e60-7fc9-fa09d9d8aa1b@oracle.com> Message-ID: <8b68b238-324f-092d-16bd-36f67f31ee84@oracle.com> Erik: > After JDK-8167354, when a test fails in jtreg, the langtools > test/Makefile ignores the result and exits with 0. This causes (at > least) JPRT jobs to not fail when langtools tests fail. The reason for > this is the added "| tee" construct which overrides the exit value from > jtreg. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8170279 > > Webrev: http://cr.openjdk.java.net/~erikj/8170279/webrev.langtools.01/ Good catch. Looks good to me. Tim From vicente.romero at oracle.com Wed Nov 23 15:37:06 2016 From: vicente.romero at oracle.com (Vicente Romero) Date: Wed, 23 Nov 2016 10:37:06 -0500 Subject: reopen JDK-8063054? In-Reply-To: References: Message-ID: Hi, Thanks for the report. It seems like I made a mistake in the evaluation, working on it. Vicente On 11/23/2016 06:11 AM, Maurizio Cimadamore wrote: > I'm seeing the warnings myself - Vicente can you take another look? > > Maurizio > > > On 23/11/16 03:34, Liam Miller-Cushon wrote: >> JDK-8063054 was marked 'cannot reproduce', but I'm still seeing this >> issue with 9-ea+145: >> >> $ cat Test.java >> class Test { >> void test(Box> b) { >> Number n = b.map(Box::get).get(); >> } >> } >> >> interface Func { T apply(S arg); } >> >> interface Box { >> T get(); >> Box map(Func f); >> } >> $ javac -Xlint:rawtypes Test.java >> Test.java:3: warning: [rawtypes] found raw type: Box >> Number n = b.map(Box::get).get(); >> ^ >> missing type arguments for generic class Box >> where T is a type-variable: >> T extends Object declared in interface Box >> 1 warning >> >> $ cat Test.java >> interface Consumer { void accept(T arg); } >> interface Parent

{ void foo(); } >> interface Child extends Parent {} >> >> class Test { >> static void m(T arg, Consumer f) {} >> >> public void test(Child c) { m(c, Parent::foo); } >> } >> $ javac -Xlint:rawtypes Test.java >> Test.java:8: warning: [rawtypes] found raw type: Parent >> public void test(Child c) { m(c, Parent::foo); } >> ^ >> missing type arguments for generic class Parent

>> where P is a type-variable: >> P extends Object declared in interface Parent >> 1 warning > From mandy.chung at oracle.com Wed Nov 23 16:37:50 2016 From: mandy.chung at oracle.com (Mandy Chung) Date: Wed, 23 Nov 2016 08:37:50 -0800 Subject: RFR: JDK-8170279: Langtools test/Makefile ignores failed tests In-Reply-To: <441605b1-0209-9e60-7fc9-fa09d9d8aa1b@oracle.com> References: <441605b1-0209-9e60-7fc9-fa09d9d8aa1b@oracle.com> Message-ID: <656733E2-5855-40C5-A884-77779F237AF3@oracle.com> Looks good. Mandy > On Nov 23, 2016, at 4:29 AM, Erik Joelsson wrote: > > After JDK-8167354, when a test fails in jtreg, the langtools test/Makefile ignores the result and exits with 0. This causes (at least) JPRT jobs to not fail when langtools tests fail. The reason for this is the added "| tee" construct which overrides the exit value from jtreg. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8170279 > > Webrev: http://cr.openjdk.java.net/~erikj/8170279/webrev.langtools.01/ > > /Erik > From Alan.Bateman at oracle.com Thu Nov 24 15:25:20 2016 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Thu, 24 Nov 2016 15:25:20 +0000 Subject: Code review for jigsaw/jake -> jdk9/dev sync up Message-ID: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> Folks on jigsaw-dev will know that we are on a mission to bring the changes accumulated in the jake forest to jdk9/dev. We can think of this as a refresh of the module system in JDK 9, the last big refresh was in May with many small updates since then. The focus this time is to bring the changes that are tied to JSR issues into jdk9/dev, specifically the issues that are tracked on the JSR issues list [1] as: #CompileTimeDependences #AddExportsInManifest #ClassFileModuleName #ClassFileAccPublic #ServiceLoaderEnhancements #ResourceEncapsulation/#ClassFilesAsResources #ReflectiveAccessToNonExportedTypes #AwkwardStrongEncapsulation #ReadabilityAddedByLayerCreator #IndirectQualifiedReflectiveAccess (partial) #VersionsInModuleNames #NonHierarchicalLayers #ModuleAnnotations/#ModuleDeprecation #ReflectiveAccessByInstrumentationAgents Some of these issues are not "Resolved" yet, meaning there is still ongoing discussion on the EG mailing list. That is okay, there is nothing final here. If there are changes to these proposals then the implementation changes will follow. Also, as I said in a mail to jigsaw-dev yesterday [2], is that we will keep the jake forest open for ongoing prototyping and iteration, also ongoing implementation improvements where iteration or bake time is important. For the code review then the focus is therefore on sanity checking the changes that we would like to bring into jdk9/dev. We will not use this review thread to debate alternative designs or other big implementation changes that are more appropriate to bake in jake. To get going, I've put the webrevs with a snapshot of the changes in jake here: http://cr.openjdk.java.net/~alanb/8169069/0/ The changes are currently sync'ed against jdk-9+146 and will be rebased (and re-tested) against jdk9/dev prior to integration. There are a number of small changes that need to be added to this in the coming days, I will refresh the webrev every few days to take account of these updates. A few important points to mention, even if you aren't reviewing the changes: 1. This refresh requires a new version of jtreg to run the tests. The changes for this new version are in the code-tools/jtreg repository and the plan is to tag a new build (jtreg4.2-b04) next week. Once the tag has been added then we'll update the requiredVersion property in each TEST.ROOT to force everyone to update. 2. For developers trying out modules with the main line JDK 9 builds then be aware that `requires public` changes to `requires transitive` and the `provides` clause changes to require all providers for a specific service type to be in the same clause. Also be aware that the binary form of the module declaration (module-info.class) changes so you will need to recompile any modules. 3. Those running existing code on JDK 9 and ignoring modules will need to be aware of a disruptive change in this refresh. The disruptive change is #AwkwardStrongEncapsulation where setAccessible(true) is changed so that it can't be used to break into non-public fields/methods of JDK classes. This change is going to expose a lot of hacks in existing code. We plan to send mail to jdk9-dev in advance of this integration to create awareness of this change. As per the original introduction of strong encapsulation then command line options (and now the manifest of application JAR files) can be used to keep existing code working. The new option is `--add-opens` to open a package in a module for deep reflection by other modules. As an example, if you find yourself with code that hacks into the private `comparator` field in java.util.TreeMap then running with `--add-opens java.base/java.util=ALL-UNNAMED` will keep that code working. A few miscellaneous notes for those that are reviewing: 1. We have some temporary/transition code in the top-level repo to deal with the importing of the JavaFX modules. This will be removed once the changes are in JDK 9 for the OpenJFX project to use. 2. In the jdk repo then it's important to understand that the module system is initialized at startup and there are many places where we need to keep startup performance in mind. This sometimes means less elegant code than might be used if startup wasn't such a big concern. 3. The changes in the jaxws repo make use of new APIs that means the code doesn't compile with JDK 7 or JDK 8. Our intention is to work with the JAXB and JAX-WS maintainers to address the issues in the upstream project and then bring those changes into jdk9/dev to replace the patches that we are forced to push for the short term. 4. You will see several tests where the value of the @modules tag has `:open` or `:+open`. This is new jtreg speak. The former means the test is run with --add-opens to open the package, the latter means the test is exported at compile-time and exported + open at run-time (the latter usage will be rare, it's where tests have static references to JDK internal types and are also doing deep reflection with setAccessible). In terms of dates then we are aiming to integrate these changes into jdk9/dev in early December. I will send a follow-up mail next week on this as we work through the logistics. -Alan [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ [2] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html From jan.lahoda at oracle.com Fri Nov 25 11:38:01 2016 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Fri, 25 Nov 2016 12:38:01 +0100 Subject: JDK-8147527: Wrong code generated for postfix unary operators Message-ID: <58382299.4010103@oracle.com> Hello, As noted here: http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010452.html javac sometimes generates code incorrectly, as discussed further in the thread. The proposed fix is to not reuse the AST nodes on multiple places. Bug: https://bugs.openjdk.java.net/browse/JDK-8147527 Webrev: http://cr.openjdk.java.net/~jlahoda/8147527/webrev.00/ Any feedback is welcome. Thanks to Bernard for his work on this. Jan From bruno.rosa at eldorado.org.br Fri Nov 25 18:47:20 2016 From: bruno.rosa at eldorado.org.br (Bruno Alexandre Rosa) Date: Fri, 25 Nov 2016 18:47:20 +0000 Subject: Running javac with symlinks Message-ID: <8240baf9e67c499fb0436ed48d91cf2a@serv030.corp.eldorado.org.br> Hi, everyone, I came across a minor unusual situation trying to compile and run the java version of a benchmark suite [1]: in jdk9, when the source files are actually symlinks, the bytecode files are generated in the same directories as the *targets* of the links as opposed to the behavior in jdk8, whereas in the bytecode files are generated in the same path as the link themselves. So, my question is: is this new behavior a feature or a bug? Regards, Bruno Rosa [1] - https://benchmarksgame.alioth.debian.org/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From jonathan.gibbons at oracle.com Sat Nov 26 03:37:27 2016 From: jonathan.gibbons at oracle.com (Jonathan Gibbons) Date: Fri, 25 Nov 2016 19:37:27 -0800 Subject: Running javac with symlinks In-Reply-To: <8240baf9e67c499fb0436ed48d91cf2a@serv030.corp.eldorado.org.br> References: <8240baf9e67c499fb0436ed48d91cf2a@serv030.corp.eldorado.org.br> Message-ID: Bruno, Since it is not really specified how javac operates in the context of symlinks, I think you can say that the new behavior is neither a feature nor a bug, but maybe just a side-effect of the internal change from using java.io.File to java.nio.file.Path. That being said, the behavior was inconsistent for following symlinks as needed for directories, but not for the final file itself. And as you noted when you forwarded the question to jdk9-dev, the man page does specify "the same directory as the source file". > Also, both man pages from openjdk8 and an early access Java SE9 [2] have the same text regarding the default behavior: > > "If the -d option is not specified, then javac puts each class file in the same directory as the source file from which it was generated." So, I think that makes the change come down on the side of a feature, and not a bug. In general, I would recommend specifying an output directory for compiled class files with -d, and not rely on behavior of putting the class file in the same directory as the source, which IMO is more suitable for simple HelloWorld-type programs. -- Jon On 11/25/16 10:47 AM, Bruno Alexandre Rosa wrote: > > Hi, everyone, > > I came across a minor unusual situation trying to compile and run the > java version of a benchmark suite [1]: in jdk9, when the source files > are actually symlinks, the bytecode files are generated in the same > directories as the *targets* of the links as opposed to the behavior > in jdk8, whereas in the bytecode files are generated in the same path > as the link themselves. > > So, my question is: is this new behavior a feature or a bug? > > Regards, > > Bruno Rosa > > [1] - https://benchmarksgame.alioth.debian.org/ > -------------- next part -------------- An HTML attachment was scrubbed... URL: From peter.levart at gmail.com Sun Nov 27 11:15:43 2016 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 27 Nov 2016 12:15:43 +0100 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> Message-ID: <8c6567ad-6c42-cebc-52b7-a28caad1c64b@gmail.com> Hi Alan, Overall this looks very good. I noticed a couple of nits... 1. I wonder if the new ServiceLoader API signature should be tweaked a bit... There is a new method in ServiceLoader with the following signature: public Stream> stream() ...where Provider declares the following two methods: Class type(); S get(); Which means that I can do the following: ServiceLoader loader = ServiceLoader.load(MyService.class); Class clazz = loader.stream().map(Provider::type).findFirst().get(); But 'clazz' now holds a Class object representing the implementation class (MyServiceImpl for example) not the MyService class/interface. Could this be characterized as heap pollution? For example, I can not do the following easily without unchecked casts: Class clazz = MyServiceImpl.class; Error: java: incompatible types: java.lang.Class cannot be converted to java.lang.Class So should Provider rather declare the following? Class type(); Or alternatively, should ServiceLoader rather declare the following? public Stream> stream(); 2. In Resolver::makeGraph, the initial 'g2' graph from parent configurations' "require transitive" is build this way: for (Configuration parent : parents) { if (parent != Configuration.empty()) { parent.configurations().forEach(c -> { c.modules().forEach(m1 -> { m1.descriptor().requires().stream() .filter(r -> r.modifiers().contains(Modifier.TRANSITIVE)) .forEach(r -> { String dn = r.name(); assert c.findModule(dn).isPresent() || r.modifiers().contains(Modifier.STATIC); c.findModule(dn).ifPresent(m2 -> { g2.computeIfAbsent(m1, k -> new HashSet<>()).add(m2); }); }); }); }); } } Now that there can be multiple parents of some configuration, those parents can have common parents, but since you iterate the transitive configurations of each individual parent in isolation, you can encounter a common "diamond" configuration multiple times. Logically all is well since you collect the required modules into Sets so multiplicity is taken care of. But this is not very optimal from algorithm point. It would be better to 1st make a stream of unique configurations of all parents: parents .stream() .flatMap(Configuration::configurations) .distinct() ...and then continute processing this stream further. You could even make this code more "functional" by using flatMap instead of forEach... Map> g2 = parents .stream() .flatMap(Configuration::configurations) .distinct() // optimization in case of common "diamond" parent(s) .flatMap(c -> c.modules().stream().flatMap(m1 -> m1.descriptor().requires().stream() .filter(req -> req.modifiers().contains(Modifier.TRANSITIVE)) .flatMap(req -> { Optional m2 = c.findModule(req.name()); assert m2.isPresent() || req.modifiers().contains(Modifier.STATIC); return m2.stream(); }) .map(m2 -> Map.entry(m1, m2)) ) ) .collect(Collectors.groupingBy( Map.Entry::getKey, () -> new HashMap<>(capacity), Collectors.mapping(Map.Entry::getValue, Collectors.toSet()) )); Regards, Peter On 11/24/2016 04:25 PM, Alan Bateman wrote: > Folks on jigsaw-dev will know that we are on a mission to bring the > changes accumulated in the jake forest to jdk9/dev. We can think of > this as a refresh of the module system in JDK 9, the last big refresh > was in May with many small updates since then. > > The focus this time is to bring the changes that are tied to JSR > issues into jdk9/dev, specifically the issues that are tracked on the > JSR issues list [1] as: > > #CompileTimeDependences > #AddExportsInManifest > #ClassFileModuleName > #ClassFileAccPublic > #ServiceLoaderEnhancements > #ResourceEncapsulation/#ClassFilesAsResources > #ReflectiveAccessToNonExportedTypes > #AwkwardStrongEncapsulation > #ReadabilityAddedByLayerCreator > #IndirectQualifiedReflectiveAccess (partial) > #VersionsInModuleNames > #NonHierarchicalLayers > #ModuleAnnotations/#ModuleDeprecation > #ReflectiveAccessByInstrumentationAgents > > Some of these issues are not "Resolved" yet, meaning there is still > ongoing discussion on the EG mailing list. That is okay, there is > nothing final here. If there are changes to these proposals then the > implementation changes will follow. Also, as I said in a mail to > jigsaw-dev yesterday [2], is that we will keep the jake forest open > for ongoing prototyping and iteration, also ongoing implementation > improvements where iteration or bake time is important. > > For the code review then the focus is therefore on sanity checking the > changes that we would like to bring into jdk9/dev. We will not use > this review thread to debate alternative designs or other big > implementation changes that are more appropriate to bake in jake. > > To get going, I've put the webrevs with a snapshot of the changes in > jake here: > http://cr.openjdk.java.net/~alanb/8169069/0/ > > The changes are currently sync'ed against jdk-9+146 and will be > rebased (and re-tested) against jdk9/dev prior to integration. There > are a number of small changes that need to be added to this in the > coming days, I will refresh the webrev every few days to take account > of these updates. > > > A few important points to mention, even if you aren't reviewing the > changes: > > 1. This refresh requires a new version of jtreg to run the tests. The > changes for this new version are in the code-tools/jtreg repository > and the plan is to tag a new build (jtreg4.2-b04) next week. Once the > tag has been added then we'll update the requiredVersion property in > each TEST.ROOT to force everyone to update. > > 2. For developers trying out modules with the main line JDK 9 builds > then be aware that `requires public` changes to `requires transitive` > and the `provides` clause changes to require all providers for a > specific service type to be in the same clause. Also be aware that the > binary form of the module declaration (module-info.class) changes so > you will need to recompile any modules. > > 3. Those running existing code on JDK 9 and ignoring modules will need > to be aware of a disruptive change in this refresh. The disruptive > change is #AwkwardStrongEncapsulation where setAccessible(true) is > changed so that it can't be used to break into non-public > fields/methods of JDK classes. This change is going to expose a lot of > hacks in existing code. We plan to send mail to jdk9-dev in advance of > this integration to create awareness of this change. As per the > original introduction of strong encapsulation then command line > options (and now the manifest of application JAR files) can be used to > keep existing code working. The new option is `--add-opens` to open a > package in a module for deep reflection by other modules. As an > example, if you find yourself with code that hacks into the private > `comparator` field in java.util.TreeMap then running with `--add-opens > java.base/java.util=ALL-UNNAMED` will keep that code working. > > > A few miscellaneous notes for those that are reviewing: > > 1. We have some temporary/transition code in the top-level repo to > deal with the importing of the JavaFX modules. This will be removed > once the changes are in JDK 9 for the OpenJFX project to use. > > 2. In the jdk repo then it's important to understand that the module > system is initialized at startup and there are many places where we > need to keep startup performance in mind. This sometimes means less > elegant code than might be used if startup wasn't such a big concern. > > 3. The changes in the jaxws repo make use of new APIs that means the > code doesn't compile with JDK 7 or JDK 8. Our intention is to work > with the JAXB and JAX-WS maintainers to address the issues in the > upstream project and then bring those changes into jdk9/dev to replace > the patches that we are forced to push for the short term. > > 4. You will see several tests where the value of the @modules tag has > `:open` or `:+open`. This is new jtreg speak. The former means the > test is run with --add-opens to open the package, the latter means the > test is exported at compile-time and exported + open at run-time (the > latter usage will be rare, it's where tests have static references to > JDK internal types and are also doing deep reflection with > setAccessible). > > > In terms of dates then we are aiming to integrate these changes into > jdk9/dev in early December. I will send a follow-up mail next week on > this as we work through the logistics. > > -Alan > > [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ > [2] > http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From suokunstar at gmail.com Sun Nov 27 21:29:08 2016 From: suokunstar at gmail.com (Tony S) Date: Sun, 27 Nov 2016 15:29:08 -0600 Subject: Compiler version test failed of SPECJVM2008 benchmarks on OpenJDK Message-ID: Here are the errors and corresponding solutions for compiler version test failed of SPECJVM2008 on OpenJDK. Hoping this will help people in the future. ------------------------[Error message start]------------------------ Received output: [008] 2nd bounds test: OK [009] Compiler version test: failed [010] testIf: OK [011] testArray: OK [012] testBitOps: OK [013] testFor: OK [014] ... Complete output: /SPECjvm2008/results/SPECjvm2008.055/check.bt1.i1.op1.error.log Validation file: /SPECjvm2008/resources/check/validity.check.dat No benchmarks will be run, since initial check test failed. The Javac version test in check failed. The Javac version must be the one included in SPECjvm2008. There is a known issue with this for Java on Mac OS X, including a workaround. For more info, see ./docs/KnownIssues.html ------------------------[Error message end]------------------------ Here is my solution: ------------------------[Solution message start]------------------------ Under your JDK directory, execute $ make all images Then you can find rt.jar under your build folder. For example, rt.jar is located under my directory: build/linux-x86_64-normal-server-release/images/j2sdk-image/jre/lib/ Next, execute the SPECJVM2008 benchmarks like this: $ [your java directory] -Xbootclasspath/p:[your rt.jar directory] -jar SPECjvm2008.jar [benchmark name] [other parameters] it should works and no compiler version test error happens. ------------------------[Solution message end]------------------------ Hoping this will help people using SPECJVM2008 on your customized JDK. -- ********************************** > Tony S > Computer Science, University of Texas at Arlington ********************************** From Alan.Bateman at oracle.com Mon Nov 28 10:57:37 2016 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Mon, 28 Nov 2016 10:57:37 +0000 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <8c6567ad-6c42-cebc-52b7-a28caad1c64b@gmail.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> <8c6567ad-6c42-cebc-52b7-a28caad1c64b@gmail.com> Message-ID: <174041a3-6233-6f7c-2b03-c1e8280c9da9@oracle.com> On 27/11/2016 11:15, Peter Levart wrote: > Hi Alan, > > Overall this looks very good. I noticed a couple of nits... Thanks for going through the changes. > : > > So should Provider rather declare the following? > > Class type(); > > Or alternatively, should ServiceLoader rather declare the following? > > public Stream> stream(); Well spotted, this should be Class. We could change the return of stream too but that might be more awkward to work with. > : > > Now that there can be multiple parents of some configuration, those > parents can have common parents, but since you iterate the transitive > configurations of each individual parent in isolation, you can > encounter a common "diamond" configuration multiple times. Logically > all is well since you collect the required modules into Sets so > multiplicity is taken care of. But this is not very optimal from > algorithm point. It would be better to 1st make a stream of unique > configurations of all parents: Fair comment, we haven't done any performance work for the multi parent scenario yet, mostly because #NonHierarchicalLayers is niche and there are still some open questions on how parents should be searched. So we can change this as you suggest except that it regresses startup, this is the reason for skipping Configuration.empty(). However we support both so I'll get that change in so that the more elegant code is used when creating dynamic configurations. -Alan From maurizio.cimadamore at oracle.com Mon Nov 28 11:28:56 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 28 Nov 2016 11:28:56 +0000 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> Message-ID: <117bda90-cf1f-8d33-ef81-b86624f486f6@oracle.com> Hi, the langtools code looks generally ok. Few questions: * Why doesn't 'open' get its own directive in Directive.java - instead of relying on a 'mode' set on an export directive? * ClassReader: should we have checks regarding an open module containing no open directives in the classfile? This seems to be called out in the spec [1] - see section 2.2 * At some point we should investigate better sharing strategy between ClassReader and ModuleNameReader * Names.dynamic seems unused * I note that the classfile attribute name changes are not captured in the spec (but I might be referring to a slightly older version). Maurizio [1] - http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html#jigsaw-2.2 On 24/11/16 15:25, Alan Bateman wrote: > Folks on jigsaw-dev will know that we are on a mission to bring the > changes accumulated in the jake forest to jdk9/dev. We can think of > this as a refresh of the module system in JDK 9, the last big refresh > was in May with many small updates since then. > > The focus this time is to bring the changes that are tied to JSR > issues into jdk9/dev, specifically the issues that are tracked on the > JSR issues list [1] as: > > #CompileTimeDependences > #AddExportsInManifest > #ClassFileModuleName > #ClassFileAccPublic > #ServiceLoaderEnhancements > #ResourceEncapsulation/#ClassFilesAsResources > #ReflectiveAccessToNonExportedTypes > #AwkwardStrongEncapsulation > #ReadabilityAddedByLayerCreator > #IndirectQualifiedReflectiveAccess (partial) > #VersionsInModuleNames > #NonHierarchicalLayers > #ModuleAnnotations/#ModuleDeprecation > #ReflectiveAccessByInstrumentationAgents > > Some of these issues are not "Resolved" yet, meaning there is still > ongoing discussion on the EG mailing list. That is okay, there is > nothing final here. If there are changes to these proposals then the > implementation changes will follow. Also, as I said in a mail to > jigsaw-dev yesterday [2], is that we will keep the jake forest open > for ongoing prototyping and iteration, also ongoing implementation > improvements where iteration or bake time is important. > > For the code review then the focus is therefore on sanity checking the > changes that we would like to bring into jdk9/dev. We will not use > this review thread to debate alternative designs or other big > implementation changes that are more appropriate to bake in jake. > > To get going, I've put the webrevs with a snapshot of the changes in > jake here: > http://cr.openjdk.java.net/~alanb/8169069/0/ > > The changes are currently sync'ed against jdk-9+146 and will be > rebased (and re-tested) against jdk9/dev prior to integration. There > are a number of small changes that need to be added to this in the > coming days, I will refresh the webrev every few days to take account > of these updates. > > > A few important points to mention, even if you aren't reviewing the > changes: > > 1. This refresh requires a new version of jtreg to run the tests. The > changes for this new version are in the code-tools/jtreg repository > and the plan is to tag a new build (jtreg4.2-b04) next week. Once the > tag has been added then we'll update the requiredVersion property in > each TEST.ROOT to force everyone to update. > > 2. For developers trying out modules with the main line JDK 9 builds > then be aware that `requires public` changes to `requires transitive` > and the `provides` clause changes to require all providers for a > specific service type to be in the same clause. Also be aware that the > binary form of the module declaration (module-info.class) changes so > you will need to recompile any modules. > > 3. Those running existing code on JDK 9 and ignoring modules will need > to be aware of a disruptive change in this refresh. The disruptive > change is #AwkwardStrongEncapsulation where setAccessible(true) is > changed so that it can't be used to break into non-public > fields/methods of JDK classes. This change is going to expose a lot of > hacks in existing code. We plan to send mail to jdk9-dev in advance of > this integration to create awareness of this change. As per the > original introduction of strong encapsulation then command line > options (and now the manifest of application JAR files) can be used to > keep existing code working. The new option is `--add-opens` to open a > package in a module for deep reflection by other modules. As an > example, if you find yourself with code that hacks into the private > `comparator` field in java.util.TreeMap then running with `--add-opens > java.base/java.util=ALL-UNNAMED` will keep that code working. > > > A few miscellaneous notes for those that are reviewing: > > 1. We have some temporary/transition code in the top-level repo to > deal with the importing of the JavaFX modules. This will be removed > once the changes are in JDK 9 for the OpenJFX project to use. > > 2. In the jdk repo then it's important to understand that the module > system is initialized at startup and there are many places where we > need to keep startup performance in mind. This sometimes means less > elegant code than might be used if startup wasn't such a big concern. > > 3. The changes in the jaxws repo make use of new APIs that means the > code doesn't compile with JDK 7 or JDK 8. Our intention is to work > with the JAXB and JAX-WS maintainers to address the issues in the > upstream project and then bring those changes into jdk9/dev to replace > the patches that we are forced to push for the short term. > > 4. You will see several tests where the value of the @modules tag has > `:open` or `:+open`. This is new jtreg speak. The former means the > test is run with --add-opens to open the package, the latter means the > test is exported at compile-time and exported + open at run-time (the > latter usage will be rare, it's where tests have static references to > JDK internal types and are also doing deep reflection with > setAccessible). > > > In terms of dates then we are aiming to integrate these changes into > jdk9/dev in early December. I will send a follow-up mail next week on > this as we work through the logistics. > > -Alan > > [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ > [2] > http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html From snicoll at pivotal.io Mon Nov 28 13:50:36 2016 From: snicoll at pivotal.io (=?UTF-8?Q?St=C3=A9phane_Nicoll?=) Date: Mon, 28 Nov 2016 14:50:36 +0100 Subject: Detect default field values in annotation processor Message-ID: Hello, I am working on the Spring Boot project where we've built an annotation processor that extracts some information about well-defined classes in order to generate a metadata file. To reduce it to the scope of my question, consider the following class: @ConfigurationProperties public class Foo { private static final String DEFAULT_NAME = "name"; private String name = DEFAULT_NAME; private Integer counter = 42; private List hosts = Collections.singletonList("localhost"); } And an annotation processor that kicks in based on the presence of @ConfigurationProperties. I would like to be able to extract the field initialization values defined in the class. Concretely: * "name" requires us to browse to a symbol that is defined in the class. That constant may be defined in the parent as well * 42 is the actual symbol so it's easy * "localhost" sounds a bit funky to extract but it's a heuristic that worked quite well for us (read: checking if the right part of the statement is a method invocation that we know, and if so extract the parameter value(s)). We have an implementation that works[1] but I am wondering if there isn't an easier way and, more importantly, something that does not rely on a compiler specific implementation. One drawback of this implementation is that it does not work with the eclipse compiler. Thoughts? Thanks! S. [1] https://github.com/spring-projects/spring-boot/tree/e15b3e463f312524495349673a16cb67cfaa2eae/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/fieldvalues/javac -------------- next part -------------- An HTML attachment was scrubbed... URL: From bruno.rosa at eldorado.org.br Mon Nov 28 13:57:50 2016 From: bruno.rosa at eldorado.org.br (Bruno Alexandre Rosa) Date: Mon, 28 Nov 2016 13:57:50 +0000 Subject: Running javac with symlinks In-Reply-To: References: <8240baf9e67c499fb0436ed48d91cf2a@serv030.corp.eldorado.org.br> Message-ID: Thanks a lot, Jonathan! That said, I'll update the scripts I'm using. Just a quick note: this microbenchmark suite is actually more of a collection of HelloWorld-like programs :) Regards, Bruno Rosa From: compiler-dev [mailto:compiler-dev-bounces at openjdk.java.net] On Behalf Of Jonathan Gibbons Sent: s?bado, 26 de novembro de 2016 01:37 To: compiler-dev at openjdk.java.net Subject: Re: Running javac with symlinks Bruno, Since it is not really specified how javac operates in the context of symlinks, I think you can say that the new behavior is neither a feature nor a bug, but maybe just a side-effect of the internal change from using java.io.File to java.nio.file.Path. That being said, the behavior was inconsistent for following symlinks as needed for directories, but not for the final file itself. And as you noted when you forwarded the question to jdk9-dev, the man page does specify "the same directory as the source file". Also, both man pages from openjdk8 and an early access Java SE9 [2] have the same text regarding the default behavior: "If the -d option is not specified, then javac puts each class file in the same directory as the source file from which it was generated." So, I think that makes the change come down on the side of a feature, and not a bug. In general, I would recommend specifying an output directory for compiled class files with -d, and not rely on behavior of putting the class file in the same directory as the source, which IMO is more suitable for simple HelloWorld-type programs. -- Jon On 11/25/16 10:47 AM, Bruno Alexandre Rosa wrote: Hi, everyone, I came across a minor unusual situation trying to compile and run the java version of a benchmark suite [1]: in jdk9, when the source files are actually symlinks, the bytecode files are generated in the same directories as the *targets* of the links as opposed to the behavior in jdk8, whereas in the bytecode files are generated in the same path as the link themselves. So, my question is: is this new behavior a feature or a bug? Regards, Bruno Rosa [1] - https://benchmarksgame.alioth.debian.org/ -------------- next part -------------- An HTML attachment was scrubbed... URL: From karen.kinnear at oracle.com Mon Nov 28 14:47:03 2016 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Mon, 28 Nov 2016 09:47:03 -0500 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <583C4019.8040506@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> <583C4019.8040506@oracle.com> Message-ID: Alan, I reviewed all the hotspot runtime changes - except the tests (Christian will review those) - and jvmti - which Dmitry Samersoff will review. They look good. thanks, Karen > On Nov 28, 2016, at 9:32 AM, Lois Foltan wrote: > > Hi Alan, > > I have reviewed the hotspot changes and they look good. Minor nit, src/share/vm/classfile/javaClasses.cpp only differs by the addition of a blank line. > > Thanks, > Lois > > On 11/24/2016 10:25 AM, Alan Bateman wrote: >> Folks on jigsaw-dev will know that we are on a mission to bring the changes accumulated in the jake forest to jdk9/dev. We can think of this as a refresh of the module system in JDK 9, the last big refresh was in May with many small updates since then. >> >> The focus this time is to bring the changes that are tied to JSR issues into jdk9/dev, specifically the issues that are tracked on the JSR issues list [1] as: >> >> #CompileTimeDependences >> #AddExportsInManifest >> #ClassFileModuleName >> #ClassFileAccPublic >> #ServiceLoaderEnhancements >> #ResourceEncapsulation/#ClassFilesAsResources >> #ReflectiveAccessToNonExportedTypes >> #AwkwardStrongEncapsulation >> #ReadabilityAddedByLayerCreator >> #IndirectQualifiedReflectiveAccess (partial) >> #VersionsInModuleNames >> #NonHierarchicalLayers >> #ModuleAnnotations/#ModuleDeprecation >> #ReflectiveAccessByInstrumentationAgents >> >> Some of these issues are not "Resolved" yet, meaning there is still ongoing discussion on the EG mailing list. That is okay, there is nothing final here. If there are changes to these proposals then the implementation changes will follow. Also, as I said in a mail to jigsaw-dev yesterday [2], is that we will keep the jake forest open for ongoing prototyping and iteration, also ongoing implementation improvements where iteration or bake time is important. >> >> For the code review then the focus is therefore on sanity checking the changes that we would like to bring into jdk9/dev. We will not use this review thread to debate alternative designs or other big implementation changes that are more appropriate to bake in jake. >> >> To get going, I've put the webrevs with a snapshot of the changes in jake here: >> http://cr.openjdk.java.net/~alanb/8169069/0/ >> >> The changes are currently sync'ed against jdk-9+146 and will be rebased (and re-tested) against jdk9/dev prior to integration. There are a number of small changes that need to be added to this in the coming days, I will refresh the webrev every few days to take account of these updates. >> >> >> A few important points to mention, even if you aren't reviewing the changes: >> >> 1. This refresh requires a new version of jtreg to run the tests. The changes for this new version are in the code-tools/jtreg repository and the plan is to tag a new build (jtreg4.2-b04) next week. Once the tag has been added then we'll update the requiredVersion property in each TEST.ROOT to force everyone to update. >> >> 2. For developers trying out modules with the main line JDK 9 builds then be aware that `requires public` changes to `requires transitive` and the `provides` clause changes to require all providers for a specific service type to be in the same clause. Also be aware that the binary form of the module declaration (module-info.class) changes so you will need to recompile any modules. >> >> 3. Those running existing code on JDK 9 and ignoring modules will need to be aware of a disruptive change in this refresh. The disruptive change is #AwkwardStrongEncapsulation where setAccessible(true) is changed so that it can't be used to break into non-public fields/methods of JDK classes. This change is going to expose a lot of hacks in existing code. We plan to send mail to jdk9-dev in advance of this integration to create awareness of this change. As per the original introduction of strong encapsulation then command line options (and now the manifest of application JAR files) can be used to keep existing code working. The new option is `--add-opens` to open a package in a module for deep reflection by other modules. As an example, if you find yourself with code that hacks into the private `comparator` field in java.util.TreeMap then running with `--add-opens java.base/java.util=ALL-UNNAMED` will keep that code working. >> >> >> A few miscellaneous notes for those that are reviewing: >> >> 1. We have some temporary/transition code in the top-level repo to deal with the importing of the JavaFX modules. This will be removed once the changes are in JDK 9 for the OpenJFX project to use. >> >> 2. In the jdk repo then it's important to understand that the module system is initialized at startup and there are many places where we need to keep startup performance in mind. This sometimes means less elegant code than might be used if startup wasn't such a big concern. >> >> 3. The changes in the jaxws repo make use of new APIs that means the code doesn't compile with JDK 7 or JDK 8. Our intention is to work with the JAXB and JAX-WS maintainers to address the issues in the upstream project and then bring those changes into jdk9/dev to replace the patches that we are forced to push for the short term. >> >> 4. You will see several tests where the value of the @modules tag has `:open` or `:+open`. This is new jtreg speak. The former means the test is run with --add-opens to open the package, the latter means the test is exported at compile-time and exported + open at run-time (the latter usage will be rare, it's where tests have static references to JDK internal types and are also doing deep reflection with setAccessible). >> >> >> In terms of dates then we are aiming to integrate these changes into jdk9/dev in early December. I will send a follow-up mail next week on this as we work through the logistics. >> >> -Alan >> >> [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ >> [2] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html > From chris.hegarty at oracle.com Mon Nov 28 14:47:24 2016 From: chris.hegarty at oracle.com (Chris Hegarty) Date: Mon, 28 Nov 2016 14:47:24 +0000 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> Message-ID: <79ECD41A-D3B4-40C2-AEDE-976C67BFE844@oracle.com> On 24 Nov 2016, at 15:25, Alan Bateman wrote: > > ... > To get going, I've put the webrevs with a snapshot of the changes in jake here: > http://cr.openjdk.java.net/~alanb/8169069/0/ Overall this look very good. I ran through most of the changes in the jdk repo, just a few small comments. 1) SuppressWarnings.java typo element - > elementS 38 * However, note that if a warning is suppressed in a {@code 39 * module-info} file, the suppression applies to elementS within the 40 * file and not to types contained within the module. 2) jartool Main.java Maybe concealedPackages should have a comment about its use ( it is used in the Validator, and not by Main at all ). 3) MethodHandles.java privateLookupIn It might be clearer if the third bullet used {@code lookup}, or 'caller lookup?, or ?given lookup'? The CALLER lookup has the {@link Lookup#MODULE MODULE} lookup mode. 4) ServiceLoader {@code ExtendedCodecsFactory} 111 * will be treated as a provider factory and {@code 112 * ExtendedCodecsFactory.provider()} will be invoked to INSTANTIATE the 113 * provider. Is 'instantiate' strictly true here? Should it simply be ?return' 206 *

  • If a named module declares more than one provider then the providers 207 * are located in the order that they appear in the {@code provides} table of 208 * the {@code Module} class file attribute ({@code module-info.class}).
  • Wow. I assume the JLS, or otherwise, will specify that the order in which the providers are listed in the module-info be preserved, no? Maybe this item could mention that. The class file reference can still be kept, but seems a bit low-level for developers. -Chris. From jan.lahoda at oracle.com Mon Nov 28 14:53:59 2016 From: jan.lahoda at oracle.com (Jan Lahoda) Date: Mon, 28 Nov 2016 15:53:59 +0100 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <117bda90-cf1f-8d33-ef81-b86624f486f6@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> <117bda90-cf1f-8d33-ef81-b86624f486f6@oracle.com> Message-ID: <583C4507.9010702@oracle.com> Thanks for the comments Maurizio. On 28.11.2016 12:28, Maurizio Cimadamore wrote: > Hi, > the langtools code looks generally ok. Few questions: > > * Why doesn't 'open' get its own directive in Directive.java - instead > of relying on a 'mode' set on an export directive? It seemed to me that having two directive interfaces in the API for directives that have the same structure was unnecessary (as we don't have MethodElement and ConstructorElement, but just ExecutableElement, or TypeElement that represents a class, an interface, an annotation type or an enum type). If you think it would be better to have separate interfaces for exports and opens, I am OK with that as well. > > * ClassReader: should we have checks regarding an open module containing > no open directives in the classfile? This seems to be called out in the > spec [1] - see section 2.2 I think such checks would be fine, working on a patch. > > * At some point we should investigate better sharing strategy between > ClassReader and ModuleNameReader > > * Names.dynamic seems unused Fixed: http://hg.openjdk.java.net/jigsaw/jake/langtools/rev/8156e205fcb4 Jan > > * I note that the classfile attribute name changes are not captured in > the spec (but I might be referring to a slightly older version). > > Maurizio > > [1] - http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html#jigsaw-2.2 > > > > > > > On 24/11/16 15:25, Alan Bateman wrote: >> Folks on jigsaw-dev will know that we are on a mission to bring the >> changes accumulated in the jake forest to jdk9/dev. We can think of >> this as a refresh of the module system in JDK 9, the last big refresh >> was in May with many small updates since then. >> >> The focus this time is to bring the changes that are tied to JSR >> issues into jdk9/dev, specifically the issues that are tracked on the >> JSR issues list [1] as: >> >> #CompileTimeDependences >> #AddExportsInManifest >> #ClassFileModuleName >> #ClassFileAccPublic >> #ServiceLoaderEnhancements >> #ResourceEncapsulation/#ClassFilesAsResources >> #ReflectiveAccessToNonExportedTypes >> #AwkwardStrongEncapsulation >> #ReadabilityAddedByLayerCreator >> #IndirectQualifiedReflectiveAccess (partial) >> #VersionsInModuleNames >> #NonHierarchicalLayers >> #ModuleAnnotations/#ModuleDeprecation >> #ReflectiveAccessByInstrumentationAgents >> >> Some of these issues are not "Resolved" yet, meaning there is still >> ongoing discussion on the EG mailing list. That is okay, there is >> nothing final here. If there are changes to these proposals then the >> implementation changes will follow. Also, as I said in a mail to >> jigsaw-dev yesterday [2], is that we will keep the jake forest open >> for ongoing prototyping and iteration, also ongoing implementation >> improvements where iteration or bake time is important. >> >> For the code review then the focus is therefore on sanity checking the >> changes that we would like to bring into jdk9/dev. We will not use >> this review thread to debate alternative designs or other big >> implementation changes that are more appropriate to bake in jake. >> >> To get going, I've put the webrevs with a snapshot of the changes in >> jake here: >> http://cr.openjdk.java.net/~alanb/8169069/0/ >> >> The changes are currently sync'ed against jdk-9+146 and will be >> rebased (and re-tested) against jdk9/dev prior to integration. There >> are a number of small changes that need to be added to this in the >> coming days, I will refresh the webrev every few days to take account >> of these updates. >> >> >> A few important points to mention, even if you aren't reviewing the >> changes: >> >> 1. This refresh requires a new version of jtreg to run the tests. The >> changes for this new version are in the code-tools/jtreg repository >> and the plan is to tag a new build (jtreg4.2-b04) next week. Once the >> tag has been added then we'll update the requiredVersion property in >> each TEST.ROOT to force everyone to update. >> >> 2. For developers trying out modules with the main line JDK 9 builds >> then be aware that `requires public` changes to `requires transitive` >> and the `provides` clause changes to require all providers for a >> specific service type to be in the same clause. Also be aware that the >> binary form of the module declaration (module-info.class) changes so >> you will need to recompile any modules. >> >> 3. Those running existing code on JDK 9 and ignoring modules will need >> to be aware of a disruptive change in this refresh. The disruptive >> change is #AwkwardStrongEncapsulation where setAccessible(true) is >> changed so that it can't be used to break into non-public >> fields/methods of JDK classes. This change is going to expose a lot of >> hacks in existing code. We plan to send mail to jdk9-dev in advance of >> this integration to create awareness of this change. As per the >> original introduction of strong encapsulation then command line >> options (and now the manifest of application JAR files) can be used to >> keep existing code working. The new option is `--add-opens` to open a >> package in a module for deep reflection by other modules. As an >> example, if you find yourself with code that hacks into the private >> `comparator` field in java.util.TreeMap then running with `--add-opens >> java.base/java.util=ALL-UNNAMED` will keep that code working. >> >> >> A few miscellaneous notes for those that are reviewing: >> >> 1. We have some temporary/transition code in the top-level repo to >> deal with the importing of the JavaFX modules. This will be removed >> once the changes are in JDK 9 for the OpenJFX project to use. >> >> 2. In the jdk repo then it's important to understand that the module >> system is initialized at startup and there are many places where we >> need to keep startup performance in mind. This sometimes means less >> elegant code than might be used if startup wasn't such a big concern. >> >> 3. The changes in the jaxws repo make use of new APIs that means the >> code doesn't compile with JDK 7 or JDK 8. Our intention is to work >> with the JAXB and JAX-WS maintainers to address the issues in the >> upstream project and then bring those changes into jdk9/dev to replace >> the patches that we are forced to push for the short term. >> >> 4. You will see several tests where the value of the @modules tag has >> `:open` or `:+open`. This is new jtreg speak. The former means the >> test is run with --add-opens to open the package, the latter means the >> test is exported at compile-time and exported + open at run-time (the >> latter usage will be rare, it's where tests have static references to >> JDK internal types and are also doing deep reflection with >> setAccessible). >> >> >> In terms of dates then we are aiming to integrate these changes into >> jdk9/dev in early December. I will send a follow-up mail next week on >> this as we work through the logistics. >> >> -Alan >> >> [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ >> [2] >> http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html >> > From maurizio.cimadamore at oracle.com Mon Nov 28 16:01:05 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 28 Nov 2016 16:01:05 +0000 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <583C4507.9010702@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> <117bda90-cf1f-8d33-ef81-b86624f486f6@oracle.com> <583C4507.9010702@oracle.com> Message-ID: On 28/11/16 14:53, Jan Lahoda wrote: > Thanks for the comments Maurizio. > > On 28.11.2016 12:28, Maurizio Cimadamore wrote: >> Hi, >> the langtools code looks generally ok. Few questions: >> >> * Why doesn't 'open' get its own directive in Directive.java - instead >> of relying on a 'mode' set on an export directive? > > It seemed to me that having two directive interfaces in the API for > directives that have the same structure was unnecessary (as we don't > have MethodElement and ConstructorElement, but just ExecutableElement, > or TypeElement that represents a class, an interface, an annotation > type or an enum type). > > If you think it would be better to have separate interfaces for > exports and opens, I am OK with that as well. I agree that it would be redundant - perhaps the two directive can both share a common superclass which defines the common fields? I said that because it looks like for everything else, 'opens' and 'exports' are really two separate directives, with separate bytecode encodings and such (that is, the Module attribute has separate entries for 'opens' and 'exports'). > >> >> * ClassReader: should we have checks regarding an open module containing >> no open directives in the classfile? This seems to be called out in the >> spec [1] - see section 2.2 > > I think such checks would be fine, working on a patch. ok > >> >> * At some point we should investigate better sharing strategy between >> ClassReader and ModuleNameReader >> >> * Names.dynamic seems unused > > Fixed: > http://hg.openjdk.java.net/jigsaw/jake/langtools/rev/8156e205fcb4 Thanks Maurizio > Jan > >> >> * I note that the classfile attribute name changes are not captured in >> the spec (but I might be referring to a slightly older version). >> >> Maurizio >> >> [1] - http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html#jigsaw-2.2 >> >> >> >> >> >> >> On 24/11/16 15:25, Alan Bateman wrote: >>> Folks on jigsaw-dev will know that we are on a mission to bring the >>> changes accumulated in the jake forest to jdk9/dev. We can think of >>> this as a refresh of the module system in JDK 9, the last big refresh >>> was in May with many small updates since then. >>> >>> The focus this time is to bring the changes that are tied to JSR >>> issues into jdk9/dev, specifically the issues that are tracked on the >>> JSR issues list [1] as: >>> >>> #CompileTimeDependences >>> #AddExportsInManifest >>> #ClassFileModuleName >>> #ClassFileAccPublic >>> #ServiceLoaderEnhancements >>> #ResourceEncapsulation/#ClassFilesAsResources >>> #ReflectiveAccessToNonExportedTypes >>> #AwkwardStrongEncapsulation >>> #ReadabilityAddedByLayerCreator >>> #IndirectQualifiedReflectiveAccess (partial) >>> #VersionsInModuleNames >>> #NonHierarchicalLayers >>> #ModuleAnnotations/#ModuleDeprecation >>> #ReflectiveAccessByInstrumentationAgents >>> >>> Some of these issues are not "Resolved" yet, meaning there is still >>> ongoing discussion on the EG mailing list. That is okay, there is >>> nothing final here. If there are changes to these proposals then the >>> implementation changes will follow. Also, as I said in a mail to >>> jigsaw-dev yesterday [2], is that we will keep the jake forest open >>> for ongoing prototyping and iteration, also ongoing implementation >>> improvements where iteration or bake time is important. >>> >>> For the code review then the focus is therefore on sanity checking the >>> changes that we would like to bring into jdk9/dev. We will not use >>> this review thread to debate alternative designs or other big >>> implementation changes that are more appropriate to bake in jake. >>> >>> To get going, I've put the webrevs with a snapshot of the changes in >>> jake here: >>> http://cr.openjdk.java.net/~alanb/8169069/0/ >>> >>> The changes are currently sync'ed against jdk-9+146 and will be >>> rebased (and re-tested) against jdk9/dev prior to integration. There >>> are a number of small changes that need to be added to this in the >>> coming days, I will refresh the webrev every few days to take account >>> of these updates. >>> >>> >>> A few important points to mention, even if you aren't reviewing the >>> changes: >>> >>> 1. This refresh requires a new version of jtreg to run the tests. The >>> changes for this new version are in the code-tools/jtreg repository >>> and the plan is to tag a new build (jtreg4.2-b04) next week. Once the >>> tag has been added then we'll update the requiredVersion property in >>> each TEST.ROOT to force everyone to update. >>> >>> 2. For developers trying out modules with the main line JDK 9 builds >>> then be aware that `requires public` changes to `requires transitive` >>> and the `provides` clause changes to require all providers for a >>> specific service type to be in the same clause. Also be aware that the >>> binary form of the module declaration (module-info.class) changes so >>> you will need to recompile any modules. >>> >>> 3. Those running existing code on JDK 9 and ignoring modules will need >>> to be aware of a disruptive change in this refresh. The disruptive >>> change is #AwkwardStrongEncapsulation where setAccessible(true) is >>> changed so that it can't be used to break into non-public >>> fields/methods of JDK classes. This change is going to expose a lot of >>> hacks in existing code. We plan to send mail to jdk9-dev in advance of >>> this integration to create awareness of this change. As per the >>> original introduction of strong encapsulation then command line >>> options (and now the manifest of application JAR files) can be used to >>> keep existing code working. The new option is `--add-opens` to open a >>> package in a module for deep reflection by other modules. As an >>> example, if you find yourself with code that hacks into the private >>> `comparator` field in java.util.TreeMap then running with `--add-opens >>> java.base/java.util=ALL-UNNAMED` will keep that code working. >>> >>> >>> A few miscellaneous notes for those that are reviewing: >>> >>> 1. We have some temporary/transition code in the top-level repo to >>> deal with the importing of the JavaFX modules. This will be removed >>> once the changes are in JDK 9 for the OpenJFX project to use. >>> >>> 2. In the jdk repo then it's important to understand that the module >>> system is initialized at startup and there are many places where we >>> need to keep startup performance in mind. This sometimes means less >>> elegant code than might be used if startup wasn't such a big concern. >>> >>> 3. The changes in the jaxws repo make use of new APIs that means the >>> code doesn't compile with JDK 7 or JDK 8. Our intention is to work >>> with the JAXB and JAX-WS maintainers to address the issues in the >>> upstream project and then bring those changes into jdk9/dev to replace >>> the patches that we are forced to push for the short term. >>> >>> 4. You will see several tests where the value of the @modules tag has >>> `:open` or `:+open`. This is new jtreg speak. The former means the >>> test is run with --add-opens to open the package, the latter means the >>> test is exported at compile-time and exported + open at run-time (the >>> latter usage will be rare, it's where tests have static references to >>> JDK internal types and are also doing deep reflection with >>> setAccessible). >>> >>> >>> In terms of dates then we are aiming to integrate these changes into >>> jdk9/dev in early December. I will send a follow-up mail next week on >>> this as we work through the logistics. >>> >>> -Alan >>> >>> [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ >>> [2] >>> http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html >>> >>> >> From erik.joelsson at oracle.com Mon Nov 28 16:06:12 2016 From: erik.joelsson at oracle.com (Erik Joelsson) Date: Mon, 28 Nov 2016 17:06:12 +0100 Subject: RFR: JDK-8166737: default langtools make test settings result in no ouput Message-ID: The various test/Makefile in the forest do no all behave the same. The langtools/test/Makefile in particular has a different default verbosity setting compared to the rest. When running tests for the whole forest for CI, it would be more convenient if the verbosity was coherent. The other repositories sets the Jtreg verbosity to fail,error,time so I suggest we change langtools to match that. This will make running langtools tests through the makefile a lot noisier than today. Bug: https://bugs.openjdk.java.net/browse/JDK-8166737 Patch: diff -r 3dc39a1ffca4 test/Makefile --- a/test/Makefile +++ b/test/Makefile @@ -211,7 +211,7 @@ endif # Default verbosity setting for jtreg -JTREG_VERBOSE ?= fail,error,nopass +JTREG_VERBOSE ?= fail,error,time # Default verbosity setting for jck JCK_VERBOSE ?= non-pass /Erik From tim.bell at oracle.com Mon Nov 28 16:36:39 2016 From: tim.bell at oracle.com (Tim Bell) Date: Mon, 28 Nov 2016 08:36:39 -0800 Subject: RFR: JDK-8166737: default langtools make test settings result in no ouput In-Reply-To: References: Message-ID: <57f81f0b-47a0-823b-8315-628eff4b3a48@oracle.com> Erik: > The various test/Makefile in the forest do no all behave the same. The > langtools/test/Makefile in particular has a different default verbosity > setting compared to the rest. When running tests for the whole forest > for CI, it would be more convenient if the verbosity was coherent. > > The other repositories sets the Jtreg verbosity to fail,error,time so I > suggest we change langtools to match that. This will make running > langtools tests through the makefile a lot noisier than today. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8166737 > > Patch: > > diff -r 3dc39a1ffca4 test/Makefile > --- a/test/Makefile > +++ b/test/Makefile > @@ -211,7 +211,7 @@ > endif > > # Default verbosity setting for jtreg > -JTREG_VERBOSE ?= fail,error,nopass > +JTREG_VERBOSE ?= fail,error,time > > # Default verbosity setting for jck > JCK_VERBOSE ?= non-pass Looks good to me. Tim From maurizio.cimadamore at oracle.com Tue Nov 29 15:28:28 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 29 Nov 2016 15:28:28 +0000 Subject: JDK-8147527: Wrong code generated for postfix unary operators In-Reply-To: <58382299.4010103@oracle.com> References: <58382299.4010103@oracle.com> Message-ID: Looks good to me. Use of shallow clone looks a tad odd - but I understand why it's the way it is - maybe worth adding a comment? Maurizio On 25/11/16 11:38, Jan Lahoda wrote: > Hello, > > As noted here: > http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010452.html > > > javac sometimes generates code incorrectly, as discussed further in > the thread. > > The proposed fix is to not reuse the AST nodes on multiple places. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8147527 > Webrev: http://cr.openjdk.java.net/~jlahoda/8147527/webrev.00/ > > Any feedback is welcome. > > Thanks to Bernard for his work on this. > > Jan From andrey.x.nazarov at oracle.com Tue Nov 29 17:26:33 2016 From: andrey.x.nazarov at oracle.com (Andrey Nazarov) Date: Tue, 29 Nov 2016 20:26:33 +0300 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> Message-ID: <6296BDD5-8FC3-411C-9860-54BAE3E202B5@oracle.com> Hi, I?ve reviewed Langtools code. There are various comment ?//TODO?, ?//FIXME?, ?//XXX?. I think they should be revised. May be issues should be filed to track them. Unused import at 37 import java.io.IOException; in langtools/test/tools/javac/modules/ModuleInfoTest.java ASCII graphics issue at 64 line in test/tools/javac/modules/GraphsTest.java Unused builder method in langtools/test/tools/lib/toolbox/ModuleBuilder.java 159 public ModuleBuilder exportsDynamicPrivate(String pkg) { 141 public ModuleBuilder exportsDynamic(String pkg) { 179 public ModuleBuilder exportsDynamicTo(String pkg, String module) { 199 public ModuleBuilder exportsDynamicPrivateTo(String pkg, String module) { Javadoc is used instead of comment langtools/test/tools/javac/modules/AnnotationsOnModules.java /** 25 * @test ?Andrey > On 24 Nov 2016, at 18:25, Alan Bateman wrote: > > Folks on jigsaw-dev will know that we are on a mission to bring the changes accumulated in the jake forest to jdk9/dev. We can think of this as a refresh of the module system in JDK 9, the last big refresh was in May with many small updates since then. > > The focus this time is to bring the changes that are tied to JSR issues into jdk9/dev, specifically the issues that are tracked on the JSR issues list [1] as: > > #CompileTimeDependences > #AddExportsInManifest > #ClassFileModuleName > #ClassFileAccPublic > #ServiceLoaderEnhancements > #ResourceEncapsulation/#ClassFilesAsResources > #ReflectiveAccessToNonExportedTypes > #AwkwardStrongEncapsulation > #ReadabilityAddedByLayerCreator > #IndirectQualifiedReflectiveAccess (partial) > #VersionsInModuleNames > #NonHierarchicalLayers > #ModuleAnnotations/#ModuleDeprecation > #ReflectiveAccessByInstrumentationAgents > > Some of these issues are not "Resolved" yet, meaning there is still ongoing discussion on the EG mailing list. That is okay, there is nothing final here. If there are changes to these proposals then the implementation changes will follow. Also, as I said in a mail to jigsaw-dev yesterday [2], is that we will keep the jake forest open for ongoing prototyping and iteration, also ongoing implementation improvements where iteration or bake time is important. > > For the code review then the focus is therefore on sanity checking the changes that we would like to bring into jdk9/dev. We will not use this review thread to debate alternative designs or other big implementation changes that are more appropriate to bake in jake. > > To get going, I've put the webrevs with a snapshot of the changes in jake here: > http://cr.openjdk.java.net/~alanb/8169069/0/ > > The changes are currently sync'ed against jdk-9+146 and will be rebased (and re-tested) against jdk9/dev prior to integration. There are a number of small changes that need to be added to this in the coming days, I will refresh the webrev every few days to take account of these updates. > > > A few important points to mention, even if you aren't reviewing the changes: > > 1. This refresh requires a new version of jtreg to run the tests. The changes for this new version are in the code-tools/jtreg repository and the plan is to tag a new build (jtreg4.2-b04) next week. Once the tag has been added then we'll update the requiredVersion property in each TEST.ROOT to force everyone to update. > > 2. For developers trying out modules with the main line JDK 9 builds then be aware that `requires public` changes to `requires transitive` and the `provides` clause changes to require all providers for a specific service type to be in the same clause. Also be aware that the binary form of the module declaration (module-info.class) changes so you will need to recompile any modules. > > 3. Those running existing code on JDK 9 and ignoring modules will need to be aware of a disruptive change in this refresh. The disruptive change is #AwkwardStrongEncapsulation where setAccessible(true) is changed so that it can't be used to break into non-public fields/methods of JDK classes. This change is going to expose a lot of hacks in existing code. We plan to send mail to jdk9-dev in advance of this integration to create awareness of this change. As per the original introduction of strong encapsulation then command line options (and now the manifest of application JAR files) can be used to keep existing code working. The new option is `--add-opens` to open a package in a module for deep reflection by other modules. As an example, if you find yourself with code that hacks into the private `comparator` field in java.util.TreeMap then running with `--add-opens java.base/java.util=ALL-UNNAMED` will keep that code working. > > > A few miscellaneous notes for those that are reviewing: > > 1. We have some temporary/transition code in the top-level repo to deal with the importing of the JavaFX modules. This will be removed once the changes are in JDK 9 for the OpenJFX project to use. > > 2. In the jdk repo then it's important to understand that the module system is initialized at startup and there are many places where we need to keep startup performance in mind. This sometimes means less elegant code than might be used if startup wasn't such a big concern. > > 3. The changes in the jaxws repo make use of new APIs that means the code doesn't compile with JDK 7 or JDK 8. Our intention is to work with the JAXB and JAX-WS maintainers to address the issues in the upstream project and then bring those changes into jdk9/dev to replace the patches that we are forced to push for the short term. > > 4. You will see several tests where the value of the @modules tag has `:open` or `:+open`. This is new jtreg speak. The former means the test is run with --add-opens to open the package, the latter means the test is exported at compile-time and exported + open at run-time (the latter usage will be rare, it's where tests have static references to JDK internal types and are also doing deep reflection with setAccessible). > > > In terms of dates then we are aiming to integrate these changes into jdk9/dev in early December. I will send a follow-up mail next week on this as we work through the logistics. > > -Alan > > [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ > [2] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From sean.coffey at oracle.com Tue Nov 29 19:59:08 2016 From: sean.coffey at oracle.com (=?UTF-8?Q?Se=c3=a1n_Coffey?=) Date: Tue, 29 Nov 2016 19:59:08 +0000 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> Message-ID: Good to see the exception handling being verbose with context Alan. I've given a quick look at that area and have only some minor comments. Layer.java : 635 if (parentLayers.size() != parentConfigurations.size()) 636 throw new IllegalArgumentException("wrong number of parents"); Could we print the number of parents expected versus detected ? src/jdk.jartool/share/classes/sun/tools/jar/Main.java 856 if (name.startsWith(VERSIONS_DIR)) { 857 throw new InternalError(name); As unlikely as it is, could we hint at what went wrong ? .. ("Can't add package beginning with " + VERSIONS_DIR) some typos : src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java 1076 /** 1077 * Loads a Enum field. src/java.base/share/classes/java/lang/module/ModuleDescriptor.java 1121 * @return {@code true} if this is a open module regards, Sean. On 24/11/2016 15:25, Alan Bateman wrote: > Folks on jigsaw-dev will know that we are on a mission to bring the > changes accumulated in the jake forest to jdk9/dev. We can think of > this as a refresh of the module system in JDK 9, the last big refresh > was in May with many small updates since then. > > The focus this time is to bring the changes that are tied to JSR > issues into jdk9/dev, specifically the issues that are tracked on the > JSR issues list [1] as: > > #CompileTimeDependences > #AddExportsInManifest > #ClassFileModuleName > #ClassFileAccPublic > #ServiceLoaderEnhancements > #ResourceEncapsulation/#ClassFilesAsResources > #ReflectiveAccessToNonExportedTypes > #AwkwardStrongEncapsulation > #ReadabilityAddedByLayerCreator > #IndirectQualifiedReflectiveAccess (partial) > #VersionsInModuleNames > #NonHierarchicalLayers > #ModuleAnnotations/#ModuleDeprecation > #ReflectiveAccessByInstrumentationAgents > > Some of these issues are not "Resolved" yet, meaning there is still > ongoing discussion on the EG mailing list. That is okay, there is > nothing final here. If there are changes to these proposals then the > implementation changes will follow. Also, as I said in a mail to > jigsaw-dev yesterday [2], is that we will keep the jake forest open > for ongoing prototyping and iteration, also ongoing implementation > improvements where iteration or bake time is important. > > For the code review then the focus is therefore on sanity checking the > changes that we would like to bring into jdk9/dev. We will not use > this review thread to debate alternative designs or other big > implementation changes that are more appropriate to bake in jake. > > To get going, I've put the webrevs with a snapshot of the changes in > jake here: > http://cr.openjdk.java.net/~alanb/8169069/0/ > > The changes are currently sync'ed against jdk-9+146 and will be > rebased (and re-tested) against jdk9/dev prior to integration. There > are a number of small changes that need to be added to this in the > coming days, I will refresh the webrev every few days to take account > of these updates. > > > A few important points to mention, even if you aren't reviewing the > changes: > > 1. This refresh requires a new version of jtreg to run the tests. The > changes for this new version are in the code-tools/jtreg repository > and the plan is to tag a new build (jtreg4.2-b04) next week. Once the > tag has been added then we'll update the requiredVersion property in > each TEST.ROOT to force everyone to update. > > 2. For developers trying out modules with the main line JDK 9 builds > then be aware that `requires public` changes to `requires transitive` > and the `provides` clause changes to require all providers for a > specific service type to be in the same clause. Also be aware that the > binary form of the module declaration (module-info.class) changes so > you will need to recompile any modules. > > 3. Those running existing code on JDK 9 and ignoring modules will need > to be aware of a disruptive change in this refresh. The disruptive > change is #AwkwardStrongEncapsulation where setAccessible(true) is > changed so that it can't be used to break into non-public > fields/methods of JDK classes. This change is going to expose a lot of > hacks in existing code. We plan to send mail to jdk9-dev in advance of > this integration to create awareness of this change. As per the > original introduction of strong encapsulation then command line > options (and now the manifest of application JAR files) can be used to > keep existing code working. The new option is `--add-opens` to open a > package in a module for deep reflection by other modules. As an > example, if you find yourself with code that hacks into the private > `comparator` field in java.util.TreeMap then running with `--add-opens > java.base/java.util=ALL-UNNAMED` will keep that code working. > > > A few miscellaneous notes for those that are reviewing: > > 1. We have some temporary/transition code in the top-level repo to > deal with the importing of the JavaFX modules. This will be removed > once the changes are in JDK 9 for the OpenJFX project to use. > > 2. In the jdk repo then it's important to understand that the module > system is initialized at startup and there are many places where we > need to keep startup performance in mind. This sometimes means less > elegant code than might be used if startup wasn't such a big concern. > > 3. The changes in the jaxws repo make use of new APIs that means the > code doesn't compile with JDK 7 or JDK 8. Our intention is to work > with the JAXB and JAX-WS maintainers to address the issues in the > upstream project and then bring those changes into jdk9/dev to replace > the patches that we are forced to push for the short term. > > 4. You will see several tests where the value of the @modules tag has > `:open` or `:+open`. This is new jtreg speak. The former means the > test is run with --add-opens to open the package, the latter means the > test is exported at compile-time and exported + open at run-time (the > latter usage will be rare, it's where tests have static references to > JDK internal types and are also doing deep reflection with > setAccessible). > > > In terms of dates then we are aiming to integrate these changes into > jdk9/dev in early December. I will send a follow-up mail next week on > this as we work through the logistics. > > -Alan > > [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ > [2] > http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html From dmitry.samersoff at oracle.com Tue Nov 29 20:12:16 2016 From: dmitry.samersoff at oracle.com (Dmitry Samersoff) Date: Tue, 29 Nov 2016 23:12:16 +0300 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> <583C4019.8040506@oracle.com> Message-ID: <4606fc5a-6f43-02d9-cb00-bb95fb88e432@oracle.com> Karen, Sorry for delay. I was on vacation last week. I plan to review the changes tomorrow. -Dmitry On 2016-11-28 17:47, Karen Kinnear wrote: > Alan, > > I reviewed all the hotspot runtime changes > - except the tests (Christian will review those) > - and jvmti - which Dmitry Samersoff will review. > > They look good. > > thanks, > Karen > >> On Nov 28, 2016, at 9:32 AM, Lois Foltan wrote: >> >> Hi Alan, >> >> I have reviewed the hotspot changes and they look good. Minor nit, src/share/vm/classfile/javaClasses.cpp only differs by the addition of a blank line. >> >> Thanks, >> Lois >> >> On 11/24/2016 10:25 AM, Alan Bateman wrote: >>> Folks on jigsaw-dev will know that we are on a mission to bring the changes accumulated in the jake forest to jdk9/dev. We can think of this as a refresh of the module system in JDK 9, the last big refresh was in May with many small updates since then. >>> >>> The focus this time is to bring the changes that are tied to JSR issues into jdk9/dev, specifically the issues that are tracked on the JSR issues list [1] as: >>> >>> #CompileTimeDependences >>> #AddExportsInManifest >>> #ClassFileModuleName >>> #ClassFileAccPublic >>> #ServiceLoaderEnhancements >>> #ResourceEncapsulation/#ClassFilesAsResources >>> #ReflectiveAccessToNonExportedTypes >>> #AwkwardStrongEncapsulation >>> #ReadabilityAddedByLayerCreator >>> #IndirectQualifiedReflectiveAccess (partial) >>> #VersionsInModuleNames >>> #NonHierarchicalLayers >>> #ModuleAnnotations/#ModuleDeprecation >>> #ReflectiveAccessByInstrumentationAgents >>> >>> Some of these issues are not "Resolved" yet, meaning there is still ongoing discussion on the EG mailing list. That is okay, there is nothing final here. If there are changes to these proposals then the implementation changes will follow. Also, as I said in a mail to jigsaw-dev yesterday [2], is that we will keep the jake forest open for ongoing prototyping and iteration, also ongoing implementation improvements where iteration or bake time is important. >>> >>> For the code review then the focus is therefore on sanity checking the changes that we would like to bring into jdk9/dev. We will not use this review thread to debate alternative designs or other big implementation changes that are more appropriate to bake in jake. >>> >>> To get going, I've put the webrevs with a snapshot of the changes in jake here: >>> http://cr.openjdk.java.net/~alanb/8169069/0/ >>> >>> The changes are currently sync'ed against jdk-9+146 and will be rebased (and re-tested) against jdk9/dev prior to integration. There are a number of small changes that need to be added to this in the coming days, I will refresh the webrev every few days to take account of these updates. >>> >>> >>> A few important points to mention, even if you aren't reviewing the changes: >>> >>> 1. This refresh requires a new version of jtreg to run the tests. The changes for this new version are in the code-tools/jtreg repository and the plan is to tag a new build (jtreg4.2-b04) next week. Once the tag has been added then we'll update the requiredVersion property in each TEST.ROOT to force everyone to update. >>> >>> 2. For developers trying out modules with the main line JDK 9 builds then be aware that `requires public` changes to `requires transitive` and the `provides` clause changes to require all providers for a specific service type to be in the same clause. Also be aware that the binary form of the module declaration (module-info.class) changes so you will need to recompile any modules. >>> >>> 3. Those running existing code on JDK 9 and ignoring modules will need to be aware of a disruptive change in this refresh. The disruptive change is #AwkwardStrongEncapsulation where setAccessible(true) is changed so that it can't be used to break into non-public fields/methods of JDK classes. This change is going to expose a lot of hacks in existing code. We plan to send mail to jdk9-dev in advance of this integration to create awareness of this change. As per the original introduction of strong encapsulation then command line options (and now the manifest of application JAR files) can be used to keep existing code working. The new option is `--add-opens` to open a package in a module for deep reflection by other modules. As an example, if you find yourself with code that hacks into the private `comparator` field in java.util.TreeMap then running with `--add-opens java.base/java.util=ALL-UNNAMED` will keep that code working. >>> >>> >>> A few miscellaneous notes for those that are reviewing: >>> >>> 1. We have some temporary/transition code in the top-level repo to deal with the importing of the JavaFX modules. This will be removed once the changes are in JDK 9 for the OpenJFX project to use. >>> >>> 2. In the jdk repo then it's important to understand that the module system is initialized at startup and there are many places where we need to keep startup performance in mind. This sometimes means less elegant code than might be used if startup wasn't such a big concern. >>> >>> 3. The changes in the jaxws repo make use of new APIs that means the code doesn't compile with JDK 7 or JDK 8. Our intention is to work with the JAXB and JAX-WS maintainers to address the issues in the upstream project and then bring those changes into jdk9/dev to replace the patches that we are forced to push for the short term. >>> >>> 4. You will see several tests where the value of the @modules tag has `:open` or `:+open`. This is new jtreg speak. The former means the test is run with --add-opens to open the package, the latter means the test is exported at compile-time and exported + open at run-time (the latter usage will be rare, it's where tests have static references to JDK internal types and are also doing deep reflection with setAccessible). >>> >>> >>> In terms of dates then we are aiming to integrate these changes into jdk9/dev in early December. I will send a follow-up mail next week on this as we work through the logistics. >>> >>> -Alan >>> >>> [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ >>> [2] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html >> > -- Dmitry Samersoff Oracle Java development team, Saint Petersburg, Russia * I would love to change the world, but they won't give me the sources. From bsrbnd at gmail.com Tue Nov 29 21:07:47 2016 From: bsrbnd at gmail.com (B. Blaser) Date: Tue, 29 Nov 2016 22:07:47 +0100 Subject: JDK-8147527: Wrong code generated for postfix unary operators In-Reply-To: References: <58382299.4010103@oracle.com> Message-ID: Hi, 2016-11-29 16:28 GMT+01:00 Maurizio Cimadamore : > Looks good to me. Use of shallow clone looks a tad odd - but I understand > why it's the way it is - maybe worth adding a comment? > > Maurizio I agree that a short comment might be helpful, something like: // Shallow clone shall fit JDK-8147527 requirements, according to related threads. Bernard > On 25/11/16 11:38, Jan Lahoda wrote: >> >> Hello, >> >> As noted here: >> >> http://mail.openjdk.java.net/pipermail/compiler-dev/2016-October/010452.html >> >> javac sometimes generates code incorrectly, as discussed further in the >> thread. >> >> The proposed fix is to not reuse the AST nodes on multiple places. >> >> Bug: https://bugs.openjdk.java.net/browse/JDK-8147527 >> Webrev: http://cr.openjdk.java.net/~jlahoda/8147527/webrev.00/ >> >> Any feedback is welcome. >> >> Thanks to Bernard for his work on this. >> >> Jan > > From mandy.chung at oracle.com Tue Nov 29 21:37:19 2016 From: mandy.chung at oracle.com (Mandy Chung) Date: Tue, 29 Nov 2016 13:37:19 -0800 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <583C4019.8040506@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> <583C4019.8040506@oracle.com> Message-ID: Thanks Lois. I removed the blank line. Mandy > On Nov 28, 2016, at 6:32 AM, Lois Foltan wrote: > > Hi Alan, > > I have reviewed the hotspot changes and they look good. Minor nit, src/share/vm/classfile/javaClasses.cpp only differs by the addition of a blank line. > > Thanks, > Lois > > On 11/24/2016 10:25 AM, Alan Bateman wrote: >> Folks on jigsaw-dev will know that we are on a mission to bring the changes accumulated in the jake forest to jdk9/dev. We can think of this as a refresh of the module system in JDK 9, the last big refresh was in May with many small updates since then. >> >> The focus this time is to bring the changes that are tied to JSR issues into jdk9/dev, specifically the issues that are tracked on the JSR issues list [1] as: >> >> #CompileTimeDependences >> #AddExportsInManifest >> #ClassFileModuleName >> #ClassFileAccPublic >> #ServiceLoaderEnhancements >> #ResourceEncapsulation/#ClassFilesAsResources >> #ReflectiveAccessToNonExportedTypes >> #AwkwardStrongEncapsulation >> #ReadabilityAddedByLayerCreator >> #IndirectQualifiedReflectiveAccess (partial) >> #VersionsInModuleNames >> #NonHierarchicalLayers >> #ModuleAnnotations/#ModuleDeprecation >> #ReflectiveAccessByInstrumentationAgents >> >> Some of these issues are not "Resolved" yet, meaning there is still ongoing discussion on the EG mailing list. That is okay, there is nothing final here. If there are changes to these proposals then the implementation changes will follow. Also, as I said in a mail to jigsaw-dev yesterday [2], is that we will keep the jake forest open for ongoing prototyping and iteration, also ongoing implementation improvements where iteration or bake time is important. >> >> For the code review then the focus is therefore on sanity checking the changes that we would like to bring into jdk9/dev. We will not use this review thread to debate alternative designs or other big implementation changes that are more appropriate to bake in jake. >> >> To get going, I've put the webrevs with a snapshot of the changes in jake here: >> http://cr.openjdk.java.net/~alanb/8169069/0/ >> >> The changes are currently sync'ed against jdk-9+146 and will be rebased (and re-tested) against jdk9/dev prior to integration. There are a number of small changes that need to be added to this in the coming days, I will refresh the webrev every few days to take account of these updates. >> >> >> A few important points to mention, even if you aren't reviewing the changes: >> >> 1. This refresh requires a new version of jtreg to run the tests. The changes for this new version are in the code-tools/jtreg repository and the plan is to tag a new build (jtreg4.2-b04) next week. Once the tag has been added then we'll update the requiredVersion property in each TEST.ROOT to force everyone to update. >> >> 2. For developers trying out modules with the main line JDK 9 builds then be aware that `requires public` changes to `requires transitive` and the `provides` clause changes to require all providers for a specific service type to be in the same clause. Also be aware that the binary form of the module declaration (module-info.class) changes so you will need to recompile any modules. >> >> 3. Those running existing code on JDK 9 and ignoring modules will need to be aware of a disruptive change in this refresh. The disruptive change is #AwkwardStrongEncapsulation where setAccessible(true) is changed so that it can't be used to break into non-public fields/methods of JDK classes. This change is going to expose a lot of hacks in existing code. We plan to send mail to jdk9-dev in advance of this integration to create awareness of this change. As per the original introduction of strong encapsulation then command line options (and now the manifest of application JAR files) can be used to keep existing code working. The new option is `--add-opens` to open a package in a module for deep reflection by other modules. As an example, if you find yourself with code that hacks into the private `comparator` field in java.util.TreeMap then running with `--add-opens java.base/java.util=ALL-UNNAMED` will keep that code working. >> >> >> A few miscellaneous notes for those that are reviewing: >> >> 1. We have some temporary/transition code in the top-level repo to deal with the importing of the JavaFX modules. This will be removed once the changes are in JDK 9 for the OpenJFX project to use. >> >> 2. In the jdk repo then it's important to understand that the module system is initialized at startup and there are many places where we need to keep startup performance in mind. This sometimes means less elegant code than might be used if startup wasn't such a big concern. >> >> 3. The changes in the jaxws repo make use of new APIs that means the code doesn't compile with JDK 7 or JDK 8. Our intention is to work with the JAXB and JAX-WS maintainers to address the issues in the upstream project and then bring those changes into jdk9/dev to replace the patches that we are forced to push for the short term. >> >> 4. You will see several tests where the value of the @modules tag has `:open` or `:+open`. This is new jtreg speak. The former means the test is run with --add-opens to open the package, the latter means the test is exported at compile-time and exported + open at run-time (the latter usage will be rare, it's where tests have static references to JDK internal types and are also doing deep reflection with setAccessible). >> >> >> In terms of dates then we are aiming to integrate these changes into jdk9/dev in early December. I will send a follow-up mail next week on this as we work through the logistics. >> >> -Alan >> >> [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ >> [2] http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html > From Alan.Bateman at oracle.com Wed Nov 30 11:13:47 2016 From: Alan.Bateman at oracle.com (Alan Bateman) Date: Wed, 30 Nov 2016 11:13:47 +0000 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> Message-ID: Thanks to everyone that have been reviewing these changes. I've pushed an updated set of webrevs here: http://cr.openjdk.java.net/~alanb/8169069/1/ The update includes changes to address most of the reviewer comments so far. There are a few more cleanups that still need to be pushed today but I think we are otherwise in reasonable shape at this point. As I said in the original mail, we will keep the jake forest open as there are still issues to work on after this integration. -Alan From weijun.wang at oracle.com Wed Nov 30 11:21:29 2016 From: weijun.wang at oracle.com (Wang Weijun) Date: Wed, 30 Nov 2016 19:21:29 +0800 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> Message-ID: <53095bcf-426b-ad18-d4c3-f86a5f009244@oracle.com> test/java/security/testlibrary/Proc.java: if (hasModules) { Stream.of(jdk.internal.misc.VM.getRuntimeArguments()) - .filter(arg -> arg.startsWith("--add-exports=")) + .filter(arg -> arg.startsWith("--add-exports=") || + arg.startsWith("--add-opens")) .forEach(cmd::add); } Maybe "--add-opens=" to be more precise? Thanks Max From erik.joelsson at oracle.com Wed Nov 30 14:30:32 2016 From: erik.joelsson at oracle.com (Erik Joelsson) Date: Wed, 30 Nov 2016 15:30:32 +0100 Subject: RFR: JDK-8168607: langtools/test/Makefile should set -retain:fail,error by default Message-ID: <432cecad-691a-f3d0-b6b3-ef54df6a779b@oracle.com> This patch moves the langtools/test/Makefile one step closer being alignmened with the rest of the test/*/Makefiles by adding the -retain:fail,error jtreg option. Bug: https://bugs.openjdk.java.net/browse/JDK-8168607 Patch: diff -r ab39653a1e6d test/Makefile --- a/test/Makefile +++ b/test/Makefile @@ -161,6 +161,9 @@ JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx768m JTREG_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION) +# Retain all files for failing tests +JTREG_OPTIONS += -retain:fail,error + ifdef EXTRA_JTREG_OPTIONS JTREG_OPTIONS += $(EXTRA_JTREG_OPTIONS) endif /Erik From tim.bell at oracle.com Wed Nov 30 15:25:08 2016 From: tim.bell at oracle.com (Tim Bell) Date: Wed, 30 Nov 2016 07:25:08 -0800 Subject: RFR: JDK-8168607: langtools/test/Makefile should set -retain:fail,error by default In-Reply-To: <432cecad-691a-f3d0-b6b3-ef54df6a779b@oracle.com> References: <432cecad-691a-f3d0-b6b3-ef54df6a779b@oracle.com> Message-ID: Erik: > This patch moves the langtools/test/Makefile one step closer being > alignmened with the rest of the test/*/Makefiles by adding the > -retain:fail,error jtreg option. > > Bug: https://bugs.openjdk.java.net/browse/JDK-8168607 > > Patch: > > diff -r ab39653a1e6d test/Makefile > --- a/test/Makefile > +++ b/test/Makefile > @@ -161,6 +161,9 @@ > JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx768m > JTREG_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION) > > +# Retain all files for failing tests > +JTREG_OPTIONS += -retain:fail,error > + > ifdef EXTRA_JTREG_OPTIONS > JTREG_OPTIONS += $(EXTRA_JTREG_OPTIONS) > endif Thank you, Erik. Looks good. Tim From lois.foltan at oracle.com Mon Nov 28 14:33:04 2016 From: lois.foltan at oracle.com (Lois Foltan) Date: Mon, 28 Nov 2016 14:33:04 -0000 Subject: Code review for jigsaw/jake -> jdk9/dev sync up In-Reply-To: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> References: <6da3ac71-ca2b-3284-576d-055c19a65521@oracle.com> Message-ID: <583C4019.8040506@oracle.com> Hi Alan, I have reviewed the hotspot changes and they look good. Minor nit, src/share/vm/classfile/javaClasses.cpp only differs by the addition of a blank line. Thanks, Lois On 11/24/2016 10:25 AM, Alan Bateman wrote: > Folks on jigsaw-dev will know that we are on a mission to bring the > changes accumulated in the jake forest to jdk9/dev. We can think of > this as a refresh of the module system in JDK 9, the last big refresh > was in May with many small updates since then. > > The focus this time is to bring the changes that are tied to JSR > issues into jdk9/dev, specifically the issues that are tracked on the > JSR issues list [1] as: > > #CompileTimeDependences > #AddExportsInManifest > #ClassFileModuleName > #ClassFileAccPublic > #ServiceLoaderEnhancements > #ResourceEncapsulation/#ClassFilesAsResources > #ReflectiveAccessToNonExportedTypes > #AwkwardStrongEncapsulation > #ReadabilityAddedByLayerCreator > #IndirectQualifiedReflectiveAccess (partial) > #VersionsInModuleNames > #NonHierarchicalLayers > #ModuleAnnotations/#ModuleDeprecation > #ReflectiveAccessByInstrumentationAgents > > Some of these issues are not "Resolved" yet, meaning there is still > ongoing discussion on the EG mailing list. That is okay, there is > nothing final here. If there are changes to these proposals then the > implementation changes will follow. Also, as I said in a mail to > jigsaw-dev yesterday [2], is that we will keep the jake forest open > for ongoing prototyping and iteration, also ongoing implementation > improvements where iteration or bake time is important. > > For the code review then the focus is therefore on sanity checking the > changes that we would like to bring into jdk9/dev. We will not use > this review thread to debate alternative designs or other big > implementation changes that are more appropriate to bake in jake. > > To get going, I've put the webrevs with a snapshot of the changes in > jake here: > http://cr.openjdk.java.net/~alanb/8169069/0/ > > The changes are currently sync'ed against jdk-9+146 and will be > rebased (and re-tested) against jdk9/dev prior to integration. There > are a number of small changes that need to be added to this in the > coming days, I will refresh the webrev every few days to take account > of these updates. > > > A few important points to mention, even if you aren't reviewing the > changes: > > 1. This refresh requires a new version of jtreg to run the tests. The > changes for this new version are in the code-tools/jtreg repository > and the plan is to tag a new build (jtreg4.2-b04) next week. Once the > tag has been added then we'll update the requiredVersion property in > each TEST.ROOT to force everyone to update. > > 2. For developers trying out modules with the main line JDK 9 builds > then be aware that `requires public` changes to `requires transitive` > and the `provides` clause changes to require all providers for a > specific service type to be in the same clause. Also be aware that the > binary form of the module declaration (module-info.class) changes so > you will need to recompile any modules. > > 3. Those running existing code on JDK 9 and ignoring modules will need > to be aware of a disruptive change in this refresh. The disruptive > change is #AwkwardStrongEncapsulation where setAccessible(true) is > changed so that it can't be used to break into non-public > fields/methods of JDK classes. This change is going to expose a lot of > hacks in existing code. We plan to send mail to jdk9-dev in advance of > this integration to create awareness of this change. As per the > original introduction of strong encapsulation then command line > options (and now the manifest of application JAR files) can be used to > keep existing code working. The new option is `--add-opens` to open a > package in a module for deep reflection by other modules. As an > example, if you find yourself with code that hacks into the private > `comparator` field in java.util.TreeMap then running with `--add-opens > java.base/java.util=ALL-UNNAMED` will keep that code working. > > > A few miscellaneous notes for those that are reviewing: > > 1. We have some temporary/transition code in the top-level repo to > deal with the importing of the JavaFX modules. This will be removed > once the changes are in JDK 9 for the OpenJFX project to use. > > 2. In the jdk repo then it's important to understand that the module > system is initialized at startup and there are many places where we > need to keep startup performance in mind. This sometimes means less > elegant code than might be used if startup wasn't such a big concern. > > 3. The changes in the jaxws repo make use of new APIs that means the > code doesn't compile with JDK 7 or JDK 8. Our intention is to work > with the JAXB and JAX-WS maintainers to address the issues in the > upstream project and then bring those changes into jdk9/dev to replace > the patches that we are forced to push for the short term. > > 4. You will see several tests where the value of the @modules tag has > `:open` or `:+open`. This is new jtreg speak. The former means the > test is run with --add-opens to open the package, the latter means the > test is exported at compile-time and exported + open at run-time (the > latter usage will be rare, it's where tests have static references to > JDK internal types and are also doing deep reflection with > setAccessible). > > > In terms of dates then we are aiming to integrate these changes into > jdk9/dev in early December. I will send a follow-up mail next week on > this as we work through the logistics. > > -Alan > > [1] http://openjdk.java.net/projects/jigsaw/spec/issues/ > [2] > http://mail.openjdk.java.net/pipermail/jigsaw-dev/2016-November/010219.html From Jacob.Wieland at spirent.com Thu Nov 24 12:33:12 2016 From: Jacob.Wieland at spirent.com (Wieland, Jacob) Date: Thu, 24 Nov 2016 12:33:12 -0000 Subject: JDK-8162704 Message-ID: Is anybody looking into this very weird issue: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8162704 Bug ID: JDK-8162704 deeply nested expression stumps the compiler-checking algorithm bugs.java.com Component: tools - Sub-Component: javac BR, Jacob Spirent Communications e-mail confidentiality. ------------------------------------------------------------------------ This e-mail contains confidential and / or privileged information belonging to Spirent Communications plc, its affiliates and / or subsidiaries. If you are not the intended recipient, you are hereby notified that any disclosure, copying, distribution and / or the taking of any action based upon reliance on the contents of this transmission is strictly forbidden. If you have received this message in error please notify the sender by return e-mail and delete it from your system. Spirent Communications plc Northwood Park, Gatwick Road, Crawley, West Sussex, RH10 9XN, United Kingdom. Tel No. +44 (0) 1293 767676 Fax No. +44 (0) 1293 767677 Registered in England Number 470893 Registered at Northwood Park, Gatwick Road, Crawley, West Sussex, RH10 9XN, United Kingdom. Or if within the US, Spirent Communications, 27349 Agoura Road, Calabasas, CA, 91301, USA. Tel No. 1-818-676- 2300 -------------- next part -------------- An HTML attachment was scrubbed... URL: