Fri, 05 Sep 2014 16:28:17 +0200
8057588: Lots of trivial (empty) classes were generated by the Nashorn compiler as part of restOf-method generation
Reviewed-by: attila, sundar, hannesw
1.1 --- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java Fri Sep 05 16:28:02 2014 +0200 1.2 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java Fri Sep 05 16:28:17 2014 +0200 1.3 @@ -48,10 +48,12 @@ 1.4 import java.util.Map; 1.5 import java.util.Map.Entry; 1.6 import java.util.Set; 1.7 + 1.8 import jdk.nashorn.internal.AssertsEnabled; 1.9 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; 1.10 import jdk.nashorn.internal.ir.FunctionNode; 1.11 import jdk.nashorn.internal.ir.FunctionNode.CompilationState; 1.12 +import jdk.nashorn.internal.ir.CompileUnitHolder; 1.13 import jdk.nashorn.internal.ir.LexicalContext; 1.14 import jdk.nashorn.internal.ir.LiteralNode; 1.15 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; 1.16 @@ -301,6 +303,71 @@ 1.17 }, 1.18 1.19 /** 1.20 + * Mark compile units used in the method tree. Used for non-rest compilation only 1.21 + */ 1.22 + MARK_USED_COMPILE_UNITS( 1.23 + EnumSet.of( 1.24 + INITIALIZED, 1.25 + PARSED, 1.26 + CONSTANT_FOLDED, 1.27 + LOWERED, 1.28 + BUILTINS_TRANSFORMED, 1.29 + SPLIT, 1.30 + SYMBOLS_ASSIGNED, 1.31 + SCOPE_DEPTHS_COMPUTED, 1.32 + OPTIMISTIC_TYPES_ASSIGNED, 1.33 + LOCAL_VARIABLE_TYPES_CALCULATED)) { 1.34 + 1.35 + @Override 1.36 + FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) { 1.37 + final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { 1.38 + private void tagUsed(final CompileUnitHolder node) { 1.39 + assert node.getCompileUnit() != null : "no compile unit in " + node; 1.40 + node.getCompileUnit().setUsed(); 1.41 + } 1.42 + 1.43 + @Override 1.44 + public Node leaveFunctionNode(final FunctionNode node) { 1.45 + tagUsed(node); 1.46 + return node; 1.47 + } 1.48 + 1.49 + @Override 1.50 + public Node leaveSplitNode(final SplitNode node) { 1.51 + tagUsed(node); 1.52 + return node; 1.53 + } 1.54 + 1.55 + @Override 1.56 + public Node leaveLiteralNode(final LiteralNode<?> node) { 1.57 + if (node instanceof ArrayLiteralNode) { 1.58 + final ArrayLiteralNode aln = (ArrayLiteralNode)node; 1.59 + if (aln.getUnits() != null) { 1.60 + for (final ArrayUnit au : aln.getUnits()) { 1.61 + tagUsed(au); 1.62 + } 1.63 + } 1.64 + return aln; 1.65 + } 1.66 + return node; 1.67 + } 1.68 + 1.69 + @Override 1.70 + public Node leaveDefault(final Node node) { 1.71 + return node.ensureUniqueLabels(lc); 1.72 + } 1.73 + }); 1.74 + 1.75 + return newFunctionNode; 1.76 + } 1.77 + 1.78 + @Override 1.79 + public String toString() { 1.80 + return "'Tag Compile Units Used'"; 1.81 + } 1.82 + }, 1.83 + 1.84 + /** 1.85 * Reuse compile units, if they are already present. We are using the same compiler 1.86 * to recompile stuff 1.87 */ 1.88 @@ -358,6 +425,7 @@ 1.89 assert newUnit != null : "old unit has no mapping to new unit " + oldUnit; 1.90 1.91 log.fine("Replacing compile unit: ", oldUnit, " => ", newUnit, " in ", quote(node.getName())); 1.92 + newUnit.setUsed(); 1.93 return node.setCompileUnit(lc, newUnit).setState(lc, CompilationState.COMPILE_UNITS_REUSED); 1.94 } 1.95 1.96 @@ -370,6 +438,7 @@ 1.97 assert newUnit != null : "old unit has no mapping to new unit " + oldUnit; 1.98 1.99 log.fine("Replacing compile unit: ", oldUnit, " => ", newUnit, " in ", quote(node.getName())); 1.100 + newUnit.setUsed(); 1.101 return node.setCompileUnit(lc, newUnit); 1.102 } 1.103 1.104 @@ -384,6 +453,7 @@ 1.105 for (final ArrayUnit au : aln.getUnits()) { 1.106 final CompileUnit newUnit = map.get(au.getCompileUnit()); 1.107 assert newUnit != null; 1.108 + newUnit.setUsed(); 1.109 newArrayUnits.add(new ArrayUnit(newUnit, au.getLo(), au.getHi())); 1.110 } 1.111 return aln.setUnits(lc, newArrayUnits); 1.112 @@ -452,6 +522,11 @@ 1.113 } 1.114 1.115 for (final CompileUnit compileUnit : compiler.getCompileUnits()) { 1.116 + if (!compileUnit.isUsed()) { 1.117 + compiler.getLogger().fine("Skipping unused compile unit ", compileUnit); 1.118 + continue; 1.119 + } 1.120 + 1.121 final ClassEmitter classEmitter = compileUnit.getClassEmitter(); 1.122 classEmitter.end(); 1.123 1.124 @@ -459,7 +534,6 @@ 1.125 assert bytecode != null; 1.126 1.127 final String className = compileUnit.getUnitClassName(); 1.128 - 1.129 compiler.addClass(className, bytecode); 1.130 1.131 // should we verify the generated code? 1.132 @@ -536,6 +610,9 @@ 1.133 1.134 // initialize function in the compile units 1.135 for (final CompileUnit unit : compiler.getCompileUnits()) { 1.136 + if (!unit.isUsed()) { 1.137 + continue; 1.138 + } 1.139 unit.setCode(installedClasses.get(unit.getUnitClassName())); 1.140 } 1.141
2.1 --- a/src/jdk/nashorn/internal/codegen/CompileUnit.java Fri Sep 05 16:28:02 2014 +0200 2.2 +++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java Fri Sep 05 16:28:17 2014 +0200 2.3 @@ -42,6 +42,8 @@ 2.4 2.5 private Class<?> clazz; 2.6 2.7 + private boolean isUsed; 2.8 + 2.9 CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) { 2.10 this.className = className; 2.11 this.weight = initialWeight; 2.12 @@ -53,6 +55,21 @@ 2.13 } 2.14 2.15 /** 2.16 + * Check if this compile unit is used 2.17 + * @return true if tagged as in use - i.e active code that needs to be generated 2.18 + */ 2.19 + public boolean isUsed() { 2.20 + return isUsed; 2.21 + } 2.22 + 2.23 + /** 2.24 + * Tag this compile unit as used 2.25 + */ 2.26 + public void setUsed() { 2.27 + this.isUsed = true; 2.28 + } 2.29 + 2.30 + /** 2.31 * Return the class that contains the code for this unit, null if not 2.32 * generated yet 2.33 *
3.1 --- a/src/jdk/nashorn/internal/codegen/Compiler.java Fri Sep 05 16:28:02 2014 +0200 3.2 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Fri Sep 05 16:28:17 2014 +0200 3.3 @@ -173,13 +173,14 @@ 3.4 CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE, 3.5 CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE, 3.6 CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE, 3.7 + CompilationPhase.MARK_USED_COMPILE_UNITS, 3.8 CompilationPhase.BYTECODE_GENERATION_PHASE, 3.9 CompilationPhase.INSTALL_PHASE 3.10 }); 3.11 3.12 /** Compile all for a rest of method */ 3.13 public final static CompilationPhases COMPILE_ALL_RESTOF = 3.14 - COMPILE_ALL.setDescription("Compile all, rest of").addAfter(CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE, CompilationPhase.REUSE_COMPILE_UNITS_PHASE); 3.15 + COMPILE_ALL.setDescription("Compile all, rest of").replace(CompilationPhase.MARK_USED_COMPILE_UNITS, CompilationPhase.REUSE_COMPILE_UNITS_PHASE); 3.16 3.17 /** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */ 3.18 public final static CompilationPhases COMPILE_ALL_NO_INSTALL = 3.19 @@ -250,6 +251,15 @@ 3.20 return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()])); 3.21 } 3.22 3.23 + private CompilationPhases replace(final CompilationPhase phase, final CompilationPhase newPhase) { 3.24 + final LinkedList<CompilationPhase> list = new LinkedList<>(); 3.25 + for (final CompilationPhase p : phases) { 3.26 + list.add(p == phase ? newPhase : p); 3.27 + } 3.28 + return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()])); 3.29 + } 3.30 + 3.31 + @SuppressWarnings("unused") //TODO I'll use this soon 3.32 private CompilationPhases addAfter(final CompilationPhase phase, final CompilationPhase newPhase) { 3.33 final LinkedList<CompilationPhase> list = new LinkedList<>(); 3.34 for (final CompilationPhase p : phases) {
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/jdk/nashorn/internal/ir/CompileUnitHolder.java Fri Sep 05 16:28:17 2014 +0200 4.3 @@ -0,0 +1,40 @@ 4.4 +/* 4.5 + * Copyright (c) 2010, 2013, 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 + 4.29 +package jdk.nashorn.internal.ir; 4.30 + 4.31 +import jdk.nashorn.internal.codegen.CompileUnit; 4.32 + 4.33 +/** 4.34 + * Marker interface for things in the IR that can hold compile units. 4.35 + * {@link CompileUnit} 4.36 + */ 4.37 +public interface CompileUnitHolder { 4.38 + /** 4.39 + * Return the compile unit held by this instance 4.40 + * @return compile unit 4.41 + */ 4.42 + public CompileUnit getCompileUnit(); 4.43 +}
5.1 --- a/src/jdk/nashorn/internal/ir/FunctionNode.java Fri Sep 05 16:28:02 2014 +0200 5.2 +++ b/src/jdk/nashorn/internal/ir/FunctionNode.java Fri Sep 05 16:28:17 2014 +0200 5.3 @@ -34,10 +34,8 @@ 5.4 5.5 import java.util.Collections; 5.6 import java.util.EnumSet; 5.7 -import java.util.HashSet; 5.8 import java.util.Iterator; 5.9 import java.util.List; 5.10 -import java.util.Set; 5.11 import java.util.function.Function; 5.12 import jdk.nashorn.internal.AssertsEnabled; 5.13 import jdk.nashorn.internal.codegen.CompileUnit; 5.14 @@ -58,7 +56,7 @@ 5.15 * IR representation for function (or script.) 5.16 */ 5.17 @Immutable 5.18 -public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode> { 5.19 +public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder { 5.20 /** Type used for all FunctionNodes */ 5.21 public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class); 5.22 5.23 @@ -1158,6 +1156,7 @@ 5.24 * @see Compiler 5.25 * @return the compile unit 5.26 */ 5.27 + @Override 5.28 public CompileUnit getCompileUnit() { 5.29 return compileUnit; 5.30 }
6.1 --- a/src/jdk/nashorn/internal/ir/LiteralNode.java Fri Sep 05 16:28:02 2014 +0200 6.2 +++ b/src/jdk/nashorn/internal/ir/LiteralNode.java Fri Sep 05 16:28:17 2014 +0200 6.3 @@ -603,7 +603,7 @@ 6.4 * An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can 6.5 * be split if they are too large, for bytecode generation reasons 6.6 */ 6.7 - public static final class ArrayUnit { 6.8 + public static final class ArrayUnit implements CompileUnitHolder { 6.9 /** Compile unit associated with the postsets range. */ 6.10 private final CompileUnit compileUnit; 6.11 6.12 @@ -642,6 +642,7 @@ 6.13 * The array compile unit 6.14 * @return array compile unit 6.15 */ 6.16 + @Override 6.17 public CompileUnit getCompileUnit() { 6.18 return compileUnit; 6.19 }
7.1 --- a/src/jdk/nashorn/internal/ir/SplitNode.java Fri Sep 05 16:28:02 2014 +0200 7.2 +++ b/src/jdk/nashorn/internal/ir/SplitNode.java Fri Sep 05 16:28:17 2014 +0200 7.3 @@ -39,7 +39,7 @@ 7.4 * Node indicating code is split across classes. 7.5 */ 7.6 @Immutable 7.7 -public class SplitNode extends LexicalContextStatement implements Labels { 7.8 +public class SplitNode extends LexicalContextStatement implements Labels, CompileUnitHolder { 7.9 /** Split node method name. */ 7.10 private final String name; 7.11 7.12 @@ -116,6 +116,7 @@ 7.13 * Get the compile unit for this split node 7.14 * @return compile unit 7.15 */ 7.16 + @Override 7.17 public CompileUnit getCompileUnit() { 7.18 return compileUnit; 7.19 }
8.1 --- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java Fri Sep 05 16:28:02 2014 +0200 8.2 +++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java Fri Sep 05 16:28:17 2014 +0200 8.3 @@ -38,6 +38,7 @@ 8.4 import java.util.TreeMap; 8.5 import java.util.function.Supplier; 8.6 import java.util.logging.Level; 8.7 + 8.8 import jdk.internal.dynalink.linker.GuardedInvocation; 8.9 import jdk.nashorn.internal.codegen.Compiler; 8.10 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;