From 5a13097581a05a9440b4c8e54d52c259057ff47e Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Mon, 18 Mar 2024 14:20:09 +0000 Subject: [PATCH] 8327695: [lworld] javac can generate incorrect code in inner class' constructors --- .../com/sun/tools/javac/comp/Lower.java | 15 ++++++++ .../classes/com/sun/tools/javac/jvm/Gen.java | 35 +++++++++++++++++++ .../inlinetypes/TestBasicFunctionality.java | 1 + 3 files changed, 51 insertions(+) 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 index ddf583c2200..e12cff7caaf 100644 --- 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 @@ -190,6 +190,10 @@ protected Lower(Context context) { */ Map lambdaTranslationMap = null; + /** A hash table mapping local classes to a set of outer this fields + */ + public Map> initializerOuterThis = new WeakHashMap<>(); + /** A navigator class for assembling a mapping from local class symbols * to class definition trees. * There is only one case; all other cases simply traverse down the tree. @@ -2958,6 +2962,17 @@ public void visitNewClass(JCNewClass tree) { } else { // nested class thisArg = makeOwnerThis(tree.pos(), c, false); + if (currentMethodSym != null && + ((currentMethodSym.flags_field & (STATIC | BLOCK)) == BLOCK) && + currentMethodSym.owner.isValueClass()) { + // instance initializer in a value class + Set outerThisSet = initializerOuterThis.get(currentClass); + if (outerThisSet == null) { + outerThisSet = new HashSet<>(); + } + outerThisSet.add(thisArg); + initializerOuterThis.put(currentClass, outerThisSet); + } } tree.args = tree.args.prepend(thisArg); } 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 index 33e2243a23b..444156bd352 100644 --- 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 @@ -558,6 +558,7 @@ void normalizeMethod(JCMethodDecl md, List initCode, List make.Block(0, initCode.append(supercall).appendList(initBlocks))); } else { TreeInfo.mapSuperCalls(md.body, supercall -> make.Block(0, initCode.prepend(supercall))); @@ -570,6 +571,40 @@ void normalizeMethod(JCMethodDecl md, List initCode, List initCode) { + if (lower.initializerOuterThis.containsKey(md.sym.owner)) { + InitializerVisitor initializerVisitor = new InitializerVisitor(md, lower.initializerOuterThis.get(md.sym.owner)); + for (JCStatement init : initCode) { + initializerVisitor.scan(init); + } + } + } + + class InitializerVisitor extends TreeScanner { + JCMethodDecl md; + Set exprSet; + + InitializerVisitor(JCMethodDecl md, Set exprSet) { + this.md = md; + this.exprSet = exprSet; + } + + @Override + public void visitTree(JCTree tree) {} + + @Override + public void visitIdent(JCIdent tree) { + if (exprSet.contains(tree)) { + for (JCVariableDecl param: md.params) { + if (param.name == tree.name && + ((param.sym.flags_field & (MANDATED | NOOUTERTHIS)) == (MANDATED | NOOUTERTHIS))) { + tree.sym = param.sym; + } + } + } + } + } + /* ************************************************************************ * Traversal methods *************************************************************************/ diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java index 8c813683835..24843a65901 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java @@ -39,6 +39,7 @@ /* * @test * @key randomness + * @bug 8327695 * @summary Test the basic value class implementation in C2. * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64") * @modules java.base/jdk.internal.value