author | attila |
Wed, 28 Jan 2015 17:58:08 +0100 | |
changeset 28690 | 78317797ab62 |
parent 27976 | ef54dfb4fc7d |
child 28784 | a79ac84f2ea4 |
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.EVAL; |
|
17233 | 29 |
import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN; |
24751 | 30 |
import static jdk.nashorn.internal.ir.Expression.isAlwaysTrue; |
16147 | 31 |
|
32 |
import java.util.ArrayList; |
|
33 |
import java.util.Arrays; |
|
24719 | 34 |
import java.util.Collections; |
16147 | 35 |
import java.util.List; |
18848
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
36 |
import java.util.ListIterator; |
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
37 |
import java.util.regex.Pattern; |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
38 |
import jdk.nashorn.internal.ir.AccessNode; |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
39 |
import jdk.nashorn.internal.ir.BaseNode; |
16147 | 40 |
import jdk.nashorn.internal.ir.BinaryNode; |
41 |
import jdk.nashorn.internal.ir.Block; |
|
17233 | 42 |
import jdk.nashorn.internal.ir.BlockLexicalContext; |
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
43 |
import jdk.nashorn.internal.ir.BlockStatement; |
16147 | 44 |
import jdk.nashorn.internal.ir.BreakNode; |
45 |
import jdk.nashorn.internal.ir.CallNode; |
|
24751 | 46 |
import jdk.nashorn.internal.ir.CaseNode; |
16147 | 47 |
import jdk.nashorn.internal.ir.CatchNode; |
48 |
import jdk.nashorn.internal.ir.ContinueNode; |
|
49 |
import jdk.nashorn.internal.ir.EmptyNode; |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
50 |
import jdk.nashorn.internal.ir.Expression; |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
51 |
import jdk.nashorn.internal.ir.ExpressionStatement; |
16147 | 52 |
import jdk.nashorn.internal.ir.ForNode; |
53 |
import jdk.nashorn.internal.ir.FunctionNode; |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
54 |
import jdk.nashorn.internal.ir.FunctionNode.CompilationState; |
16147 | 55 |
import jdk.nashorn.internal.ir.IdentNode; |
56 |
import jdk.nashorn.internal.ir.IfNode; |
|
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
57 |
import jdk.nashorn.internal.ir.IndexNode; |
26889
dba314d7a634
8059371: Code duplication in handling of break and continue
attila
parents:
26504
diff
changeset
|
58 |
import jdk.nashorn.internal.ir.JumpStatement; |
28690 | 59 |
import jdk.nashorn.internal.ir.JumpToInlinedFinally; |
16147 | 60 |
import jdk.nashorn.internal.ir.LabelNode; |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
61 |
import jdk.nashorn.internal.ir.LexicalContext; |
16147 | 62 |
import jdk.nashorn.internal.ir.LiteralNode; |
28690 | 63 |
import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode; |
17233 | 64 |
import jdk.nashorn.internal.ir.LoopNode; |
16147 | 65 |
import jdk.nashorn.internal.ir.Node; |
66 |
import jdk.nashorn.internal.ir.ReturnNode; |
|
24751 | 67 |
import jdk.nashorn.internal.ir.RuntimeNode; |
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
|
68 |
import jdk.nashorn.internal.ir.Statement; |
16147 | 69 |
import jdk.nashorn.internal.ir.SwitchNode; |
70 |
import jdk.nashorn.internal.ir.Symbol; |
|
71 |
import jdk.nashorn.internal.ir.ThrowNode; |
|
72 |
import jdk.nashorn.internal.ir.TryNode; |
|
73 |
import jdk.nashorn.internal.ir.VarNode; |
|
74 |
import jdk.nashorn.internal.ir.WhileNode; |
|
75 |
import jdk.nashorn.internal.ir.WithNode; |
|
76 |
import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; |
|
77 |
import jdk.nashorn.internal.ir.visitor.NodeVisitor; |
|
78 |
import jdk.nashorn.internal.parser.Token; |
|
79 |
import jdk.nashorn.internal.parser.TokenType; |
|
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
80 |
import jdk.nashorn.internal.runtime.Context; |
24751 | 81 |
import jdk.nashorn.internal.runtime.JSType; |
16147 | 82 |
import jdk.nashorn.internal.runtime.Source; |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
83 |
import jdk.nashorn.internal.runtime.logging.DebugLogger; |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
84 |
import jdk.nashorn.internal.runtime.logging.Loggable; |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
85 |
import jdk.nashorn.internal.runtime.logging.Logger; |
16147 | 86 |
|
87 |
/** |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
88 |
* Lower to more primitive operations. After lowering, an AST still has no symbols |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
89 |
* and types, but several nodes have been turned into more low level constructs |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
90 |
* and control flow termination criteria have been computed. |
16147 | 91 |
* |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
92 |
* We do things like code copying/inlining of finallies here, as it is much |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
93 |
* harder and context dependent to do any code copying after symbols have been |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
94 |
* finalized. |
16147 | 95 |
*/ |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
96 |
@Logger(name="lower") |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
97 |
final class Lower extends NodeOperatorVisitor<BlockLexicalContext> implements Loggable { |
16147 | 98 |
|
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
99 |
private final DebugLogger log; |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
100 |
|
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
101 |
// Conservative pattern to test if element names consist of characters valid for identifiers. |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
102 |
// This matches any non-zero length alphanumeric string including _ and $ and not starting with a digit. |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
103 |
private static Pattern SAFE_PROPERTY_NAME = Pattern.compile("[a-zA-Z_$][\\w$]*"); |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
104 |
|
16147 | 105 |
/** |
106 |
* Constructor. |
|
107 |
*/ |
|
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
108 |
Lower(final Compiler compiler) { |
17233 | 109 |
super(new BlockLexicalContext() { |
110 |
||
111 |
@Override |
|
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
|
112 |
public List<Statement> popStatements() { |
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
|
113 |
final List<Statement> newStatements = new ArrayList<>(); |
17233 | 114 |
boolean terminated = false; |
115 |
||
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
|
116 |
final List<Statement> statements = super.popStatements(); |
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
|
117 |
for (final Statement statement : statements) { |
17233 | 118 |
if (!terminated) { |
119 |
newStatements.add(statement); |
|
28690 | 120 |
if (statement.isTerminal() || statement instanceof JumpStatement) { //TODO hasGoto? But some Loops are hasGoto too - why? |
17233 | 121 |
terminated = true; |
122 |
} |
|
123 |
} else { |
|
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:
17752
diff
changeset
|
124 |
statement.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
|
125 |
@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
|
126 |
public boolean enterVarNode(final VarNode varNode) { |
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
|
127 |
newStatements.add(varNode.setInit(null)); |
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
|
128 |
return false; |
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
|
129 |
} |
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
|
130 |
}); |
17233 | 131 |
} |
132 |
} |
|
133 |
return newStatements; |
|
134 |
} |
|
18848
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
135 |
|
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
136 |
@Override |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
137 |
protected Block afterSetStatements(final Block block) { |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
138 |
final List<Statement> stmts = block.getStatements(); |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
139 |
for(final ListIterator<Statement> li = stmts.listIterator(stmts.size()); li.hasPrevious();) { |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
140 |
final Statement stmt = li.previous(); |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
141 |
// popStatements() guarantees that the only thing after a terminal statement are uninitialized |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
142 |
// VarNodes. We skip past those, and set the terminal state of the block to the value of the |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
143 |
// terminal state of the first statement that is not an uninitialized VarNode. |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
144 |
if(!(stmt instanceof VarNode && ((VarNode)stmt).getInit() == null)) { |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
145 |
return block.setIsTerminal(this, stmt.isTerminal()); |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
146 |
} |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
147 |
} |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
148 |
return block.setIsTerminal(this, false); |
e64943db2b06
8019809: return after break incorrectly sets the block as terminal
attila
parents:
17982
diff
changeset
|
149 |
} |
17233 | 150 |
}); |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
151 |
|
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
152 |
this.log = initLogger(compiler.getContext()); |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
153 |
} |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
154 |
|
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
155 |
@Override |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
156 |
public DebugLogger getLogger() { |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
157 |
return log; |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
158 |
} |
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
159 |
|
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
160 |
@Override |
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
161 |
public DebugLogger initLogger(final Context context) { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
162 |
return context.getLogger(this.getClass()); |
17233 | 163 |
} |
164 |
||
165 |
@Override |
|
166 |
public boolean enterBreakNode(final BreakNode breakNode) { |
|
167 |
addStatement(breakNode); |
|
168 |
return false; |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
169 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
170 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
171 |
@Override |
17233 | 172 |
public Node leaveCallNode(final CallNode callNode) { |
173 |
return checkEval(callNode.setFunction(markerFunction(callNode.getFunction()))); |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
174 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
175 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
176 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
177 |
public Node leaveCatchNode(final CatchNode catchNode) { |
17233 | 178 |
return addStatement(catchNode); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
179 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
180 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
181 |
@Override |
17233 | 182 |
public boolean enterContinueNode(final ContinueNode continueNode) { |
183 |
addStatement(continueNode); |
|
184 |
return false; |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
185 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
186 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
187 |
@Override |
28690 | 188 |
public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) { |
189 |
addStatement(jumpToInlinedFinally); |
|
190 |
return false; |
|
191 |
} |
|
192 |
||
193 |
@Override |
|
17233 | 194 |
public boolean enterEmptyNode(final EmptyNode emptyNode) { |
195 |
return false; |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
196 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
197 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
198 |
@Override |
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
199 |
public Node leaveIndexNode(final IndexNode indexNode) { |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
200 |
final String name = getConstantPropertyName(indexNode.getIndex()); |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
201 |
if (name != null) { |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
202 |
// If index node is a constant property name convert index node to access node. |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
203 |
assert Token.descType(indexNode.getToken()) == TokenType.LBRACKET; |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
204 |
return new AccessNode(indexNode.getToken(), indexNode.getFinish(), indexNode.getBase(), name); |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
205 |
} |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
206 |
return super.leaveIndexNode(indexNode); |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
207 |
} |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
208 |
|
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
209 |
// If expression is a primitive literal that is not an array index and does return its string value. Else return null. |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
210 |
private static String getConstantPropertyName(final Expression expression) { |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
211 |
if (expression instanceof LiteralNode.PrimitiveLiteralNode) { |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
212 |
final Object value = ((LiteralNode) expression).getValue(); |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
213 |
if (value instanceof String && SAFE_PROPERTY_NAME.matcher((String) value).matches()) { |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
214 |
return (String) value; |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
215 |
} |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
216 |
} |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
217 |
return null; |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
218 |
} |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
219 |
|
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27970
diff
changeset
|
220 |
@Override |
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
221 |
public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) { |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
222 |
final Expression expr = expressionStatement.getExpression(); |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
223 |
ExpressionStatement node = expressionStatement; |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
224 |
|
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:
17752
diff
changeset
|
225 |
final FunctionNode currentFunction = lc.getCurrentFunction(); |
17233 | 226 |
|
227 |
if (currentFunction.isProgram()) { |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
228 |
if (!isInternalExpression(expr) && !isEvalResultAssignment(expr)) { |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
229 |
node = expressionStatement.setExpression( |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
230 |
new BinaryNode( |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
231 |
Token.recast( |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
232 |
expressionStatement.getToken(), |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
233 |
TokenType.ASSIGN), |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
234 |
compilerConstant(RETURN), |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
235 |
expr)); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
236 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
237 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
238 |
|
17233 | 239 |
return addStatement(node); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
240 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
241 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
242 |
@Override |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
243 |
public Node leaveBlockStatement(final BlockStatement blockStatement) { |
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
244 |
return addStatement(blockStatement); |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
245 |
} |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
246 |
|
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
247 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
248 |
public Node leaveForNode(final ForNode forNode) { |
17233 | 249 |
ForNode newForNode = forNode; |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
250 |
|
24751 | 251 |
final Expression test = forNode.getTest(); |
252 |
if (!forNode.isForIn() && isAlwaysTrue(test)) { |
|
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:
17752
diff
changeset
|
253 |
newForNode = forNode.setTest(lc, null); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
254 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
255 |
|
24719 | 256 |
newForNode = checkEscape(newForNode); |
257 |
if(newForNode.isForIn()) { |
|
258 |
// Wrap it in a block so its internally created iterator is restricted in scope |
|
24751 | 259 |
addStatementEnclosedInBlock(newForNode); |
24719 | 260 |
} else { |
261 |
addStatement(newForNode); |
|
262 |
} |
|
263 |
return newForNode; |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
264 |
} |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
265 |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
266 |
@Override |
17233 | 267 |
public Node leaveFunctionNode(final FunctionNode functionNode) { |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
268 |
log.info("END FunctionNode: ", functionNode.getName()); |
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:
17752
diff
changeset
|
269 |
return functionNode.setState(lc, CompilationState.LOWERED); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
270 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
271 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
272 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
273 |
public Node leaveIfNode(final IfNode ifNode) { |
17233 | 274 |
return addStatement(ifNode); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
275 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
276 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
277 |
@Override |
24759
31aed7d9c02a
8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents:
24751
diff
changeset
|
278 |
public Node leaveIN(final BinaryNode binaryNode) { |
24751 | 279 |
return new RuntimeNode(binaryNode); |
280 |
} |
|
281 |
||
282 |
@Override |
|
24759
31aed7d9c02a
8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents:
24751
diff
changeset
|
283 |
public Node leaveINSTANCEOF(final BinaryNode binaryNode) { |
24751 | 284 |
return new RuntimeNode(binaryNode); |
285 |
} |
|
286 |
||
287 |
@Override |
|
17233 | 288 |
public Node leaveLabelNode(final LabelNode labelNode) { |
289 |
return addStatement(labelNode); |
|
290 |
} |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
291 |
|
17233 | 292 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
293 |
public Node leaveReturnNode(final ReturnNode returnNode) { |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
294 |
addStatement(returnNode); //ReturnNodes are always terminal, marked as such in constructor |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
295 |
return returnNode; |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
296 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
297 |
|
24751 | 298 |
@Override |
24759
31aed7d9c02a
8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents:
24751
diff
changeset
|
299 |
public Node leaveCaseNode(final CaseNode caseNode) { |
24751 | 300 |
// Try to represent the case test as an integer |
301 |
final Node test = caseNode.getTest(); |
|
302 |
if (test instanceof LiteralNode) { |
|
303 |
final LiteralNode<?> lit = (LiteralNode<?>)test; |
|
304 |
if (lit.isNumeric() && !(lit.getValue() instanceof Integer)) { |
|
305 |
if (JSType.isRepresentableAsInt(lit.getNumber())) { |
|
306 |
return caseNode.setTest((Expression)LiteralNode.newInstance(lit, lit.getInt32()).accept(this)); |
|
307 |
} |
|
308 |
} |
|
309 |
} |
|
310 |
return caseNode; |
|
311 |
} |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
312 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
313 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
314 |
public Node leaveSwitchNode(final SwitchNode switchNode) { |
27970
7b0048b90967
8066225: NPE in MethodEmitter with duplicate integer switch cases
attila
parents:
27817
diff
changeset
|
315 |
if(!switchNode.isUniqueInteger()) { |
24751 | 316 |
// Wrap it in a block so its internally created tag is restricted in scope |
317 |
addStatementEnclosedInBlock(switchNode); |
|
318 |
} else { |
|
319 |
addStatement(switchNode); |
|
320 |
} |
|
321 |
return switchNode; |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
322 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
323 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
324 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
325 |
public Node leaveThrowNode(final ThrowNode throwNode) { |
24751 | 326 |
return addStatement(throwNode); //ThrowNodes are always terminal, marked as such in constructor |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
327 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
328 |
|
28690 | 329 |
private static <T extends Node> T ensureUniqueNamesIn(final T node) { |
330 |
return (T)node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { |
|
17752
9d2d0e74a833
8013919: Original exception no longer thrown away when a finally rethrows
lagergren
parents:
17745
diff
changeset
|
331 |
@Override |
9d2d0e74a833
8013919: Original exception no longer thrown away when a finally rethrows
lagergren
parents:
17745
diff
changeset
|
332 |
public Node leaveFunctionNode(final FunctionNode functionNode) { |
9d2d0e74a833
8013919: Original exception no longer thrown away when a finally rethrows
lagergren
parents:
17745
diff
changeset
|
333 |
final String name = functionNode.getName(); |
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:
17752
diff
changeset
|
334 |
return functionNode.setName(lc, lc.getCurrentFunction().uniqueName(name)); |
17752
9d2d0e74a833
8013919: Original exception no longer thrown away when a finally rethrows
lagergren
parents:
17745
diff
changeset
|
335 |
} |
9d2d0e74a833
8013919: Original exception no longer thrown away when a finally rethrows
lagergren
parents:
17745
diff
changeset
|
336 |
|
9d2d0e74a833
8013919: Original exception no longer thrown away when a finally rethrows
lagergren
parents:
17745
diff
changeset
|
337 |
@Override |
9d2d0e74a833
8013919: Original exception no longer thrown away when a finally rethrows
lagergren
parents:
17745
diff
changeset
|
338 |
public Node leaveDefault(final Node labelledNode) { |
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:
17752
diff
changeset
|
339 |
return labelledNode.ensureUniqueLabels(lc); |
17752
9d2d0e74a833
8013919: Original exception no longer thrown away when a finally rethrows
lagergren
parents:
17745
diff
changeset
|
340 |
} |
17233 | 341 |
}); |
342 |
} |
|
343 |
||
28690 | 344 |
private static Block createFinallyBlock(final Block finallyBody) { |
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
|
345 |
final List<Statement> newStatements = 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
|
346 |
for (final Statement statement : finallyBody.getStatements()) { |
28690 | 347 |
newStatements.add(statement); |
17233 | 348 |
if (statement.hasTerminalFlags()) { |
28690 | 349 |
break; |
17233 | 350 |
} |
351 |
} |
|
28690 | 352 |
return finallyBody.setStatements(null, newStatements); |
17233 | 353 |
} |
354 |
||
355 |
private Block catchAllBlock(final TryNode tryNode) { |
|
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
|
356 |
final int lineNumber = tryNode.getLineNumber(); |
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
|
357 |
final long token = tryNode.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
|
358 |
final int finish = tryNode.getFinish(); |
17233 | 359 |
|
24719 | 360 |
final IdentNode exception = new IdentNode(token, finish, lc.getCurrentFunction().uniqueName(CompilerConstants.EXCEPTION_PREFIX.symbolName())); |
17233 | 361 |
|
24751 | 362 |
final Block catchBody = new Block(token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), true)); |
19100
62d400be5b44
8021244: Inconsistent stackmap with splitter threshold set very low
hannesw
parents:
18867
diff
changeset
|
363 |
assert catchBody.isTerminal(); //ends with throw, so terminal |
17233 | 364 |
|
24751 | 365 |
final CatchNode catchAllNode = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody, true); |
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
366 |
final Block catchAllBlock = new Block(token, finish, catchAllNode); |
17233 | 367 |
|
368 |
//catchallblock -> catchallnode (catchnode) -> exception -> throw |
|
369 |
||
370 |
return (Block)catchAllBlock.accept(this); //not accepted. has to be accepted by lower |
|
371 |
} |
|
372 |
||
373 |
private IdentNode compilerConstant(final CompilerConstants cc) { |
|
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:
17752
diff
changeset
|
374 |
final FunctionNode functionNode = lc.getCurrentFunction(); |
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17233
diff
changeset
|
375 |
return new IdentNode(functionNode.getToken(), functionNode.getFinish(), cc.symbolName()); |
17233 | 376 |
} |
377 |
||
28690 | 378 |
private static boolean isTerminalFinally(final Block finallyBlock) { |
379 |
return finallyBlock.getLastStatement().hasTerminalFlags(); |
|
17233 | 380 |
} |
381 |
||
382 |
/** |
|
383 |
* Splice finally code into all endpoints of a trynode |
|
384 |
* @param tryNode the try node |
|
28690 | 385 |
* @param rethrow the rethrowing throw nodes from the synthetic catch block |
17233 | 386 |
* @param finallyBody the code in the original finally block |
387 |
* @return new try node after splicing finally code (same if nop) |
|
388 |
*/ |
|
28690 | 389 |
private TryNode spliceFinally(final TryNode tryNode, final ThrowNode rethrow, final Block finallyBody) { |
17233 | 390 |
assert tryNode.getFinallyBody() == null; |
391 |
||
28690 | 392 |
final Block finallyBlock = createFinallyBlock(finallyBody); |
393 |
final ArrayList<Block> inlinedFinallies = new ArrayList<>(); |
|
394 |
final FunctionNode fn = lc.getCurrentFunction(); |
|
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:
17752
diff
changeset
|
395 |
final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { |
17233 | 396 |
|
397 |
@Override |
|
398 |
public boolean enterFunctionNode(final FunctionNode functionNode) { |
|
399 |
// do not enter function nodes - finally code should not be inlined into them |
|
400 |
return false; |
|
401 |
} |
|
402 |
||
403 |
@Override |
|
404 |
public Node leaveThrowNode(final ThrowNode throwNode) { |
|
28690 | 405 |
if (rethrow == throwNode) { |
406 |
return new BlockStatement(prependFinally(finallyBlock, throwNode)); |
|
17233 | 407 |
} |
408 |
return throwNode; |
|
409 |
} |
|
410 |
||
411 |
@Override |
|
412 |
public Node leaveBreakNode(final BreakNode breakNode) { |
|
26889
dba314d7a634
8059371: Code duplication in handling of break and continue
attila
parents:
26504
diff
changeset
|
413 |
return leaveJumpStatement(breakNode); |
17233 | 414 |
} |
415 |
||
416 |
@Override |
|
417 |
public Node leaveContinueNode(final ContinueNode continueNode) { |
|
26889
dba314d7a634
8059371: Code duplication in handling of break and continue
attila
parents:
26504
diff
changeset
|
418 |
return leaveJumpStatement(continueNode); |
dba314d7a634
8059371: Code duplication in handling of break and continue
attila
parents:
26504
diff
changeset
|
419 |
} |
dba314d7a634
8059371: Code duplication in handling of break and continue
attila
parents:
26504
diff
changeset
|
420 |
|
dba314d7a634
8059371: Code duplication in handling of break and continue
attila
parents:
26504
diff
changeset
|
421 |
private Node leaveJumpStatement(final JumpStatement jump) { |
28690 | 422 |
// NOTE: leaveJumpToInlinedFinally deliberately does not delegate to this method, only break and |
423 |
// continue are edited. JTIF nodes should not be changed, rather the surroundings of |
|
424 |
// break/continue/return that were moved into the inlined finally block itself will be changed. |
|
425 |
||
426 |
// If this visitor's lc doesn't find the target of the jump, it means it's external to the try block. |
|
427 |
if (jump.getTarget(lc) == null) { |
|
428 |
return createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, jump)); |
|
429 |
} |
|
430 |
return jump; |
|
17233 | 431 |
} |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
432 |
|
17233 | 433 |
@Override |
434 |
public Node leaveReturnNode(final ReturnNode returnNode) { |
|
28690 | 435 |
final Expression expr = returnNode.getExpression(); |
436 |
if (isTerminalFinally(finallyBlock)) { |
|
437 |
if (expr == null) { |
|
438 |
// Terminal finally; no return expression. |
|
439 |
return createJumpToInlinedFinally(fn, inlinedFinallies, ensureUniqueNamesIn(finallyBlock)); |
|
440 |
} |
|
441 |
// Terminal finally; has a return expression. |
|
442 |
final List<Statement> newStatements = new ArrayList<>(2); |
|
443 |
final int retLineNumber = returnNode.getLineNumber(); |
|
444 |
final long retToken = returnNode.getToken(); |
|
445 |
// Expression is evaluated for side effects. |
|
446 |
newStatements.add(new ExpressionStatement(retLineNumber, retToken, returnNode.getFinish(), expr)); |
|
447 |
newStatements.add(createJumpToInlinedFinally(fn, inlinedFinallies, ensureUniqueNamesIn(finallyBlock))); |
|
448 |
return new BlockStatement(retLineNumber, new Block(retToken, finallyBlock.getFinish(), newStatements)); |
|
449 |
} else if (expr == null || expr instanceof PrimitiveLiteralNode<?> || (expr instanceof IdentNode && RETURN.symbolName().equals(((IdentNode)expr).getName()))) { |
|
450 |
// Nonterminal finally; no return expression, or returns a primitive literal, or returns :return. |
|
451 |
// Just move the return expression into the finally block. |
|
452 |
return createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, returnNode)); |
|
17233 | 453 |
} else { |
28690 | 454 |
// We need to evaluate the result of the return in case it is complex while still in the try block, |
455 |
// store it in :return, and return it afterwards. |
|
456 |
final List<Statement> newStatements = new ArrayList<>(); |
|
457 |
final int retLineNumber = returnNode.getLineNumber(); |
|
458 |
final long retToken = returnNode.getToken(); |
|
459 |
final int retFinish = returnNode.getFinish(); |
|
460 |
final Expression resultNode = new IdentNode(expr.getToken(), expr.getFinish(), RETURN.symbolName()); |
|
461 |
// ":return = <expr>;" |
|
462 |
newStatements.add(new ExpressionStatement(retLineNumber, retToken, retFinish, new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr))); |
|
463 |
// inline finally and end it with "return :return;" |
|
464 |
newStatements.add(createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, returnNode.setExpression(resultNode)))); |
|
465 |
return new BlockStatement(retLineNumber, new Block(retToken, retFinish, newStatements)); |
|
17233 | 466 |
} |
467 |
} |
|
468 |
}); |
|
28690 | 469 |
addStatement(inlinedFinallies.isEmpty() ? newTryNode : newTryNode.setInlinedFinallies(lc, inlinedFinallies)); |
470 |
// TODO: if finallyStatement is terminal, we could just have sites of inlined finallies jump here. |
|
471 |
addStatement(new BlockStatement(finallyBlock)); |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
472 |
|
17233 | 473 |
return newTryNode; |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
474 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
475 |
|
28690 | 476 |
private static JumpToInlinedFinally createJumpToInlinedFinally(final FunctionNode fn, final List<Block> inlinedFinallies, final Block finallyBlock) { |
477 |
final String labelName = fn.uniqueName(":finally"); |
|
478 |
final long token = finallyBlock.getToken(); |
|
479 |
final int finish = finallyBlock.getFinish(); |
|
480 |
inlinedFinallies.add(new Block(token, finish, new LabelNode(finallyBlock.getFirstStatementLineNumber(), |
|
481 |
token, finish, labelName, finallyBlock))); |
|
482 |
return new JumpToInlinedFinally(labelName); |
|
483 |
} |
|
484 |
||
485 |
private static Block prependFinally(final Block finallyBlock, final Statement statement) { |
|
486 |
final Block inlinedFinally = ensureUniqueNamesIn(finallyBlock); |
|
487 |
if (isTerminalFinally(finallyBlock)) { |
|
488 |
return inlinedFinally; |
|
489 |
} |
|
490 |
final List<Statement> stmts = inlinedFinally.getStatements(); |
|
491 |
final List<Statement> newStmts = new ArrayList<>(stmts.size() + 1); |
|
492 |
newStmts.addAll(stmts); |
|
493 |
newStmts.add(statement); |
|
494 |
return new Block(inlinedFinally.getToken(), statement.getFinish(), newStmts); |
|
495 |
} |
|
496 |
||
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
497 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
498 |
public Node leaveTryNode(final TryNode tryNode) { |
17233 | 499 |
final Block finallyBody = tryNode.getFinallyBody(); |
28690 | 500 |
TryNode newTryNode = tryNode.setFinallyBody(lc, null); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
501 |
|
28690 | 502 |
// No finally or empty finally |
503 |
if (finallyBody == null || finallyBody.getStatementCount() == 0) { |
|
504 |
final List<CatchNode> catches = newTryNode.getCatches(); |
|
505 |
if (catches == null || catches.isEmpty()) { |
|
506 |
// A completely degenerate try block: empty finally, no catches. Replace it with try body. |
|
507 |
return addStatement(new BlockStatement(tryNode.getBody())); |
|
508 |
} |
|
509 |
return addStatement(ensureUnconditionalCatch(newTryNode)); |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
510 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
511 |
|
17233 | 512 |
/* |
513 |
* create a new trynode |
|
514 |
* if we have catches: |
|
515 |
* |
|
516 |
* try try |
|
517 |
* x try |
|
518 |
* catch x |
|
519 |
* y catch |
|
520 |
* finally z y |
|
521 |
* catchall |
|
522 |
* rethrow |
|
523 |
* |
|
524 |
* otheriwse |
|
525 |
* |
|
526 |
* try try |
|
527 |
* x x |
|
528 |
* finally catchall |
|
529 |
* y rethrow |
|
530 |
* |
|
531 |
* |
|
532 |
* now splice in finally code wherever needed |
|
533 |
* |
|
534 |
*/ |
|
535 |
final Block catchAll = catchAllBlock(tryNode); |
|
536 |
||
28690 | 537 |
final List<ThrowNode> rethrows = new ArrayList<>(1); |
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:
17752
diff
changeset
|
538 |
catchAll.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { |
17233 | 539 |
@Override |
540 |
public boolean enterThrowNode(final ThrowNode throwNode) { |
|
541 |
rethrows.add(throwNode); |
|
542 |
return true; |
|
543 |
} |
|
544 |
}); |
|
545 |
assert rethrows.size() == 1; |
|
546 |
||
28690 | 547 |
if (!tryNode.getCatchBlocks().isEmpty()) { |
548 |
final Block outerBody = new Block(newTryNode.getToken(), newTryNode.getFinish(), ensureUnconditionalCatch(newTryNode)); |
|
549 |
newTryNode = newTryNode.setBody(lc, outerBody).setCatchBlocks(lc, null); |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
550 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
551 |
|
28690 | 552 |
newTryNode = newTryNode.setCatchBlocks(lc, Arrays.asList(catchAll)); |
17233 | 553 |
|
554 |
/* |
|
555 |
* Now that the transform is done, we have to go into the try and splice |
|
556 |
* the finally block in front of any statement that is outside the try |
|
557 |
*/ |
|
28690 | 558 |
return (TryNode)lc.replace(tryNode, spliceFinally(newTryNode, rethrows.get(0), finallyBody)); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
559 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
560 |
|
24759
31aed7d9c02a
8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents:
24751
diff
changeset
|
561 |
private TryNode ensureUnconditionalCatch(final TryNode tryNode) { |
24751 | 562 |
final List<CatchNode> catches = tryNode.getCatches(); |
563 |
if(catches == null || catches.isEmpty() || catches.get(catches.size() - 1).getExceptionCondition() == null) { |
|
564 |
return tryNode; |
|
565 |
} |
|
566 |
// If the last catch block is conditional, add an unconditional rethrow block |
|
567 |
final List<Block> newCatchBlocks = new ArrayList<>(tryNode.getCatchBlocks()); |
|
568 |
||
569 |
newCatchBlocks.add(catchAllBlock(tryNode)); |
|
28690 | 570 |
return tryNode.setCatchBlocks(lc, newCatchBlocks); |
24751 | 571 |
} |
572 |
||
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
573 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
574 |
public Node leaveVarNode(final VarNode varNode) { |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
575 |
addStatement(varNode); |
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:
17752
diff
changeset
|
576 |
if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) && lc.getCurrentFunction().isProgram()) { |
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
577 |
new ExpressionStatement(varNode.getLineNumber(), varNode.getToken(), varNode.getFinish(), new IdentNode(varNode.getName())).accept(this); |
17233 | 578 |
} |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
579 |
return varNode; |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
580 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
581 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
582 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
583 |
public Node leaveWhileNode(final WhileNode whileNode) { |
24751 | 584 |
final Expression test = whileNode.getTest(); |
17233 | 585 |
final Block body = whileNode.getBody(); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
586 |
|
24751 | 587 |
if (isAlwaysTrue(test)) { |
17233 | 588 |
//turn it into a for node without a test. |
27817
56f6161c3e55
8057980: let & const: remaining issues with lexical scoping
hannesw
parents:
27206
diff
changeset
|
589 |
final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), body, 0).accept(this); |
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:
17752
diff
changeset
|
590 |
lc.replace(whileNode, forNode); |
17233 | 591 |
return forNode; |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
592 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
593 |
|
17233 | 594 |
return addStatement(checkEscape(whileNode)); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
595 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
596 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
597 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
598 |
public Node leaveWithNode(final WithNode withNode) { |
17233 | 599 |
return addStatement(withNode); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
600 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
601 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
602 |
/** |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
603 |
* Given a function node that is a callee in a CallNode, replace it with |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
604 |
* the appropriate marker function. This is used by {@link CodeGenerator} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
605 |
* for fast scope calls |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
606 |
* |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
607 |
* @param function function called by a CallNode |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
608 |
* @return transformed node to marker function or identity if not ident/access/indexnode |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
609 |
*/ |
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
610 |
private static Expression markerFunction(final Expression function) { |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
611 |
if (function instanceof IdentNode) { |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
612 |
return ((IdentNode)function).setIsFunction(); |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
613 |
} else if (function instanceof BaseNode) { |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
614 |
return ((BaseNode)function).setIsFunction(); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
615 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
616 |
return function; |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
617 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
618 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
619 |
/** |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
620 |
* Calculate a synthetic eval location for a node for the stacktrace, for example src#17<eval> |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
621 |
* @param node a node |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
622 |
* @return eval location |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
623 |
*/ |
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17233
diff
changeset
|
624 |
private String evalLocation(final IdentNode node) { |
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:
17752
diff
changeset
|
625 |
final Source source = lc.getCurrentFunction().getSource(); |
20929
f2bd18181940
8026167: Class cache/reuse of 'eval' scripts results in ClassCastException in some cases.
sundar
parents:
19100
diff
changeset
|
626 |
final int pos = node.position(); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
627 |
return new StringBuilder(). |
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17233
diff
changeset
|
628 |
append(source.getName()). |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
629 |
append('#'). |
20929
f2bd18181940
8026167: Class cache/reuse of 'eval' scripts results in ClassCastException in some cases.
sundar
parents:
19100
diff
changeset
|
630 |
append(source.getLine(pos)). |
f2bd18181940
8026167: Class cache/reuse of 'eval' scripts results in ClassCastException in some cases.
sundar
parents:
19100
diff
changeset
|
631 |
append(':'). |
f2bd18181940
8026167: Class cache/reuse of 'eval' scripts results in ClassCastException in some cases.
sundar
parents:
19100
diff
changeset
|
632 |
append(source.getColumn(pos)). |
26504 | 633 |
append("<eval>"). |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
634 |
toString(); |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
635 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
636 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
637 |
/** |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
638 |
* Check whether a call node may be a call to eval. In that case we |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
639 |
* clone the args in order to create the following construct in |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
640 |
* {@link CodeGenerator} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
641 |
* |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
642 |
* <pre> |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
643 |
* if (calledFuntion == buildInEval) { |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
644 |
* eval(cloned arg); |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
645 |
* } else { |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
646 |
* cloned arg; |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
647 |
* } |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
648 |
* </pre> |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
649 |
* |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
650 |
* @param callNode call node to check if it's an eval |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
651 |
*/ |
17233 | 652 |
private CallNode checkEval(final CallNode callNode) { |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
653 |
if (callNode.getFunction() instanceof IdentNode) { |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
654 |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
655 |
final List<Expression> args = callNode.getArgs(); |
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
656 |
final IdentNode callee = (IdentNode)callNode.getFunction(); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
657 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
658 |
// 'eval' call with at least one argument |
17233 | 659 |
if (args.size() >= 1 && EVAL.symbolName().equals(callee.getName())) { |
25423
ca63828cf996
8047067: all eval arguments need to be copied in Lower
attila
parents:
25244
diff
changeset
|
660 |
final List<Expression> evalArgs = new ArrayList<>(args.size()); |
ca63828cf996
8047067: all eval arguments need to be copied in Lower
attila
parents:
25244
diff
changeset
|
661 |
for(final Expression arg: args) { |
ca63828cf996
8047067: all eval arguments need to be copied in Lower
attila
parents:
25244
diff
changeset
|
662 |
evalArgs.add((Expression)ensureUniqueNamesIn(arg).accept(this)); |
ca63828cf996
8047067: all eval arguments need to be copied in Lower
attila
parents:
25244
diff
changeset
|
663 |
} |
ca63828cf996
8047067: all eval arguments need to be copied in Lower
attila
parents:
25244
diff
changeset
|
664 |
return callNode.setEvalArgs(new CallNode.EvalArgs(evalArgs, evalLocation(callee))); |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
665 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
666 |
} |
17233 | 667 |
|
668 |
return callNode; |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
669 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
670 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
671 |
/** |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
672 |
* Helper that given a loop body makes sure that it is not terminal if it |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
673 |
* has a continue that leads to the loop header or to outer loops' loop |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
674 |
* headers. This means that, even if the body ends with a terminal |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
675 |
* statement, we cannot tag it as terminal |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
676 |
* |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
677 |
* @param loopBody the loop body to check |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
678 |
* @return true if control flow may escape the loop |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
679 |
*/ |
17233 | 680 |
private static boolean controlFlowEscapes(final LexicalContext lex, final Block loopBody) { |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
681 |
final List<Node> escapes = new ArrayList<>(); |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
682 |
|
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:
17752
diff
changeset
|
683 |
loopBody.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) { |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
684 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
685 |
public Node leaveBreakNode(final BreakNode node) { |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
686 |
escapes.add(node); |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
687 |
return node; |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
688 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
689 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
690 |
@Override |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16524
diff
changeset
|
691 |
public Node leaveContinueNode(final ContinueNode node) { |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
692 |
// all inner loops have been popped. |
26889
dba314d7a634
8059371: Code duplication in handling of break and continue
attila
parents:
26504
diff
changeset
|
693 |
if (lex.contains(node.getTarget(lex))) { |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
694 |
escapes.add(node); |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
695 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
696 |
return node; |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
697 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
698 |
}); |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
699 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
700 |
return !escapes.isEmpty(); |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
701 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
702 |
|
24719 | 703 |
@SuppressWarnings("unchecked") |
704 |
private <T extends LoopNode> T checkEscape(final T loopNode) { |
|
17233 | 705 |
final boolean escapes = controlFlowEscapes(lc, loopNode.getBody()); |
706 |
if (escapes) { |
|
24719 | 707 |
return (T)loopNode. |
17233 | 708 |
setBody(lc, loopNode.getBody().setIsTerminal(lc, false)). |
709 |
setControlFlowEscapes(lc, escapes); |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
710 |
} |
17233 | 711 |
return loopNode; |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
712 |
} |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
713 |
|
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
714 |
|
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
|
715 |
private Node addStatement(final Statement statement) { |
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:
17752
diff
changeset
|
716 |
lc.appendStatement(statement); |
17233 | 717 |
return statement; |
16147 | 718 |
} |
719 |
||
24751 | 720 |
private void addStatementEnclosedInBlock(final Statement stmt) { |
721 |
BlockStatement b = BlockStatement.createReplacement(stmt, Collections.<Statement>singletonList(stmt)); |
|
722 |
if(stmt.isTerminal()) { |
|
723 |
b = b.setBlock(b.getBlock().setIsTerminal(null, true)); |
|
724 |
} |
|
725 |
addStatement(b); |
|
726 |
} |
|
727 |
||
16147 | 728 |
/** |
729 |
* An internal expression has a symbol that is tagged internal. Check if |
|
730 |
* this is such a node |
|
731 |
* |
|
732 |
* @param expression expression to check for internal symbol |
|
733 |
* @return true if internal, false otherwise |
|
734 |
*/ |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
18848
diff
changeset
|
735 |
private static boolean isInternalExpression(final Expression expression) { |
24751 | 736 |
if (!(expression instanceof IdentNode)) { |
737 |
return false; |
|
738 |
} |
|
739 |
final Symbol symbol = ((IdentNode)expression).getSymbol(); |
|
16147 | 740 |
return symbol != null && symbol.isInternal(); |
741 |
} |
|
742 |
||
743 |
/** |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
744 |
* Is this an assignment to the special variable that hosts scripting eval |
17233 | 745 |
* results, i.e. __return__? |
16147 | 746 |
* |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
747 |
* @param expression expression to check whether it is $evalresult = X |
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
748 |
* @return true if an assignment to eval result, false otherwise |
16147 | 749 |
*/ |
17233 | 750 |
private static boolean isEvalResultAssignment(final Node expression) { |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24719
diff
changeset
|
751 |
final Node e = expression; |
17233 | 752 |
if (e instanceof BinaryNode) { |
753 |
final Node lhs = ((BinaryNode)e).lhs(); |
|
754 |
if (lhs instanceof IdentNode) { |
|
755 |
return ((IdentNode)lhs).getName().equals(RETURN.symbolName()); |
|
16206
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
756 |
} |
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
757 |
} |
17233 | 758 |
return false; |
16147 | 759 |
} |
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16188
diff
changeset
|
760 |
} |