Thu, 29 Nov 2012 09:41:48 +0000
7153958: add constant pool reference to class containing inlined constants
Reviewed-by: jjg, mcimadamore
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Nov 23 15:13:45 2012 +0000 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Thu Nov 29 09:41:48 2012 +0000 1.3 @@ -138,6 +138,10 @@ 1.4 */ 1.5 Map<ClassSymbol, JCClassDecl> classdefs; 1.6 1.7 + /** A hash table mapping local classes to a list of pruned trees. 1.8 + */ 1.9 + public Map<ClassSymbol, List<JCTree>> prunedTree = new WeakHashMap<ClassSymbol, List<JCTree>>(); 1.10 + 1.11 /** A hash table mapping virtual accessed symbols in outer subclasses 1.12 * to the actually referred symbol in superclasses. 1.13 */ 1.14 @@ -1039,6 +1043,12 @@ 1.15 } 1.16 } 1.17 1.18 + private void addPrunedInfo(JCTree tree) { 1.19 + List<JCTree> infoList = prunedTree.get(currentClass); 1.20 + infoList = (infoList == null) ? List.of(tree) : infoList.prepend(tree); 1.21 + prunedTree.put(currentClass, infoList); 1.22 + } 1.23 + 1.24 /** Ensure that identifier is accessible, return tree accessing the identifier. 1.25 * @param sym The accessed symbol. 1.26 * @param tree The tree referring to the symbol. 1.27 @@ -1111,7 +1121,10 @@ 1.28 // Constants are replaced by their constant value. 1.29 if (sym.kind == VAR) { 1.30 Object cv = ((VarSymbol)sym).getConstValue(); 1.31 - if (cv != null) return makeLit(sym.type, cv); 1.32 + if (cv != null) { 1.33 + addPrunedInfo(tree); 1.34 + return makeLit(sym.type, cv); 1.35 + } 1.36 } 1.37 1.38 // Private variables and methods are replaced by calls 1.39 @@ -2746,12 +2759,15 @@ 1.40 1.41 /** Visitor method for conditional expressions. 1.42 */ 1.43 + @Override 1.44 public void visitConditional(JCConditional tree) { 1.45 JCTree cond = tree.cond = translate(tree.cond, syms.booleanType); 1.46 if (cond.type.isTrue()) { 1.47 result = convert(translate(tree.truepart, tree.type), tree.type); 1.48 + addPrunedInfo(cond); 1.49 } else if (cond.type.isFalse()) { 1.50 result = convert(translate(tree.falsepart, tree.type), tree.type); 1.51 + addPrunedInfo(cond); 1.52 } else { 1.53 // Condition is not a compile-time constant. 1.54 tree.truepart = translate(tree.truepart, tree.type); 1.55 @@ -2760,14 +2776,14 @@ 1.56 } 1.57 } 1.58 //where 1.59 - private JCTree convert(JCTree tree, Type pt) { 1.60 - if (tree.type == pt || tree.type.hasTag(BOT)) 1.61 - return tree; 1.62 - JCTree result = make_at(tree.pos()).TypeCast(make.Type(pt), (JCExpression)tree); 1.63 - result.type = (tree.type.constValue() != null) ? cfolder.coerce(tree.type, pt) 1.64 - : pt; 1.65 - return result; 1.66 - } 1.67 + private JCTree convert(JCTree tree, Type pt) { 1.68 + if (tree.type == pt || tree.type.hasTag(BOT)) 1.69 + return tree; 1.70 + JCTree result = make_at(tree.pos()).TypeCast(make.Type(pt), (JCExpression)tree); 1.71 + result.type = (tree.type.constValue() != null) ? cfolder.coerce(tree.type, pt) 1.72 + : pt; 1.73 + return result; 1.74 + } 1.75 1.76 /** Visitor method for if statements. 1.77 */ 1.78 @@ -2775,12 +2791,14 @@ 1.79 JCTree cond = tree.cond = translate(tree.cond, syms.booleanType); 1.80 if (cond.type.isTrue()) { 1.81 result = translate(tree.thenpart); 1.82 + addPrunedInfo(cond); 1.83 } else if (cond.type.isFalse()) { 1.84 if (tree.elsepart != null) { 1.85 result = translate(tree.elsepart); 1.86 } else { 1.87 result = make.Skip(); 1.88 } 1.89 + addPrunedInfo(cond); 1.90 } else { 1.91 // Condition is not a compile-time constant. 1.92 tree.thenpart = translate(tree.thenpart);
2.1 --- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Nov 23 15:13:45 2012 +0000 2.2 +++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java Thu Nov 29 09:41:48 2012 +0000 2.3 @@ -71,6 +71,7 @@ 2.4 private final Map<Type,Symbol> stringBufferAppend; 2.5 private Name accessDollar; 2.6 private final Types types; 2.7 + private final Lower lower; 2.8 2.9 /** Switch: GJ mode? 2.10 */ 2.11 @@ -112,6 +113,7 @@ 2.12 stringBufferAppend = new HashMap<Type,Symbol>(); 2.13 accessDollar = names. 2.14 fromString("access" + target.syntheticNameChar()); 2.15 + lower = Lower.instance(context); 2.16 2.17 Options options = Options.instance(context); 2.18 lineDebugInfo = 2.19 @@ -816,6 +818,62 @@ 2.20 } 2.21 } 2.22 2.23 + /** Visitor class for expressions which might be constant expressions. 2.24 + * This class is a subset of TreeScanner. Intended to visit trees pruned by 2.25 + * Lower as long as constant expressions looking for references to any 2.26 + * ClassSymbol. Any such reference will be added to the constant pool so 2.27 + * automated tools can detect class dependencies better. 2.28 + */ 2.29 + class ClassReferenceVisitor extends JCTree.Visitor { 2.30 + 2.31 + @Override 2.32 + public void visitTree(JCTree tree) {} 2.33 + 2.34 + @Override 2.35 + public void visitBinary(JCBinary tree) { 2.36 + tree.lhs.accept(this); 2.37 + tree.rhs.accept(this); 2.38 + } 2.39 + 2.40 + @Override 2.41 + public void visitSelect(JCFieldAccess tree) { 2.42 + if (tree.selected.type.hasTag(CLASS)) { 2.43 + makeRef(tree.selected.pos(), tree.selected.type); 2.44 + } 2.45 + } 2.46 + 2.47 + @Override 2.48 + public void visitIdent(JCIdent tree) { 2.49 + if (tree.sym.owner instanceof ClassSymbol) { 2.50 + pool.put(tree.sym.owner); 2.51 + } 2.52 + } 2.53 + 2.54 + @Override 2.55 + public void visitConditional(JCConditional tree) { 2.56 + tree.cond.accept(this); 2.57 + tree.truepart.accept(this); 2.58 + tree.falsepart.accept(this); 2.59 + } 2.60 + 2.61 + @Override 2.62 + public void visitUnary(JCUnary tree) { 2.63 + tree.arg.accept(this); 2.64 + } 2.65 + 2.66 + @Override 2.67 + public void visitParens(JCParens tree) { 2.68 + tree.expr.accept(this); 2.69 + } 2.70 + 2.71 + @Override 2.72 + public void visitTypeCast(JCTypeCast tree) { 2.73 + tree.expr.accept(this); 2.74 + } 2.75 + } 2.76 + 2.77 + private ClassReferenceVisitor classReferenceVisitor = new ClassReferenceVisitor(); 2.78 + 2.79 /** Visitor method: generate code for an expression, catching and reporting 2.80 * any completion failures. 2.81 * @param tree The expression to be visited. 2.82 @@ -826,6 +884,7 @@ 2.83 try { 2.84 if (tree.type.constValue() != null) { 2.85 // Short circuit any expressions which are constants 2.86 + tree.accept(classReferenceVisitor); 2.87 checkStringConstant(tree.pos(), tree.type.constValue()); 2.88 result = items.makeImmediateItem(tree.type, tree.type.constValue()); 2.89 } else { 2.90 @@ -2205,6 +2264,15 @@ 2.91 code.endScopes(limit); 2.92 } 2.93 2.94 + private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) { 2.95 + List<JCTree> prunedInfo = lower.prunedTree.get(classSymbol); 2.96 + if (prunedInfo != null) { 2.97 + for (JCTree prunedTree: prunedInfo) { 2.98 + prunedTree.accept(classReferenceVisitor); 2.99 + } 2.100 + } 2.101 + } 2.102 + 2.103 /* ************************************************************************ 2.104 * main method 2.105 *************************************************************************/ 2.106 @@ -2232,6 +2300,7 @@ 2.107 cdef.defs = normalizeDefs(cdef.defs, c); 2.108 c.pool = pool; 2.109 pool.reset(); 2.110 + generateReferencesToPrunedTree(c, pool); 2.111 Env<GenContext> localEnv = 2.112 new Env<GenContext>(cdef, new GenContext()); 2.113 localEnv.toplevel = env.toplevel;
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/7153958/CPoolRefClassContainingInlinedCts.java Thu Nov 29 09:41:48 2012 +0000 3.3 @@ -0,0 +1,134 @@ 3.4 +/* 3.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. Oracle designates this 3.11 + * particular file as subject to the "Classpath" exception as provided 3.12 + * by Oracle in the LICENSE file that accompanied this code. 3.13 + * 3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.17 + * version 2 for more details (a copy is included in the LICENSE file that 3.18 + * accompanied this code). 3.19 + * 3.20 + * You should have received a copy of the GNU General Public License version 3.21 + * 2 along with this work; if not, write to the Free Software Foundation, 3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.23 + * 3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.25 + * or visit www.oracle.com if you need additional information or have any 3.26 + * questions. 3.27 + */ 3.28 + 3.29 +/* 3.30 + * @test 3.31 + * @bug 7153958 3.32 + * @summary add constant pool reference to class containing inlined constants 3.33 + * @compile pkg/ClassToBeStaticallyImported.java 3.34 + * @run main CPoolRefClassContainingInlinedCts 3.35 + */ 3.36 + 3.37 +import com.sun.tools.classfile.ClassFile; 3.38 +import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info; 3.39 +import com.sun.tools.classfile.ConstantPool.CPInfo; 3.40 +import com.sun.tools.classfile.ConstantPoolException; 3.41 +import java.io.File; 3.42 +import java.io.IOException; 3.43 + 3.44 +import static pkg.ClassToBeStaticallyImported.staticField; 3.45 + 3.46 +public class CPoolRefClassContainingInlinedCts { 3.47 + 3.48 + public static void main(String args[]) throws Exception { 3.49 + new CPoolRefClassContainingInlinedCts().run(); 3.50 + } 3.51 + 3.52 + void run() throws Exception { 3.53 + checkReferences(); 3.54 + } 3.55 + 3.56 + int numberOfReferencedClassesToBeChecked = 0; 3.57 + 3.58 + void checkClassName(String className) { 3.59 + switch (className) { 3.60 + case "SimpleAssignClass" : case "BinaryExpClass": 3.61 + case "UnaryExpClass" : case "CastClass": 3.62 + case "ParensClass" : case "CondClass": 3.63 + case "IfClass" : case "pkg/ClassToBeStaticallyImported": 3.64 + numberOfReferencedClassesToBeChecked++; 3.65 + } 3.66 + } 3.67 + 3.68 + void checkReferences() throws IOException, ConstantPoolException { 3.69 + File testClasses = new File(System.getProperty("test.classes")); 3.70 + File file = new File(testClasses, 3.71 + CPoolRefClassContainingInlinedCts.class.getName() + ".class"); 3.72 + ClassFile classFile = ClassFile.read(file); 3.73 + int i = 1; 3.74 + CPInfo cpInfo; 3.75 + while (i < classFile.constant_pool.size()) { 3.76 + cpInfo = classFile.constant_pool.get(i); 3.77 + if (cpInfo instanceof CONSTANT_Class_info) { 3.78 + checkClassName(((CONSTANT_Class_info)cpInfo).getName()); 3.79 + } 3.80 + i += cpInfo.size(); 3.81 + } 3.82 + if (numberOfReferencedClassesToBeChecked != 8) { 3.83 + throw new AssertionError("Class reference missing in the constant pool"); 3.84 + } 3.85 + } 3.86 + 3.87 + private int assign = SimpleAssignClass.x; 3.88 + private int binary = BinaryExpClass.x + 1; 3.89 + private int unary = -UnaryExpClass.x; 3.90 + private int cast = (int)CastClass.x; 3.91 + private int parens = (ParensClass.x); 3.92 + private int cond = (CondClass.x == 1) ? 1 : 2; 3.93 + private static int ifConstant; 3.94 + private static int importStatic; 3.95 + static { 3.96 + if (IfClass.x == 1) { 3.97 + ifConstant = 1; 3.98 + } else { 3.99 + ifConstant = 2; 3.100 + } 3.101 + } 3.102 + static { 3.103 + if (staticField == 1) { 3.104 + importStatic = 1; 3.105 + } else { 3.106 + importStatic = 2; 3.107 + } 3.108 + } 3.109 +} 3.110 + 3.111 +class SimpleAssignClass { 3.112 + public static final int x = 1; 3.113 +} 3.114 + 3.115 +class BinaryExpClass { 3.116 + public static final int x = 1; 3.117 +} 3.118 + 3.119 +class UnaryExpClass { 3.120 + public static final int x = 1; 3.121 +} 3.122 + 3.123 +class CastClass { 3.124 + public static final int x = 1; 3.125 +} 3.126 + 3.127 +class ParensClass { 3.128 + public static final int x = 1; 3.129 +} 3.130 + 3.131 +class CondClass { 3.132 + public static final int x = 1; 3.133 +} 3.134 + 3.135 +class IfClass { 3.136 + public static final int x = 1; 3.137 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/tools/javac/7153958/pkg/ClassToBeStaticallyImported.java Thu Nov 29 09:41:48 2012 +0000 4.3 @@ -0,0 +1,29 @@ 4.4 +/* 4.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. Oracle designates this 4.11 + * particular file as subject to the "Classpath" exception as provided 4.12 + * by Oracle in the LICENSE file that accompanied this code. 4.13 + * 4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.17 + * version 2 for more details (a copy is included in the LICENSE file that 4.18 + * accompanied this code). 4.19 + * 4.20 + * You should have received a copy of the GNU General Public License version 4.21 + * 2 along with this work; if not, write to the Free Software Foundation, 4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.23 + * 4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.25 + * or visit www.oracle.com if you need additional information or have any 4.26 + * questions. 4.27 + */ 4.28 +package pkg; 4.29 + 4.30 +public class ClassToBeStaticallyImported { 4.31 + public static final int staticField = 1; 4.32 +}