src/jdk/nashorn/internal/codegen/Splitter.java

changeset 290
6fc7b51e83d6
parent 253
fb1d7ea3e1b6
child 430
2c007a8bb0e7
equal deleted inserted replaced
289:8af550dee961 290:6fc7b51e83d6
47 import jdk.nashorn.internal.runtime.options.Options; 47 import jdk.nashorn.internal.runtime.options.Options;
48 48
49 /** 49 /**
50 * Split the IR into smaller compile units. 50 * Split the IR into smaller compile units.
51 */ 51 */
52 final class Splitter extends NodeVisitor { 52 final class Splitter extends NodeVisitor<LexicalContext> {
53 /** Current compiler. */ 53 /** Current compiler. */
54 private final Compiler compiler; 54 private final Compiler compiler;
55 55
56 /** IR to be broken down. */ 56 /** IR to be broken down. */
57 private FunctionNode outermost; 57 private final FunctionNode outermost;
58 58
59 /** Compile unit for the main script. */ 59 /** Compile unit for the main script. */
60 private final CompileUnit outermostCompileUnit; 60 private final CompileUnit outermostCompileUnit;
61 61
62 /** Cache for calculated block weights. */ 62 /** Cache for calculated block weights. */
73 * @param compiler the compiler 73 * @param compiler the compiler
74 * @param functionNode function node to split 74 * @param functionNode function node to split
75 * @param outermostCompileUnit compile unit for outermost function, if non-lazy this is the script's compile unit 75 * @param outermostCompileUnit compile unit for outermost function, if non-lazy this is the script's compile unit
76 */ 76 */
77 public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) { 77 public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) {
78 super(new LexicalContext());
78 this.compiler = compiler; 79 this.compiler = compiler;
79 this.outermost = functionNode; 80 this.outermost = functionNode;
80 this.outermostCompileUnit = outermostCompileUnit; 81 this.outermostCompileUnit = outermostCompileUnit;
81 } 82 }
82 83
90 LOG.finest("Postponing split of '", functionNode.getName(), "' as it's lazy"); 91 LOG.finest("Postponing split of '", functionNode.getName(), "' as it's lazy");
91 return functionNode; 92 return functionNode;
92 } 93 }
93 94
94 LOG.finest("Initiating split of '", functionNode.getName(), "'"); 95 LOG.finest("Initiating split of '", functionNode.getName(), "'");
95
96 final LexicalContext lc = getLexicalContext();
97 96
98 long weight = WeighNodes.weigh(functionNode); 97 long weight = WeighNodes.weigh(functionNode);
99 final boolean top = fn.isProgram(); //compiler.getFunctionNode() == outermost; 98 final boolean top = fn.isProgram(); //compiler.getFunctionNode() == outermost;
100 99
101 if (weight >= SPLIT_THRESHOLD) { 100 if (weight >= SPLIT_THRESHOLD) {
125 } 124 }
126 125
127 final Block body = functionNode.getBody(); 126 final Block body = functionNode.getBody();
128 final List<FunctionNode> dc = directChildren(functionNode); 127 final List<FunctionNode> dc = directChildren(functionNode);
129 128
130 final Block newBody = (Block)body.accept(new NodeVisitor() { 129 final Block newBody = (Block)body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
131 @Override 130 @Override
132 public boolean enterFunctionNode(final FunctionNode nestedFunction) { 131 public boolean enterFunctionNode(final FunctionNode nestedFunction) {
133 return dc.contains(nestedFunction); 132 return dc.contains(nestedFunction);
134 } 133 }
135 134
136 @Override 135 @Override
137 public Node leaveFunctionNode(final FunctionNode nestedFunction) { 136 public Node leaveFunctionNode(final FunctionNode nestedFunction) {
138 FunctionNode split = new Splitter(compiler, nestedFunction, outermostCompileUnit).split(nestedFunction); 137 FunctionNode split = new Splitter(compiler, nestedFunction, outermostCompileUnit).split(nestedFunction);
139 getLexicalContext().replace(nestedFunction, split); 138 lc.replace(nestedFunction, split);
140 return split; 139 return split;
141 } 140 }
142 }); 141 });
143 functionNode = functionNode.setBody(lc, newBody); 142 functionNode = functionNode.setBody(lc, newBody);
144 143
147 return functionNode.setState(lc, CompilationState.SPLIT); 146 return functionNode.setState(lc, CompilationState.SPLIT);
148 } 147 }
149 148
150 private static List<FunctionNode> directChildren(final FunctionNode functionNode) { 149 private static List<FunctionNode> directChildren(final FunctionNode functionNode) {
151 final List<FunctionNode> dc = new ArrayList<>(); 150 final List<FunctionNode> dc = new ArrayList<>();
152 functionNode.accept(new NodeVisitor() { 151 functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
153 @Override 152 @Override
154 public boolean enterFunctionNode(final FunctionNode child) { 153 public boolean enterFunctionNode(final FunctionNode child) {
155 if (child == functionNode) { 154 if (child == functionNode) {
156 return true; 155 return true;
157 } 156 }
158 if (getLexicalContext().getParentFunction(child) == functionNode) { 157 if (lc.getParentFunction(child) == functionNode) {
159 dc.add(child); 158 dc.add(child);
160 } 159 }
161 return false; 160 return false;
162 } 161 }
163 }); 162 });
179 * @param block Block or function to split. 178 * @param block Block or function to split.
180 * 179 *
181 * @return new weight for the resulting block. 180 * @return new weight for the resulting block.
182 */ 181 */
183 private Block splitBlock(final Block block, final FunctionNode function) { 182 private Block splitBlock(final Block block, final FunctionNode function) {
184 getLexicalContext().setFlag(getLexicalContext().getCurrentFunction(), FunctionNode.IS_SPLIT); 183 lc.setFlag(lc.getCurrentFunction(), FunctionNode.IS_SPLIT);
185 184
186 final List<Statement> splits = new ArrayList<>(); 185 final List<Statement> splits = new ArrayList<>();
187 List<Statement> statements = new ArrayList<>(); 186 List<Statement> statements = new ArrayList<>();
188 long statementsWeight = 0; 187 long statementsWeight = 0;
189 188
208 207
209 if (!statements.isEmpty()) { 208 if (!statements.isEmpty()) {
210 splits.add(createBlockSplitNode(block, function, statements, statementsWeight)); 209 splits.add(createBlockSplitNode(block, function, statements, statementsWeight));
211 } 210 }
212 211
213 return block.setStatements(getLexicalContext(), splits); 212 return block.setStatements(lc, splits);
214 } 213 }
215 214
216 /** 215 /**
217 * Create a new split node from statements contained in a parent block. 216 * Create a new split node from statements contained in a parent block.
218 * 217 *
256 255
257 // Block was heavier than SLIT_THRESHOLD in enter, but a sub-block may have 256 // Block was heavier than SLIT_THRESHOLD in enter, but a sub-block may have
258 // been split already, so weigh again before splitting. 257 // been split already, so weigh again before splitting.
259 long weight = WeighNodes.weigh(block, weightCache); 258 long weight = WeighNodes.weigh(block, weightCache);
260 if (weight >= SPLIT_THRESHOLD) { 259 if (weight >= SPLIT_THRESHOLD) {
261 newBlock = splitBlock(block, getLexicalContext().getFunction(block)); 260 newBlock = splitBlock(block, lc.getFunction(block));
262 weight = WeighNodes.weigh(newBlock, weightCache); 261 weight = WeighNodes.weigh(newBlock, weightCache);
263 } 262 }
264 weightCache.put(newBlock, weight); 263 weightCache.put(newBlock, weight);
265 return newBlock; 264 return newBlock;
266 } 265 }
272 271
273 if (weight < SPLIT_THRESHOLD) { 272 if (weight < SPLIT_THRESHOLD) {
274 return literal; 273 return literal;
275 } 274 }
276 275
277 final FunctionNode functionNode = getLexicalContext().getCurrentFunction(); 276 final FunctionNode functionNode = lc.getCurrentFunction();
278 277
279 getLexicalContext().setFlag(functionNode, FunctionNode.IS_SPLIT); 278 lc.setFlag(functionNode, FunctionNode.IS_SPLIT);
280 279
281 if (literal instanceof ArrayLiteralNode) { 280 if (literal instanceof ArrayLiteralNode) {
282 final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal; 281 final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal;
283 final Node[] value = arrayLiteralNode.getValue(); 282 final Node[] value = arrayLiteralNode.getValue();
284 final int[] postsets = arrayLiteralNode.getPostsets(); 283 final int[] postsets = arrayLiteralNode.getPostsets();

mercurial