Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(342)

Side by Side Diff: lib/compiler/implementation/ssa/codegen_helpers.dart

Issue 10660026: Don't allow statement-nodes in expression contexts. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix test for checked mode. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * Instead of emitting each SSA instruction with a temporary variable 6 * Instead of emitting each SSA instruction with a temporary variable
7 * mark instructions that can be emitted at their use-site. 7 * mark instructions that can be emitted at their use-site.
8 * For example, in: 8 * For example, in:
9 * t0 = 4; 9 * t0 = 4;
10 * t1 = 3; 10 * t1 = 3;
11 * t2 = add(t0, t1); 11 * t2 = add(t0, t1);
12 * t0 and t1 would be marked and the resulting code would then be: 12 * t0 and t1 would be marked and the resulting code would then be:
13 * t2 = add(4, 3); 13 * t2 = add(4, 3);
14 */ 14 */
15 class SsaInstructionMerger extends HBaseVisitor { 15 class SsaInstructionMerger extends HBaseVisitor {
16 List<HInstruction> expectedInputs; 16 List<HInstruction> expectedInputs;
17 Set<HInstruction> generateAtUseSite; 17 Set<HInstruction> generateAtUseSite;
18 18
19 void markAsGenerateAtUseSite(HInstruction instruction) {
20 assert(!instruction.isStatement);
21 generateAtUseSite.add(instruction);
22 }
23
19 SsaInstructionMerger(this.generateAtUseSite); 24 SsaInstructionMerger(this.generateAtUseSite);
20 25
21 void visitGraph(HGraph graph) { 26 void visitGraph(HGraph graph) {
22 visitDominatorTree(graph); 27 visitDominatorTree(graph);
23 } 28 }
24 29
25 void visitInstruction(HInstruction instruction) { 30 void visitInstruction(HInstruction instruction) {
26 // A code motion invariant instruction is dealt before visiting it. 31 // A code motion invariant instruction is dealt before visiting it.
27 assert(!instruction.isCodeMotionInvariant()); 32 assert(!instruction.isCodeMotionInvariant());
28 for (HInstruction input in instruction.inputs) { 33 for (HInstruction input in instruction.inputs) {
(...skipping 24 matching lines...) Expand all
53 if (!instruction.builtin) super.visitEquals(instruction); 58 if (!instruction.builtin) super.visitEquals(instruction);
54 // Otherwise do nothing. 59 // Otherwise do nothing.
55 } 60 }
56 61
57 // Identity operations must not have its input generated at use site, because 62 // Identity operations must not have its input generated at use site, because
58 // it's using it multiple times (because of null/undefined). 63 // it's using it multiple times (because of null/undefined).
59 void visitIdentity(HIdentity instruction) {} 64 void visitIdentity(HIdentity instruction) {}
60 65
61 void visitTypeConversion(HTypeConversion instruction) { 66 void visitTypeConversion(HTypeConversion instruction) {
62 if (!instruction.isChecked) { 67 if (!instruction.isChecked) {
63 generateAtUseSite.add(instruction); 68 markAsGenerateAtUseSite(instruction);
64 } else if (instruction.isCheckedModeCheck) { 69 } else if (instruction.isCheckedModeCheck) {
65 // Checked mode checks compile to code that only use their input 70 // Checked mode checks compile to code that only use their input
66 // once, so we can safely visit them and try to merge the input. 71 // once, so we can safely visit them and try to merge the input.
67 visitInstruction(instruction); 72 visitInstruction(instruction);
68 } 73 }
69 } 74 }
70 75
71 void tryGenerateAtUseSite(HInstruction instruction) { 76 void tryGenerateAtUseSite(HInstruction instruction) {
72 if (instruction.isControlFlow()) return; 77 if (instruction.isControlFlow()) return;
73 generateAtUseSite.add(instruction); 78 markAsGenerateAtUseSite(instruction);
74 } 79 }
75 80
76 bool isBlockSinglePredecessor(HBasicBlock block) { 81 bool isBlockSinglePredecessor(HBasicBlock block) {
77 return block.successors.length === 1 82 return block.successors.length === 1
78 && block.successors[0].predecessors.length === 1; 83 && block.successors[0].predecessors.length === 1;
79 } 84 }
80 85
81 void visitBasicBlock(HBasicBlock block) { 86 void visitBasicBlock(HBasicBlock block) {
82 // Compensate from not merging blocks: if the block is the 87 // Compensate from not merging blocks: if the block is the
83 // single predecessor of its single successor, let the successor 88 // single predecessor of its single successor, let the successor
(...skipping 28 matching lines...) Expand all
112 } 117 }
113 118
114 block.last.accept(this); 119 block.last.accept(this);
115 for (HInstruction instruction = block.last.previous; 120 for (HInstruction instruction = block.last.previous;
116 instruction !== null; 121 instruction !== null;
117 instruction = instruction.previous) { 122 instruction = instruction.previous) {
118 if (generateAtUseSite.contains(instruction)) { 123 if (generateAtUseSite.contains(instruction)) {
119 continue; 124 continue;
120 } 125 }
121 if (instruction.isCodeMotionInvariant()) { 126 if (instruction.isCodeMotionInvariant()) {
122 generateAtUseSite.add(instruction); 127 markAsGenerateAtUseSite(instruction);
123 continue; 128 continue;
124 } 129 }
130 if (instruction.isStatement) {
ngeoffray 2012/08/17 13:08:58 Please explain which inputs can be statements. May
floitsch 2012/08/29 11:03:12 Changed to isJsStatement.
131 expectedInputs.clear();
132 }
125 // See if the current instruction is the next non-trivial 133 // See if the current instruction is the next non-trivial
126 // expected input. 134 // expected input.
127 if (findInInputsAndPopNonMatching(instruction)) { 135 if (findInInputsAndPopNonMatching(instruction)) {
128 tryGenerateAtUseSite(instruction); 136 tryGenerateAtUseSite(instruction);
129 } else { 137 } else {
130 assert(expectedInputs.isEmpty()); 138 assert(expectedInputs.isEmpty());
131 } 139 }
132 instruction.accept(this); 140 instruction.accept(this);
133 } 141 }
134 142
135 if (block.predecessors.length === 1 143 if (block.predecessors.length === 1
136 && isBlockSinglePredecessor(block.predecessors[0])) { 144 && isBlockSinglePredecessor(block.predecessors[0])) {
137 assert(block.phis.isEmpty()); 145 assert(block.phis.isEmpty());
138 tryMergingExpressions(block.predecessors[0]); 146 tryMergingExpressions(block.predecessors[0]);
139 } else { 147 } else {
140 expectedInputs = null; 148 expectedInputs = null;
141 } 149 }
142 } 150 }
143 } 151 }
144 152
145 /** 153 /**
146 * Detect control flow arising from short-circuit logical and 154 * Detect control flow arising from short-circuit logical and
147 * conditional operators, and prepare the program to be generated 155 * conditional operators, and prepare the program to be generated
148 * using these operators instead of nested ifs and boolean variables. 156 * using these operators instead of nested ifs and boolean variables.
149 */ 157 */
150 class SsaConditionMerger extends HGraphVisitor { 158 class SsaConditionMerger extends HGraphVisitor {
151 Set<HInstruction> generateAtUseSite; 159 Set<HInstruction> generateAtUseSite;
152 Set<HInstruction> controlFlowOperators; 160 Set<HInstruction> controlFlowOperators;
153 161
162 void markAsGenerateAtUseSite(HInstruction instruction) {
163 assert(!instruction.isStatement);
164 generateAtUseSite.add(instruction);
165 }
166
154 SsaConditionMerger(this.generateAtUseSite, this.controlFlowOperators); 167 SsaConditionMerger(this.generateAtUseSite, this.controlFlowOperators);
155 168
156 void visitGraph(HGraph graph) { 169 void visitGraph(HGraph graph) {
157 visitPostDominatorTree(graph); 170 visitPostDominatorTree(graph);
158 } 171 }
159 172
160 /** 173 /**
161 * Check if a block has at least one statement other than 174 * Check if a block has at least one statement other than
162 * [instruction]. 175 * [instruction].
163 */ 176 */
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 // phi(expr, true|false) 228 // phi(expr, true|false)
216 if (end == null) return; 229 if (end == null) return;
217 if (end.phis.isEmpty()) return; 230 if (end.phis.isEmpty()) return;
218 if (end.phis.first !== end.phis.last) return; 231 if (end.phis.first !== end.phis.last) return;
219 HBasicBlock elseBlock = startIf.elseBlock; 232 HBasicBlock elseBlock = startIf.elseBlock;
220 233
221 if (end.predecessors[1] !== elseBlock) return; 234 if (end.predecessors[1] !== elseBlock) return;
222 HPhi phi = end.phis.first; 235 HPhi phi = end.phis.first;
223 HInstruction thenInput = phi.inputs[0]; 236 HInstruction thenInput = phi.inputs[0];
224 HInstruction elseInput = phi.inputs[1]; 237 HInstruction elseInput = phi.inputs[1];
238 if (thenInput.isStatement || elseInput.isStatement) return;
225 239
226 if (hasAnyStatement(elseBlock, elseInput)) return; 240 if (hasAnyStatement(elseBlock, elseInput)) return;
227 assert(elseBlock.successors.length == 1); 241 assert(elseBlock.successors.length == 1);
228 assert(end.predecessors.length == 2); 242 assert(end.predecessors.length == 2);
229 243
230 HBasicBlock thenBlock = startIf.thenBlock; 244 HBasicBlock thenBlock = startIf.thenBlock;
231 // Skip trivial goto blocks. 245 // Skip trivial goto blocks.
232 while (thenBlock.successors[0] != end && thenBlock.first is HGoto) { 246 while (thenBlock.successors[0] != end && thenBlock.first is HGoto) {
233 thenBlock = thenBlock.successors[0]; 247 thenBlock = thenBlock.successors[0];
234 } 248 }
235 249
236 // If the [thenBlock] is already a control flow operation, and does not 250 // If the [thenBlock] is already a control flow operation, and does not
237 // have any statement and its join block is [end], we can emit a 251 // have any statement and its join block is [end], we can emit a
238 // sequence of control flow operation. 252 // sequence of control flow operation.
239 if (controlFlowOperators.contains(thenBlock.last)) { 253 if (controlFlowOperators.contains(thenBlock.last)) {
240 HIf otherIf = thenBlock.last; 254 HIf otherIf = thenBlock.last;
241 if (otherIf.joinBlock !== end) return; 255 if (otherIf.joinBlock !== end) return;
242 if (hasAnyStatement(thenBlock, otherIf)) return; 256 if (hasAnyStatement(thenBlock, otherIf)) return;
243 } else { 257 } else {
244 if (end.predecessors[0] !== thenBlock) return; 258 if (end.predecessors[0] !== thenBlock) return;
245 if (hasAnyStatement(thenBlock, thenInput)) return; 259 if (hasAnyStatement(thenBlock, thenInput)) return;
246 assert(thenBlock.successors.length == 1); 260 assert(thenBlock.successors.length == 1);
247 } 261 }
248 262
249 // From now on, we have recognized a control flow operation built from 263 // From now on, we have recognized a control flow operation built from
250 // the builder. Mark the if instruction as such. 264 // the builder. Mark the if instruction as such.
251 controlFlowOperators.add(startIf); 265 controlFlowOperators.add(startIf);
252 266
253 // If the operation is only used by the first instruction 267 // If the operation is only used by the first instruction
254 // of its block and is safe to be generated at use sute, mark it 268 // of its block and is safe to be generated at use site, mark it
255 // so. 269 // so.
256 if (phi.usedBy.length == 1 270 if (phi.usedBy.length == 1
257 && phi.usedBy[0] === phi.block.first 271 && phi.usedBy[0] === phi.block.first
258 && isSafeToGenerateAtUseSite(phi.usedBy[0], phi)) { 272 && isSafeToGenerateAtUseSite(phi.usedBy[0], phi)) {
259 generateAtUseSite.add(phi); 273 markAsGenerateAtUseSite(phi);
260 } 274 }
261 275
262 if (elseInput.block === elseBlock) { 276 if (elseInput.block === elseBlock) {
263 assert(elseInput.usedBy.length == 1); 277 assert(elseInput.usedBy.length == 1);
264 generateAtUseSite.add(elseInput); 278 markAsGenerateAtUseSite(elseInput);
265 } 279 }
266 280
267 // If [thenInput] is defined in the first predecessor, then it is only used 281 // If [thenInput] is defined in the first predecessor, then it is only used
268 // by [phi] and can be generated at use site. 282 // by [phi] and can be generated at use site.
269 if (thenInput.block === end.predecessors[0]) { 283 if (thenInput.block === end.predecessors[0]) {
270 assert(thenInput.usedBy.length == 1); 284 assert(thenInput.usedBy.length == 1);
271 generateAtUseSite.add(thenInput); 285 markAsGenerateAtUseSite(thenInput);
272 } 286 }
273 } 287 }
274 } 288 }
275 289
276 // Precedence information for JavaScript operators. 290 // Precedence information for JavaScript operators.
277 class JSPrecedence { 291 class JSPrecedence {
278 // Used as precedence for something that's not even an expression. 292 // Used as precedence for something that's not even an expression.
279 static final int STATEMENT_PRECEDENCE = 0; 293 static final int STATEMENT_PRECEDENCE = 0;
280 // Precedences of JS operators. 294 // Precedences of JS operators.
281 static final int EXPRESSION_PRECEDENCE = 1; 295 static final int EXPRESSION_PRECEDENCE = 1;
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 }; 360 };
347 } 361 }
348 362
349 class JSBinaryOperatorPrecedence { 363 class JSBinaryOperatorPrecedence {
350 final int left; 364 final int left;
351 final int right; 365 final int right;
352 const JSBinaryOperatorPrecedence(this.left, this.right); 366 const JSBinaryOperatorPrecedence(this.left, this.right);
353 // All binary operators (excluding assignment) are left associative. 367 // All binary operators (excluding assignment) are left associative.
354 int get precedence() => left; 368 int get precedence() => left;
355 } 369 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/nodes.dart » ('j') | tests/language/side_effect_throw_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698