author | hannesw |
Sat, 19 Sep 2015 16:04:28 +0200 | |
changeset 32781 | d8f34ffbbc7a |
parent 32692 | 8f60bd284bf4 |
child 32888 | 24f99be3d5ab |
permissions | -rw-r--r-- |
16147 | 1 |
/* |
16151 | 2 |
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
16147 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package jdk.nashorn.internal.codegen; |
|
27 |
||
28 |
import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX; |
|
29 |
||
30 |
import java.util.ArrayList; |
|
31 |
import java.util.HashMap; |
|
32 |
import java.util.List; |
|
33 |
import java.util.Map; |
|
34 |
import jdk.nashorn.internal.ir.Block; |
|
35 |
import jdk.nashorn.internal.ir.FunctionNode; |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16523
diff
changeset
|
36 |
import jdk.nashorn.internal.ir.LexicalContext; |
16147 | 37 |
import jdk.nashorn.internal.ir.LiteralNode; |
38 |
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; |
|
39 |
import jdk.nashorn.internal.ir.Node; |
|
32781
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
40 |
import jdk.nashorn.internal.ir.ObjectNode; |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
41 |
import jdk.nashorn.internal.ir.PropertyNode; |
16147 | 42 |
import jdk.nashorn.internal.ir.SplitNode; |
32781
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
43 |
import jdk.nashorn.internal.ir.Splittable; |
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
44 |
import jdk.nashorn.internal.ir.Statement; |
16147 | 45 |
import jdk.nashorn.internal.ir.visitor.NodeVisitor; |
31195
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
46 |
import jdk.nashorn.internal.runtime.Context; |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24731
diff
changeset
|
47 |
import jdk.nashorn.internal.runtime.logging.DebugLogger; |
31195
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
48 |
import jdk.nashorn.internal.runtime.logging.Loggable; |
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
49 |
import jdk.nashorn.internal.runtime.logging.Logger; |
16168
f0c208287983
8005976: Break out AccessSpecializer into one pass before CodeGenerator instead of iterative applications from CodeGenerator
lagergren
parents:
16152
diff
changeset
|
50 |
import jdk.nashorn.internal.runtime.options.Options; |
16147 | 51 |
|
52 |
/** |
|
53 |
* Split the IR into smaller compile units. |
|
54 |
*/ |
|
31195
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
55 |
@Logger(name="splitter") |
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
56 |
final class Splitter extends NodeVisitor<LexicalContext> implements Loggable { |
16147 | 57 |
/** Current compiler. */ |
58 |
private final Compiler compiler; |
|
59 |
||
60 |
/** IR to be broken down. */ |
|
17769
14ea7feaf658
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents:
17524
diff
changeset
|
61 |
private final FunctionNode outermost; |
16147 | 62 |
|
63 |
/** Compile unit for the main script. */ |
|
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16168
diff
changeset
|
64 |
private final CompileUnit outermostCompileUnit; |
16147 | 65 |
|
66 |
/** Cache for calculated block weights. */ |
|
67 |
private final Map<Node, Long> weightCache = new HashMap<>(); |
|
68 |
||
69 |
/** Weight threshold for when to start a split. */ |
|
16168
f0c208287983
8005976: Break out AccessSpecializer into one pass before CodeGenerator instead of iterative applications from CodeGenerator
lagergren
parents:
16152
diff
changeset
|
70 |
public static final long SPLIT_THRESHOLD = Options.getIntProperty("nashorn.compiler.splitter.threshold", 32 * 1024); |
16147 | 71 |
|
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24731
diff
changeset
|
72 |
private final DebugLogger log; |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24731
diff
changeset
|
73 |
|
16147 | 74 |
/** |
75 |
* Constructor. |
|
76 |
* |
|
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16168
diff
changeset
|
77 |
* @param compiler the compiler |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16168
diff
changeset
|
78 |
* @param functionNode function node to split |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16168
diff
changeset
|
79 |
* @param outermostCompileUnit compile unit for outermost function, if non-lazy this is the script's compile unit |
16147 | 80 |
*/ |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16168
diff
changeset
|
81 |
public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) { |
17769
14ea7feaf658
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents:
17524
diff
changeset
|
82 |
super(new LexicalContext()); |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16168
diff
changeset
|
83 |
this.compiler = compiler; |
17518
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17233
diff
changeset
|
84 |
this.outermost = functionNode; |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16168
diff
changeset
|
85 |
this.outermostCompileUnit = outermostCompileUnit; |
31195
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
86 |
this.log = initLogger(compiler.getContext()); |
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
87 |
} |
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
88 |
|
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
89 |
@Override |
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
90 |
public DebugLogger initLogger(final Context context) { |
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
91 |
return context.getLogger(this.getClass()); |
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
92 |
} |
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
93 |
|
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
94 |
@Override |
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
95 |
public DebugLogger getLogger() { |
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
96 |
return log; |
16147 | 97 |
} |
98 |
||
99 |
/** |
|
24719 | 100 |
* Execute the split. |
101 |
* @param fn the function to split |
|
102 |
* @param top whether this is the topmost compiled function (it's either a program, or we're doing a recompilation). |
|
16147 | 103 |
*/ |
24731
ab0c8fc915ae
8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents:
24719
diff
changeset
|
104 |
FunctionNode split(final FunctionNode fn, final boolean top) { |
17233 | 105 |
FunctionNode functionNode = fn; |
106 |
||
31195
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
107 |
log.fine("Initiating split of '", functionNode.getName(), "'"); |
17233 | 108 |
|
16147 | 109 |
long weight = WeighNodes.weigh(functionNode); |
110 |
||
19084
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
111 |
// We know that our LexicalContext is empty outside the call to functionNode.accept(this) below, |
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
112 |
// so we can pass null to all methods expecting a LexicalContext parameter. |
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
113 |
assert lc.isEmpty() : "LexicalContext not empty"; |
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
114 |
|
16147 | 115 |
if (weight >= SPLIT_THRESHOLD) { |
31195
4ff0587b9ed1
8098807: Strict eval throws ClassCastException with large scripts
hannesw
parents:
25865
diff
changeset
|
116 |
log.info("Splitting '", functionNode.getName(), "' as its weight ", weight, " exceeds split threshold ", SPLIT_THRESHOLD); |
17233 | 117 |
functionNode = (FunctionNode)functionNode.accept(this); |
16147 | 118 |
|
119 |
if (functionNode.isSplit()) { |
|
120 |
// Weight has changed so weigh again, this time using block weight cache |
|
121 |
weight = WeighNodes.weigh(functionNode, weightCache); |
|
19084
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
122 |
functionNode = functionNode.setBody(null, functionNode.getBody().setNeedsScope(null)); |
16147 | 123 |
} |
124 |
||
125 |
if (weight >= SPLIT_THRESHOLD) { |
|
19084
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
126 |
functionNode = functionNode.setBody(null, splitBlock(functionNode.getBody(), functionNode)); |
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
127 |
functionNode = functionNode.setFlag(null, FunctionNode.IS_SPLIT); |
17233 | 128 |
weight = WeighNodes.weigh(functionNode.getBody(), weightCache); |
16147 | 129 |
} |
130 |
} |
|
131 |
||
17233 | 132 |
assert functionNode.getCompileUnit() == null : "compile unit already set for " + functionNode.getName(); |
16147 | 133 |
|
17233 | 134 |
if (top) { |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16168
diff
changeset
|
135 |
assert outermostCompileUnit != null : "outermost compile unit is null"; |
19084
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
136 |
functionNode = functionNode.setCompileUnit(null, outermostCompileUnit); |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16168
diff
changeset
|
137 |
outermostCompileUnit.addWeight(weight + WeighNodes.FUNCTION_WEIGHT); |
16147 | 138 |
} else { |
19084
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
139 |
functionNode = functionNode.setCompileUnit(null, findUnit(weight)); |
16147 | 140 |
} |
141 |
||
17233 | 142 |
final Block body = functionNode.getBody(); |
143 |
final List<FunctionNode> dc = directChildren(functionNode); |
|
144 |
||
17769
14ea7feaf658
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents:
17524
diff
changeset
|
145 |
final Block newBody = (Block)body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { |
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
146 |
@Override |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
147 |
public boolean enterFunctionNode(final FunctionNode nestedFunction) { |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
148 |
return dc.contains(nestedFunction); |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
149 |
} |
17233 | 150 |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
151 |
@Override |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
152 |
public Node leaveFunctionNode(final FunctionNode nestedFunction) { |
24731
ab0c8fc915ae
8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents:
24719
diff
changeset
|
153 |
final FunctionNode split = new Splitter(compiler, nestedFunction, outermostCompileUnit).split(nestedFunction, false); |
17769
14ea7feaf658
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents:
17524
diff
changeset
|
154 |
lc.replace(nestedFunction, split); |
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
155 |
return split; |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
156 |
} |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
157 |
}); |
19084
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
158 |
functionNode = functionNode.setBody(null, newBody); |
17233 | 159 |
|
160 |
assert functionNode.getCompileUnit() != null; |
|
161 |
||
32692
8f60bd284bf4
8055917: jdk.nashorn.internal.codegen.CompilationPhase$N should be renamed to proper classes
sundar
parents:
31195
diff
changeset
|
162 |
return functionNode; |
17233 | 163 |
} |
164 |
||
165 |
private static List<FunctionNode> directChildren(final FunctionNode functionNode) { |
|
166 |
final List<FunctionNode> dc = new ArrayList<>(); |
|
17769
14ea7feaf658
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents:
17524
diff
changeset
|
167 |
functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16523
diff
changeset
|
168 |
@Override |
17233 | 169 |
public boolean enterFunctionNode(final FunctionNode child) { |
170 |
if (child == functionNode) { |
|
171 |
return true; |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16523
diff
changeset
|
172 |
} |
17769
14ea7feaf658
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents:
17524
diff
changeset
|
173 |
if (lc.getParentFunction(child) == functionNode) { |
17233 | 174 |
dc.add(child); |
175 |
} |
|
176 |
return false; |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16523
diff
changeset
|
177 |
} |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16523
diff
changeset
|
178 |
}); |
17233 | 179 |
return dc; |
16147 | 180 |
} |
181 |
||
182 |
/** |
|
183 |
* Override this logic to look up compile units in a different way |
|
184 |
* @param weight weight needed |
|
185 |
* @return compile unit |
|
186 |
*/ |
|
187 |
protected CompileUnit findUnit(final long weight) { |
|
188 |
return compiler.findUnit(weight); |
|
189 |
} |
|
190 |
||
191 |
/** |
|
192 |
* Split a block into sub methods. |
|
193 |
* |
|
194 |
* @param block Block or function to split. |
|
195 |
* |
|
196 |
* @return new weight for the resulting block. |
|
197 |
*/ |
|
17233 | 198 |
private Block splitBlock(final Block block, final FunctionNode function) { |
16147 | 199 |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
200 |
final List<Statement> splits = new ArrayList<>(); |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
201 |
List<Statement> statements = new ArrayList<>(); |
16147 | 202 |
long statementsWeight = 0; |
203 |
||
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
204 |
for (final Statement statement : block.getStatements()) { |
16147 | 205 |
final long weight = WeighNodes.weigh(statement, weightCache); |
206 |
||
207 |
if (statementsWeight + weight >= SPLIT_THRESHOLD || statement.isTerminal()) { |
|
208 |
if (!statements.isEmpty()) { |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16523
diff
changeset
|
209 |
splits.add(createBlockSplitNode(block, function, statements, statementsWeight)); |
16147 | 210 |
statements = new ArrayList<>(); |
211 |
statementsWeight = 0; |
|
212 |
} |
|
213 |
} |
|
214 |
||
215 |
if (statement.isTerminal()) { |
|
216 |
splits.add(statement); |
|
217 |
} else { |
|
218 |
statements.add(statement); |
|
219 |
statementsWeight += weight; |
|
220 |
} |
|
221 |
} |
|
222 |
||
223 |
if (!statements.isEmpty()) { |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16523
diff
changeset
|
224 |
splits.add(createBlockSplitNode(block, function, statements, statementsWeight)); |
16147 | 225 |
} |
226 |
||
17769
14ea7feaf658
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents:
17524
diff
changeset
|
227 |
return block.setStatements(lc, splits); |
16147 | 228 |
} |
229 |
||
230 |
/** |
|
231 |
* Create a new split node from statements contained in a parent block. |
|
232 |
* |
|
233 |
* @param parent Parent block. |
|
234 |
* @param statements Statements to include. |
|
235 |
* |
|
236 |
* @return New split node. |
|
237 |
*/ |
|
17524
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
238 |
private SplitNode createBlockSplitNode(final Block parent, final FunctionNode function, final List<Statement> statements, final long weight) { |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
239 |
final long token = parent.getToken(); |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
240 |
final int finish = parent.getFinish(); |
703643aeb0d6
8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents:
17523
diff
changeset
|
241 |
final String name = function.uniqueName(SPLIT_PREFIX.symbolName()); |
16147 | 242 |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
243 |
final Block newBlock = new Block(token, finish, statements); |
16147 | 244 |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
245 |
return new SplitNode(name, newBlock, compiler.findUnit(weight + WeighNodes.FUNCTION_WEIGHT)); |
16147 | 246 |
} |
247 |
||
248 |
@Override |
|
17233 | 249 |
public boolean enterBlock(final Block block) { |
16147 | 250 |
if (block.isCatchBlock()) { |
17233 | 251 |
return false; |
16147 | 252 |
} |
253 |
||
254 |
final long weight = WeighNodes.weigh(block, weightCache); |
|
255 |
||
256 |
if (weight < SPLIT_THRESHOLD) { |
|
257 |
weightCache.put(block, weight); |
|
17233 | 258 |
return false; |
16147 | 259 |
} |
260 |
||
17233 | 261 |
return true; |
16147 | 262 |
} |
263 |
||
264 |
@Override |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16523
diff
changeset
|
265 |
public Node leaveBlock(final Block block) { |
16147 | 266 |
assert !block.isCatchBlock(); |
267 |
||
17233 | 268 |
Block newBlock = block; |
269 |
||
16147 | 270 |
// Block was heavier than SLIT_THRESHOLD in enter, but a sub-block may have |
271 |
// been split already, so weigh again before splitting. |
|
272 |
long weight = WeighNodes.weigh(block, weightCache); |
|
273 |
if (weight >= SPLIT_THRESHOLD) { |
|
19084
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
274 |
final FunctionNode currentFunction = lc.getCurrentFunction(); |
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
275 |
newBlock = splitBlock(block, currentFunction); |
17233 | 276 |
weight = WeighNodes.weigh(newBlock, weightCache); |
19084
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
277 |
lc.setFlag(currentFunction, FunctionNode.IS_SPLIT); |
16147 | 278 |
} |
17233 | 279 |
weightCache.put(newBlock, weight); |
280 |
return newBlock; |
|
16147 | 281 |
} |
282 |
||
283 |
@SuppressWarnings("rawtypes") |
|
284 |
@Override |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16523
diff
changeset
|
285 |
public Node leaveLiteralNode(final LiteralNode literal) { |
16147 | 286 |
long weight = WeighNodes.weigh(literal); |
287 |
||
288 |
if (weight < SPLIT_THRESHOLD) { |
|
289 |
return literal; |
|
290 |
} |
|
291 |
||
17769
14ea7feaf658
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents:
17524
diff
changeset
|
292 |
final FunctionNode functionNode = lc.getCurrentFunction(); |
17518
2225a4f929c0
8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents:
17233
diff
changeset
|
293 |
|
17769
14ea7feaf658
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents:
17524
diff
changeset
|
294 |
lc.setFlag(functionNode, FunctionNode.IS_SPLIT); |
16147 | 295 |
|
296 |
if (literal instanceof ArrayLiteralNode) { |
|
297 |
final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal; |
|
298 |
final Node[] value = arrayLiteralNode.getValue(); |
|
299 |
final int[] postsets = arrayLiteralNode.getPostsets(); |
|
32781
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
300 |
final List<Splittable.SplitRange> ranges = new ArrayList<>(); |
16147 | 301 |
|
302 |
long totalWeight = 0; |
|
303 |
int lo = 0; |
|
304 |
||
305 |
for (int i = 0; i < postsets.length; i++) { |
|
306 |
final int postset = postsets[i]; |
|
307 |
final Node element = value[postset]; |
|
308 |
||
309 |
weight = WeighNodes.weigh(element); |
|
19084
daddbeee0058
8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents:
18867
diff
changeset
|
310 |
totalWeight += WeighNodes.AASTORE_WEIGHT + weight; |
16147 | 311 |
|
312 |
if (totalWeight >= SPLIT_THRESHOLD) { |
|
313 |
final CompileUnit unit = compiler.findUnit(totalWeight - weight); |
|
32781
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
314 |
ranges.add(new Splittable.SplitRange(unit, lo, i)); |
16147 | 315 |
lo = i; |
316 |
totalWeight = weight; |
|
317 |
} |
|
318 |
} |
|
319 |
||
320 |
if (lo != postsets.length) { |
|
321 |
final CompileUnit unit = compiler.findUnit(totalWeight); |
|
32781
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
322 |
ranges.add(new Splittable.SplitRange(unit, lo, postsets.length)); |
16147 | 323 |
} |
324 |
||
32781
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
325 |
return arrayLiteralNode.setSplitRanges(lc, ranges); |
16147 | 326 |
} |
327 |
||
328 |
return literal; |
|
329 |
} |
|
330 |
||
331 |
@Override |
|
32781
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
332 |
public Node leaveObjectNode(final ObjectNode objectNode) { |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
333 |
long weight = WeighNodes.weigh(objectNode); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
334 |
|
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
335 |
if (weight < SPLIT_THRESHOLD) { |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
336 |
return objectNode; |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
337 |
} |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
338 |
|
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
339 |
final FunctionNode functionNode = lc.getCurrentFunction(); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
340 |
lc.setFlag(functionNode, FunctionNode.IS_SPLIT); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
341 |
|
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
342 |
final List<Splittable.SplitRange> ranges = new ArrayList<>(); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
343 |
final List<PropertyNode> properties = objectNode.getElements(); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
344 |
final boolean isSpillObject = properties.size() > CodeGenerator.OBJECT_SPILL_THRESHOLD; |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
345 |
long totalWeight = 0; |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
346 |
int lo = 0; |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
347 |
|
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
348 |
for (int i = 0; i < properties.size(); i++) { |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
349 |
|
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
350 |
final PropertyNode property = properties.get(i); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
351 |
final boolean isConstant = LiteralNode.isConstant(property.getValue()); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
352 |
|
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
353 |
if (!isConstant || !isSpillObject) { |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
354 |
weight = isConstant ? 0 : WeighNodes.weigh(property.getValue()); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
355 |
totalWeight += WeighNodes.AASTORE_WEIGHT + weight; |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
356 |
|
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
357 |
if (totalWeight >= SPLIT_THRESHOLD) { |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
358 |
final CompileUnit unit = compiler.findUnit(totalWeight - weight); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
359 |
ranges.add(new Splittable.SplitRange(unit, lo, i)); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
360 |
lo = i; |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
361 |
totalWeight = weight; |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
362 |
} |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
363 |
} |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
364 |
} |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
365 |
|
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
366 |
if (lo != properties.size()) { |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
367 |
final CompileUnit unit = compiler.findUnit(totalWeight); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
368 |
ranges.add(new Splittable.SplitRange(unit, lo, properties.size())); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
369 |
} |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
370 |
|
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
371 |
return objectNode.setSplitRanges(lc, ranges); |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
372 |
} |
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
373 |
|
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32692
diff
changeset
|
374 |
@Override |
17233 | 375 |
public boolean enterFunctionNode(final FunctionNode node) { |
376 |
//only go into the function node for this splitter. any subfunctions are rejected |
|
24719 | 377 |
return node == outermost; |
16147 | 378 |
} |
379 |
} |
|
380 |