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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/bailout.dart

Issue 11411068: Fix bad assumption of environment builder when it comes to nested loops: blocks inside a loop would… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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
« no previous file with comments | « no previous file | tests/language/bailout4_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 part of ssa; 5 part of ssa;
6 6
7 class BailoutInfo { 7 class BailoutInfo {
8 int instructionId; 8 int instructionId;
9 int bailoutId; 9 int bailoutId;
10 BailoutInfo(this.instructionId, this.bailoutId); 10 BailoutInfo(this.instructionId, this.bailoutId);
11 } 11 }
12 12
13 /** 13 /**
14 * Keeps track of the execution environment for instructions. An 14 * Keeps track of the execution environment for instructions. An
15 * execution environment contains the SSA instructions that are live. 15 * execution environment contains the SSA instructions that are live.
16 */ 16 */
17 class Environment { 17 class Environment {
18 final Set<HInstruction> lives; 18 final Set<HInstruction> lives;
19 final Set<HBasicBlock> loopMarkers; 19 final List<HBasicBlock> loopMarkers;
20 Environment() : lives = new Set<HInstruction>(), 20 Environment() : lives = new Set<HInstruction>(),
21 loopMarkers = new Set<HBasicBlock>(); 21 loopMarkers = new List<HBasicBlock>();
22 Environment.from(Environment other) 22 Environment.from(Environment other)
23 : lives = new Set<HInstruction>.from(other.lives), 23 : lives = new Set<HInstruction>.from(other.lives),
24 loopMarkers = new Set<HBasicBlock>.from(other.loopMarkers); 24 loopMarkers = new List<HBasicBlock>.from(other.loopMarkers);
25 25
26 void remove(HInstruction instruction) { 26 void remove(HInstruction instruction) {
27 lives.remove(instruction); 27 lives.remove(instruction);
28 } 28 }
29 29
30 void add(HInstruction instruction) { 30 void add(HInstruction instruction) {
31 // If the instruction is a check, we add its checked input 31 // If the instruction is a check, we add its checked input
32 // instead. This allows sharing the same environment between 32 // instead. This allows sharing the same environment between
33 // different type guards. 33 // different type guards.
34 // 34 //
35 // Also, we don't need to add code motion invariant instructions 35 // Also, we don't need to add code motion invariant instructions
36 // in the live set (because we generate them at use-site), except 36 // in the live set (because we generate them at use-site), except
37 // for parameters that are not 'this', which is always passed as 37 // for parameters that are not 'this', which is always passed as
38 // the receiver. 38 // the receiver.
39 if (instruction is HCheck) { 39 if (instruction is HCheck) {
40 add(instruction.checkedInput); 40 add(instruction.checkedInput);
41 } else if (!instruction.isCodeMotionInvariant() 41 } else if (!instruction.isCodeMotionInvariant()
42 || (instruction is HParameterValue && instruction is !HThis)) { 42 || (instruction is HParameterValue && instruction is !HThis)) {
43 lives.add(instruction); 43 lives.add(instruction);
44 } else { 44 } else {
45 for (int i = 0, len = instruction.inputs.length; i < len; i++) { 45 for (int i = 0, len = instruction.inputs.length; i < len; i++) {
46 add(instruction.inputs[i]); 46 add(instruction.inputs[i]);
47 } 47 }
48 } 48 }
49 } 49 }
50 50
51 void addLoopMarker(HBasicBlock block) {
52 loopMarkers.add(block);
53 }
54
55 void removeLoopMarker(HBasicBlock block) {
56 loopMarkers.remove(block);
57 }
58
59 void addAll(Environment other) { 51 void addAll(Environment other) {
60 lives.addAll(other.lives); 52 lives.addAll(other.lives);
61 loopMarkers.addAll(other.loopMarkers);
62 } 53 }
63 54
64 bool get isEmpty => lives.isEmpty && loopMarkers.isEmpty; 55 bool get isEmpty => lives.isEmpty && loopMarkers.isEmpty;
56
57 String toString() => '${loopMarkers.length}';
floitsch 2012/11/20 15:39:31 Remove or make it at least mention "Environment".
ngeoffray 2012/11/20 16:40:37 Removed.
65 } 58 }
66 59
67 60
68 /** 61 /**
69 * Visits the graph in dominator order and inserts TypeGuards in places where 62 * Visits the graph in dominator order and inserts TypeGuards in places where
70 * we consider the guard to be of value. 63 * we consider the guard to be of value.
71 * 64 *
72 * Might modify the [types] in an inconsistent way. No further analysis should 65 * Might modify the [types] in an inconsistent way. No further analysis should
73 * rely on them. 66 * rely on them.
74 */ 67 */
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 * 243 *
251 * At the end of the computation, insert type guards in the graph. 244 * At the end of the computation, insert type guards in the graph.
252 */ 245 */
253 class SsaEnvironmentBuilder extends HBaseVisitor implements OptimizationPhase { 246 class SsaEnvironmentBuilder extends HBaseVisitor implements OptimizationPhase {
254 final Compiler compiler; 247 final Compiler compiler;
255 final String name = 'SsaEnvironmentBuilder'; 248 final String name = 'SsaEnvironmentBuilder';
256 249
257 final Map<HBailoutTarget, Environment> capturedEnvironments; 250 final Map<HBailoutTarget, Environment> capturedEnvironments;
258 final Map<HBasicBlock, Environment> liveInstructions; 251 final Map<HBasicBlock, Environment> liveInstructions;
259 Environment environment; 252 Environment environment;
253 List<HBasicBlock> loopMarkers;
floitsch 2012/11/20 15:39:31 Add comment explaining what these contain.
ngeoffray 2012/11/20 16:40:37 Done.
260 254
261 SsaEnvironmentBuilder(Compiler this.compiler) 255 SsaEnvironmentBuilder(Compiler this.compiler)
262 : capturedEnvironments = new Map<HBailoutTarget, Environment>(), 256 : capturedEnvironments = new Map<HBailoutTarget, Environment>(),
263 liveInstructions = new Map<HBasicBlock, Environment>(); 257 liveInstructions = new Map<HBasicBlock, Environment>(),
258 loopMarkers = <HBasicBlock>[];
264 259
265 260
266 void visitGraph(HGraph graph) { 261 void visitGraph(HGraph graph) {
267 visitPostDominatorTree(graph); 262 visitPostDominatorTree(graph);
268 if (!liveInstructions[graph.entry].isEmpty) { 263 if (!liveInstructions[graph.entry].isEmpty) {
269 compiler.internalError('Bailout environment computation', 264 compiler.internalError('Bailout environment computation',
270 node: compiler.currentElement.parseNode(compiler)); 265 node: compiler.currentElement.parseNode(compiler));
271 } 266 }
272 updateLoopMarkers(); 267 updateLoopMarkers();
273 insertCapturedEnvironments(); 268 insertCapturedEnvironments();
274 } 269 }
275 270
276 void updateLoopMarkers() { 271 void updateLoopMarkers() {
277 // If the block is a loop header, we need to merge the loop 272 // If the block is a loop header, we need to merge the loop
278 // header's live instructions into every environment that contains 273 // header's live instructions into every environment that contains
279 // the loop marker. 274 // the loop marker.
280 // For example with the following loop (read the example in 275 // For example with the following loop (read the example in
281 // reverse): 276 // reverse):
282 // 277 //
283 // while (true) { <-- (4) update the marker with the environment 278 // while (true) { <-- (4) update the marker with the environment
284 // use(x); <-- (3) environment = {x} 279 // use(x); <-- (3) environment = {x}
285 // bailout; <-- (2) has the marker when computed 280 // bailout; <-- (2) has the marker when computed
286 // } <-- (1) create a loop marker 281 // } <-- (1) create a loop marker
287 // 282 //
288 // The bailout instruction first captures the marker, but it 283 // The bailout instruction first captures the marker, but it
289 // will be replaced by the live environment at the loop entry, 284 // will be replaced by the live environment at the loop entry,
290 // in this case {x}. 285 // in this case {x}.
291 capturedEnvironments.forEach((ignoredInstruction, env) { 286 capturedEnvironments.forEach((ignoredInstruction, env) {
292 env.loopMarkers.forEach((HBasicBlock header) { 287 env.loopMarkers.forEach((HBasicBlock header) {
293 env.removeLoopMarker(header);
294 env.addAll(liveInstructions[header]); 288 env.addAll(liveInstructions[header]);
295 }); 289 });
290 env.loopMarkers.clear();
296 }); 291 });
297 } 292 }
298 293
299 void visitBasicBlock(HBasicBlock block) { 294 void visitBasicBlock(HBasicBlock block) {
300 environment = new Environment(); 295 environment = new Environment();
301 296
302 // Add to the environment the live instructions of its successor, as well as 297 // Add to the environment the live instructions of its successor, as well as
303 // the inputs of the phis of the successor that flow from this block. 298 // the inputs of the phis of the successor that flow from this block.
304 for (int i = 0; i < block.successors.length; i++) { 299 for (int i = 0; i < block.successors.length; i++) {
305 HBasicBlock successor = block.successors[i]; 300 HBasicBlock successor = block.successors[i];
306 Environment successorEnv = liveInstructions[successor]; 301 Environment successorEnv = liveInstructions[successor];
307 if (successorEnv != null) { 302 if (successorEnv != null) {
308 environment.addAll(successorEnv); 303 environment.addAll(successorEnv);
309 } else { 304 } else {
310 // If we haven't computed the liveInstructions of that successor, we 305 // If we haven't computed the liveInstructions of that successor, we
311 // know it must be a loop header. 306 // know it must be a loop header.
312 assert(successor.isLoopHeader()); 307 assert(successor.isLoopHeader());
313 environment.addLoopMarker(successor); 308 assert(!block.isLoopHeader());
309 loopMarkers.add(successor);
314 } 310 }
315 311
316 int index = successor.predecessors.indexOf(block); 312 int index = successor.predecessors.indexOf(block);
317 for (HPhi phi = successor.phis.first; phi != null; phi = phi.next) { 313 for (HPhi phi = successor.phis.first; phi != null; phi = phi.next) {
318 environment.add(phi.inputs[index]); 314 environment.add(phi.inputs[index]);
319 } 315 }
320 } 316 }
321 317
318 // If the block is a loop header, we can remove the loop marker,
floitsch 2012/11/20 15:39:31 This sounds too much like an optimization. In fact
ngeoffray 2012/11/20 16:40:37 Improved comment.
319 // because it will just recompute the loop phis.
320 if (block.isLoopHeader()) {
321 loopMarkers.removeLast();
floitsch 2012/11/20 15:39:31 assert that it is the same as block?
ngeoffray 2012/11/20 16:40:37 Done.
ngeoffray 2012/11/20 17:30:45 Actually, I had to change the data structure to be
322 }
323
324 environment.loopMarkers.addAll(loopMarkers);
325
322 // Iterate over all instructions to remove an instruction from the 326 // Iterate over all instructions to remove an instruction from the
323 // environment and add its inputs. 327 // environment and add its inputs.
324 HInstruction instruction = block.last; 328 HInstruction instruction = block.last;
325 while (instruction != null) { 329 while (instruction != null) {
326 instruction.accept(this); 330 instruction.accept(this);
327 instruction = instruction.previous; 331 instruction = instruction.previous;
328 } 332 }
329 333
330 // We just remove the phis from the environment. The inputs of the 334 // We just remove the phis from the environment. The inputs of the
331 // phis will be put in the environment of the predecessors. 335 // phis will be put in the environment of the predecessors.
332 for (HPhi phi = block.phis.first; phi != null; phi = phi.next) { 336 for (HPhi phi = block.phis.first; phi != null; phi = phi.next) {
333 environment.remove(phi); 337 environment.remove(phi);
334 } 338 }
335 339
336 // If the block is a loop header, we can remove the loop marker,
337 // because it will just recompute the loop phis.
338 if (block.isLoopHeader()) {
339 environment.removeLoopMarker(block);
340 }
341
342 // Finally save the liveInstructions of that block. 340 // Finally save the liveInstructions of that block.
343 liveInstructions[block] = environment; 341 liveInstructions[block] = environment;
344 } 342 }
345 343
346 void visitBailoutTarget(HBailoutTarget target) { 344 void visitBailoutTarget(HBailoutTarget target) {
347 visitInstruction(target); 345 visitInstruction(target);
348 capturedEnvironments[target] = new Environment.from(environment); 346 capturedEnvironments[target] = new Environment.from(environment);
349 } 347 }
350 348
351 void visitInstruction(HInstruction instruction) { 349 void visitInstruction(HInstruction instruction) {
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 hasComplexBailoutTargets = true; 537 hasComplexBailoutTargets = true;
540 } 538 }
541 } else { 539 } else {
542 hasComplexBailoutTargets = true; 540 hasComplexBailoutTargets = true;
543 blocks.forEach((HBasicBlock block) { 541 blocks.forEach((HBasicBlock block) {
544 block.bailoutTargets.add(target); 542 block.bailoutTargets.add(target);
545 }); 543 });
546 } 544 }
547 } 545 }
548 } 546 }
OLDNEW
« no previous file with comments | « no previous file | tests/language/bailout4_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698