mirror of
https://github.com/openjdk/jdk.git
synced 2026-08-07 08:33:59 +00:00
8388338: javac shares proxy initializer trees across constructors
Reviewed-by: liach, mcimadamore
This commit is contained in:
parent
d5336eb3f9
commit
a935581a4d
@ -26,18 +26,17 @@
|
||||
package com.sun.tools.javac.comp;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||
import com.sun.tools.javac.code.Symtab;
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.code.Types;
|
||||
import com.sun.tools.javac.tree.JCTree.JCAssign;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
@ -91,6 +90,7 @@ public class LocalProxyVarsGen {
|
||||
private final Target target;
|
||||
private TreeMaker make;
|
||||
private final Map<Symbol, Set<Symbol>> fieldsReadInPrologue = new HashMap<>();
|
||||
private final Map<JCMethodDecl, Map<JCTree, JCTree>> rollback = new HashMap<>();
|
||||
|
||||
private final boolean noLocalProxyVars;
|
||||
|
||||
@ -136,7 +136,7 @@ public class LocalProxyVarsGen {
|
||||
}
|
||||
}
|
||||
|
||||
public void allFieldNormalized(Symbol.ClassSymbol csym) {
|
||||
public void classGenerated(ClassSymbol csym) {
|
||||
fieldsReadInPrologue.remove(csym);
|
||||
}
|
||||
|
||||
@ -164,6 +164,7 @@ public class LocalProxyVarsGen {
|
||||
for (JCStatement st : constructor.body.stats) {
|
||||
newBody = newBody.append(fieldRewriter.translate(st));
|
||||
}
|
||||
rollback.put(constructor, fieldRewriter.rollback);
|
||||
localDeclarations.addAll(newBody);
|
||||
ListBuffer<JCStatement> assigmentsBeforeSuper = new ListBuffer<>();
|
||||
for (Symbol vsym : fieldToLocalMap.keySet()) {
|
||||
@ -207,7 +208,27 @@ public class LocalProxyVarsGen {
|
||||
return names.fromString("local" + target.syntheticNameChar() + name);
|
||||
}
|
||||
|
||||
public void unpatchConstructor(JCMethodDecl tree, TreeMaker make) {
|
||||
Map<JCTree, JCTree> thisMethodRollback = rollback.remove(tree);
|
||||
|
||||
if (thisMethodRollback == null) {
|
||||
return ;
|
||||
}
|
||||
|
||||
new TreeTranslator() {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends JCTree> T translate(T tree) {
|
||||
if (tree != null && thisMethodRollback.containsKey(tree)) {
|
||||
return (T) thisMethodRollback.get(tree);
|
||||
}
|
||||
return super.translate(tree);
|
||||
}
|
||||
}.translate(tree.body);
|
||||
}
|
||||
|
||||
class FieldRewriter extends TreeTranslator {
|
||||
Map<JCTree, JCTree> rollback = new HashMap<>();
|
||||
JCMethodDecl md;
|
||||
Map<Symbol, Symbol> fieldToLocalMap;
|
||||
boolean ctorPrologue = true;
|
||||
@ -221,6 +242,7 @@ public class LocalProxyVarsGen {
|
||||
public void visitIdent(JCTree.JCIdent tree) {
|
||||
if (ctorPrologue && fieldToLocalMap.get(tree.sym) != null) {
|
||||
result = make.at(md).Ident(fieldToLocalMap.get(tree.sym));
|
||||
rollback.put(result, tree);
|
||||
} else {
|
||||
result = tree;
|
||||
}
|
||||
@ -231,6 +253,7 @@ public class LocalProxyVarsGen {
|
||||
super.visitSelect(tree);
|
||||
if (ctorPrologue && fieldToLocalMap.get(tree.sym) != null) {
|
||||
result = make.at(md).Ident(fieldToLocalMap.get(tree.sym));
|
||||
rollback.put(result, tree);
|
||||
} else {
|
||||
result = tree;
|
||||
}
|
||||
|
||||
@ -493,7 +493,6 @@ public class Gen extends JCTree.Visitor {
|
||||
for (JCTree t : methodDefs) {
|
||||
normalizeMethod((JCMethodDecl)t, initCode.toList(), initBlocks.toList(), initTAlist);
|
||||
}
|
||||
localProxyVarsGen.allFieldNormalized(classDecl.sym);
|
||||
// If there are class initializers, create a <clinit> method
|
||||
// that contains them as its body.
|
||||
if (clinitCode.length() != 0) {
|
||||
@ -570,8 +569,6 @@ public class Gen extends JCTree.Visitor {
|
||||
md.sym.appendUniqueTypeAttributes(initTAs);
|
||||
}
|
||||
|
||||
localProxyVarsGen.patchConstructor(md, make);
|
||||
|
||||
if (md.body.bracePos == Position.NOPOS)
|
||||
md.body.bracePos = TreeInfo.endPos(md.body.stats.last());
|
||||
}
|
||||
@ -981,6 +978,7 @@ public class Gen extends JCTree.Visitor {
|
||||
int extras = 0;
|
||||
// Count up extra parameters
|
||||
if (meth.isConstructor()) {
|
||||
localProxyVarsGen.patchConstructor(tree, make);
|
||||
extras++;
|
||||
if (meth.enclClass().isInner() &&
|
||||
!meth.enclClass().isStatic()) {
|
||||
@ -1052,6 +1050,9 @@ public class Gen extends JCTree.Visitor {
|
||||
// Fill in type annotation positions for exception parameters
|
||||
code.fillExceptionParameterPositions();
|
||||
}
|
||||
if (meth.isConstructor()) {
|
||||
localProxyVarsGen.unpatchConstructor(tree, make);
|
||||
}
|
||||
}
|
||||
|
||||
private int initCode(JCMethodDecl tree, Env<GenContext> env, boolean fatcode) {
|
||||
@ -2567,6 +2568,7 @@ public class Gen extends JCTree.Visitor {
|
||||
}
|
||||
}
|
||||
cdef.defs = List.nil(); // discard trees
|
||||
localProxyVarsGen.classGenerated(c);
|
||||
return nerrs == 0;
|
||||
} finally {
|
||||
// note: this method does NOT support recursion.
|
||||
|
||||
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @enablePreview
|
||||
* @compile LocalProxyVariablesRuntime.java
|
||||
* @run main LocalProxyVariablesRuntime
|
||||
*/
|
||||
public class LocalProxyVariablesRuntime {
|
||||
public static void main(String... args) {
|
||||
new Value1();
|
||||
new Value1(0);
|
||||
new Value2();
|
||||
new Value2(0);
|
||||
new Value3();
|
||||
new Value3(0);
|
||||
new Value4();
|
||||
new Value4(0);
|
||||
}
|
||||
|
||||
private static value class Value1 {
|
||||
int i = 0;
|
||||
int j = i + 1;
|
||||
|
||||
public Value1() {}
|
||||
|
||||
public Value1(int x) {}
|
||||
}
|
||||
|
||||
private static value class Value2 {
|
||||
Object f1 = new String("");
|
||||
String f2 = f1 instanceof String s ? s : "";
|
||||
|
||||
public Value2() {}
|
||||
|
||||
public Value2(int x) {}
|
||||
}
|
||||
|
||||
private static value class Value3 {
|
||||
Object f1 = new String("");
|
||||
String f2 = !switch (f1) {
|
||||
case String s -> true;
|
||||
default -> false;
|
||||
} ? "a" : "b";
|
||||
|
||||
public Value3() {}
|
||||
|
||||
public Value3(int x) {}
|
||||
}
|
||||
|
||||
private static value class Value4 {
|
||||
Object f1 = new String("");
|
||||
String f2 = switch (0) {
|
||||
default -> {
|
||||
boolean r;
|
||||
switch (f1) {
|
||||
case String s:
|
||||
r = true;
|
||||
break;
|
||||
default:
|
||||
r = false;
|
||||
break;
|
||||
}
|
||||
IF: if (true) break IF;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (i < 5) continue;
|
||||
System.err.println(i);
|
||||
}
|
||||
yield r;
|
||||
}
|
||||
} ? "a" : "b";
|
||||
|
||||
public Value4() {}
|
||||
|
||||
public Value4(int x) {}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user