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

Side by Side Diff: frog/leg/ssa/bailout.dart

Issue 9668029: Fix a long-standing bug in the computation of the live environments for bailouts. When visiting a l… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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
« no previous file with comments | « frog/leg/emitter.dart ('k') | frog/leg/ssa/nodes.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 class BailoutInfo { 5 class BailoutInfo {
6 int instructionId; 6 int instructionId;
7 int bailoutId; 7 int bailoutId;
8 BailoutInfo(this.instructionId, this.bailoutId); 8 BailoutInfo(this.instructionId, this.bailoutId);
9 } 9 }
10 10
11 /** 11 /**
12 * Keeps track of the execution environment for instructions. An 12 * Keeps track of the execution environment for instructions. An
13 * execution environment contains the SSA instructions that are live. 13 * execution environment contains the SSA instructions that are live.
14 */ 14 */
15 class Environment { 15 class Environment {
16 final Set<HInstruction> lives; 16 final Set<HInstruction> lives;
17 Environment() : lives = new Set<HInstruction>(); 17 final Set<HBasicBlock> loopMarkers;
18 Environment() : lives = new Set<HInstruction>(),
19 loopMarkers = new Set<HBasicBlock>();
18 Environment.from(Environment other) 20 Environment.from(Environment other)
19 : lives = new Set<HInstruction>.from(other.lives); 21 : lives = new Set<HInstruction>.from(other.lives),
22 loopMarkers = new Set<HBasicBlock>.from(other.loopMarkers);
23
24 Environment.forLoop(Environment other)
floitsch 2012/03/12 11:35:10 forLoopBody
ngeoffray 2012/03/12 11:53:24 Done.
25 : lives = new Set<HInstruction>(),
26 loopMarkers = new Set<HBasicBlock>.from(other.loopMarkers);
20 27
21 void remove(HInstruction instruction) { 28 void remove(HInstruction instruction) {
22 lives.remove(instruction); 29 lives.remove(instruction);
23 } 30 }
24 31
25 void add(HInstruction instruction) { 32 void add(HInstruction instruction) {
26 if (!instruction.generateAtUseSite()) { 33 if (!instruction.generateAtUseSite()) {
27 lives.add(instruction); 34 lives.add(instruction);
28 } else { 35 } else {
29 for (int i = 0, len = instruction.inputs.length; i < len; i++) { 36 for (int i = 0, len = instruction.inputs.length; i < len; i++) {
30 add(instruction.inputs[i]); 37 add(instruction.inputs[i]);
31 } 38 }
32 } 39 }
33 } 40 }
34 41
42 void addLoopMarker(HBasicBlock block) {
43 loopMarkers.add(block);
44 }
45
46 void removeLoopMarker(HBasicBlock block) {
47 loopMarkers.remove(block);
48 }
49
35 void addAll(Environment other) { 50 void addAll(Environment other) {
36 lives.addAll(other.lives); 51 lives.addAll(other.lives);
52 loopMarkers.addAll(other.loopMarkers);
37 } 53 }
38 54
39 List<HInstruction> buildAndSetLast(HInstruction instruction) { 55 List<HInstruction> buildAndSetLast(HInstruction instruction) {
40 remove(instruction); 56 remove(instruction);
41 List<HInstruction> result = new List<HInstruction>.from(lives); 57 List<HInstruction> result = new List<HInstruction>.from(lives);
42 result.addLast(instruction); 58 result.addLast(instruction);
43 add(instruction); 59 add(instruction);
44 return result; 60 return result;
45 } 61 }
46 62
47 bool isEmpty() => lives.isEmpty(); 63 bool isEmpty() => lives.isEmpty();
48 bool contains(HInstruction instruction) => lives.contains(instruction); 64 bool contains(HInstruction instruction) => lives.contains(instruction);
65 bool containsLoopMarker(HBasicBlock block) => loopMarkers.contains(block);
49 void clear() => lives.clear(); 66 void clear() => lives.clear();
50 } 67 }
51 68
52 /** 69 /**
53 * Computes the environment for each SSA instruction: visits the graph 70 * Computes the environment for each SSA instruction: visits the graph
54 * in post-dominator order. Removes an instruction from the environment 71 * in post-dominator order. Removes an instruction from the environment
55 * and adds its inputs to the environment at the instruction's 72 * and adds its inputs to the environment at the instruction's
56 * definition. 73 * definition.
57 */ 74 */
58 class SsaEnvironmentBuilder extends HBaseVisitor { 75 class SsaEnvironmentBuilder extends HBaseVisitor {
59 final Compiler compiler; 76 final Compiler compiler;
60 Environment environment; 77 Environment environment;
61 SubGraph subGraph; 78 SubGraph subGraph;
62 79
63 SsaEnvironmentBuilder(Compiler this.compiler); 80 final Map<HInstruction, Environment> capturedEnvironments;
81
82 SsaEnvironmentBuilder(Compiler this.compiler)
83 : capturedEnvironments = new Map<HInstruction, Environment>();
64 84
65 void visitGraph(HGraph graph) { 85 void visitGraph(HGraph graph) {
66 subGraph = new SubGraph(graph.entry, graph.exit); 86 subGraph = new SubGraph(graph.entry, graph.exit);
67 environment = new Environment(); 87 environment = new Environment();
68 visitBasicBlock(graph.entry); 88 visitBasicBlock(graph.entry);
69 assert(environment.isEmpty()); 89 assert(environment.isEmpty());
90 insertCapturedEnvironments();
91 }
92
93 abstract void insertCapturedEnvironments();
94 abstract bool shouldCaptureEnvironment(HInstruction instruction);
95
96 void maybeCaptureEnvironment(HInstruction instruction) {
97 if (shouldCaptureEnvironment(instruction)) {
98 capturedEnvironments[instruction] = new Environment.from(environment);
99 }
70 } 100 }
71 101
72 void visitSubGraph(SubGraph newSubGraph) { 102 void visitSubGraph(SubGraph newSubGraph) {
73 SubGraph oldSubGraph = subGraph; 103 SubGraph oldSubGraph = subGraph;
74 subGraph = newSubGraph; 104 subGraph = newSubGraph;
75 visitBasicBlock(subGraph.start); 105 visitBasicBlock(subGraph.start);
76 subGraph = oldSubGraph; 106 subGraph = oldSubGraph;
77 } 107 }
78 108
79 void visitBasicBlock(HBasicBlock block) { 109 void visitBasicBlock(HBasicBlock block) {
80 if (!subGraph.contains(block)) return; 110 if (!subGraph.contains(block)) return;
81 block.last.accept(this); 111 block.last.accept(this);
82 112
83 HInstruction instruction = block.last.previous; 113 HInstruction instruction = block.last.previous;
84 while (instruction != null) { 114 while (instruction != null) {
85 HInstruction previous = instruction.previous; 115 HInstruction previous = instruction.previous;
86 instruction.accept(this); 116 instruction.accept(this);
87 instruction = previous; 117 instruction = previous;
88 } 118 }
89 119
90 for (HPhi phi = block.phis.first; phi != null; phi = phi.next) { 120 for (HPhi phi = block.phis.first; phi != null; phi = phi.next) {
91 phi.accept(this); 121 phi.accept(this);
92 } 122 }
123
124 if (block.isLoopHeader()) {
floitsch 2012/03/12 11:35:10 Add a comment, maybe even with an example.
ngeoffray 2012/03/12 11:53:24 Done.
125 environment.removeLoopMarker(block);
126 capturedEnvironments.forEach((instruction, env) {
127 if (env.containsLoopMarker(block)) {
128 env.removeLoopMarker(block);
129 env.addAll(environment);
130 }
131 });
132 }
93 } 133 }
94 134
95 void visitPhi(HPhi phi) { 135 void visitPhi(HPhi phi) {
136 maybeCaptureEnvironment(phi);
96 environment.remove(phi); 137 environment.remove(phi);
97 // If the block is a loop header, we insert the incoming values of 138 // If the block is a loop header, we insert the incoming values of
98 // the phis, and remove the loop values. 139 // the phis, and remove the loop values.
99 // If the block is not a loop header, the phi will be handled by 140 // If the block is not a loop header, the phi will be handled by
100 // the control flow instruction. 141 // the control flow instruction.
101 if (phi.block.isLoopHeader()) { 142 if (phi.block.isLoopHeader()) {
102 environment.add(phi.inputs[0]); 143 environment.add(phi.inputs[0]);
103 for (int i = 1, len = phi.inputs.length; i < len; i++) { 144 for (int i = 1, len = phi.inputs.length; i < len; i++) {
104 environment.remove(phi.inputs[i]); 145 environment.remove(phi.inputs[i]);
105 } 146 }
106 } 147 }
107 } 148 }
108 149
109 void visitInstruction(HInstruction instruction) { 150 void visitInstruction(HInstruction instruction) {
151 maybeCaptureEnvironment(instruction);
110 environment.remove(instruction); 152 environment.remove(instruction);
111 for (int i = 0, len = instruction.inputs.length; i < len; i++) { 153 for (int i = 0, len = instruction.inputs.length; i < len; i++) {
112 environment.add(instruction.inputs[i]); 154 environment.add(instruction.inputs[i]);
113 } 155 }
114 } 156 }
115 157
116 void visitIf(HIf instruction) { 158 void visitIf(HIf instruction) {
117 HIfBlockInformation info = instruction.blockInformation; 159 HIfBlockInformation info = instruction.blockInformation;
118 HBasicBlock joinBlock = info.joinBlock; 160 HBasicBlock joinBlock = info.joinBlock;
119 161
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 228
187 void visitBreak(HBreak breakInstruction) { 229 void visitBreak(HBreak breakInstruction) {
188 unimplemented(); 230 unimplemented();
189 } 231 }
190 232
191 void visitLoopBranch(HLoopBranch branch) { 233 void visitLoopBranch(HLoopBranch branch) {
192 HBasicBlock block = branch.block; 234 HBasicBlock block = branch.block;
193 235
194 // Visit the code after the loop. 236 // Visit the code after the loop.
195 visitBasicBlock(block.successors[1]); 237 visitBasicBlock(block.successors[1]);
196 // TODO(ngeoffray): Remove the instructions of the loop-exit from
197 // the environment.
198 238
239 Environment joinEnvironment = environment;
240
241 // When visiting the loop body, we don't require the live
242 // instructions after the loop body to be in the environment. They
243 // will be either recomputed in the loop header, or inserted
244 // with the loop marker.
floitsch 2012/03/12 11:35:10 However we need the current environment to transfe
ngeoffray 2012/03/12 11:53:24 Done.
245 environment = new Environment.forLoop(environment);
246
247 // Put the loop phis in the environment.
199 HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader; 248 HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader;
200 // Put the loop phis in the environment.
201 for (HPhi phi = header.phis.first; phi != null; phi = phi.next) { 249 for (HPhi phi = header.phis.first; phi != null; phi = phi.next) {
202 for (int i = 1, len = phi.inputs.length; i < len; i++) { 250 for (int i = 1, len = phi.inputs.length; i < len; i++) {
203 environment.add(phi.inputs[i]); 251 environment.add(phi.inputs[i]);
204 } 252 }
205 } 253 }
206 254
255 // Add the loop marker
256 environment.addLoopMarker(header);
257
207 if (!branch.isDoWhile()) { 258 if (!branch.isDoWhile()) {
208 assert(block.successors[0] == block.dominatedBlocks[0]); 259 assert(block.successors[0] == block.dominatedBlocks[0]);
209 visitBasicBlock(block.successors[0]); 260 visitBasicBlock(block.successors[0]);
210 } 261 }
262
263 // We merge the environment required by the code after the loop,
264 // and the code inside the loop.
265 environment.addAll(joinEnvironment);
211 } 266 }
212 267
213 // Deal with all kinds of control flow instructions. In case we add 268 // Deal with all kinds of control flow instructions. In case we add
214 // a new one, we will hit an internal error. 269 // a new one, we will hit an internal error.
215 void visitExit(HExit exit) {} 270 void visitExit(HExit exit) {}
216 271
217 void visitReturn(HReturn instruction) { 272 void visitReturn(HReturn instruction) {
218 environment.clear(); 273 environment.clear();
219 visitInstruction(instruction); 274 visitInstruction(instruction);
220 } 275 }
(...skipping 12 matching lines...) Expand all
233 /** 288 /**
234 * Visits the graph and replaces guards with guards that capture the 289 * Visits the graph and replaces guards with guards that capture the
235 * environment. 290 * environment.
236 */ 291 */
237 class SsaTypeGuardBuilder extends SsaEnvironmentBuilder implements OptimizationP hase { 292 class SsaTypeGuardBuilder extends SsaEnvironmentBuilder implements OptimizationP hase {
238 293
239 final String name = 'SsaTypeGuardBuilder'; 294 final String name = 'SsaTypeGuardBuilder';
240 295
241 SsaTypeGuardBuilder(Compiler compiler) : super(compiler); 296 SsaTypeGuardBuilder(Compiler compiler) : super(compiler);
242 297
243 void tryInsertTypeGuard(HInstruction instruction, 298 bool shouldCaptureEnvironment(HInstruction instruction) {
244 HInstruction insertionPoint) { 299 return instruction.type.isKnown() && !instruction.hasExpectedType();
245 // If we found a type for the instruction, but the instruction 300 }
246 // does not know if it produces that type, add a type guard. 301
247 if (instruction.type.isKnown() && !instruction.hasExpectedType()) { 302 void insertCapturedEnvironments() {
248 // The type guard expects the guarded instruction to be at the 303 capturedEnvironments.forEach((HInstruction instruction, Environment env) {
249 // end of the inputs. 304 List<HInstruction> inputs = env.buildAndSetLast(instruction);
250 List<HInstruction> inputs = environment.buildAndSetLast(instruction);
251 HTypeGuard guard = 305 HTypeGuard guard =
252 new HTypeGuard(instruction.type, inputs, instruction.id); 306 new HTypeGuard(instruction.type, inputs, instruction.id);
253 // Remove the instruction's type, the guard is now holding that 307 // Remove the instruction's type, the guard is now holding that
254 // type. 308 // type.
255 instruction.type = HType.UNKNOWN; 309 instruction.type = HType.UNKNOWN;
256 instruction.block.rewrite(instruction, guard); 310 instruction.block.rewrite(instruction, guard);
311 HInstruction insertionPoint = (instruction is HPhi)
312 ? phi.block.first
313 : instruction.next;
257 insertionPoint.block.addBefore(insertionPoint, guard); 314 insertionPoint.block.addBefore(insertionPoint, guard);
258 } 315 });
259 }
260
261
262 void visitInstruction(HInstruction instruction) {
263 tryInsertTypeGuard(instruction, instruction.next);
264 super.visitInstruction(instruction);
265 }
266
267 void visitPhi(HPhi phi) {
268 tryInsertTypeGuard(phi, phi.block.first);
269 super.visitPhi(phi);
270 } 316 }
271 } 317 }
272 318
273 /* 319 /*
274 * Visits the graph and inserts [HBailoutTarget] instructions where 320 * Visits the graph and inserts [HBailoutTarget] instructions where
275 * the optimized version had [HTypeGuard] instructions. 321 * the optimized version had [HTypeGuard] instructions.
276 */ 322 */
277 class SsaBailoutBuilder extends SsaEnvironmentBuilder implements OptimizationPha se { 323 class SsaBailoutBuilder extends SsaEnvironmentBuilder implements OptimizationPha se {
278 final Map<int, BailoutInfo> bailouts; 324 final Map<int, BailoutInfo> bailouts;
279 final String name = 'SsaBailoutBuilder'; 325 final String name = 'SsaBailoutBuilder';
280 326
281 SsaBailoutBuilder(Compiler compiler, this.bailouts) : super(compiler); 327 SsaBailoutBuilder(Compiler compiler, this.bailouts) : super(compiler);
282 328
283 void checkBailout(HInstruction instruction, HInstruction insertionPoint) { 329 bool shouldCaptureEnvironment(HInstruction instruction) {
284 BailoutInfo info = bailouts[instruction.id]; 330 return bailouts[instruction.id] != null;
285 if (info != null) {
286 List<HInstruction> inputs = environment.buildAndSetLast(instruction);
287 HBailoutTarget bailout = new HBailoutTarget(info.bailoutId, inputs);
288 instruction.block.addBefore(insertionPoint, bailout);
289 }
290 } 331 }
291 332
292 void visitInstruction(HInstruction instruction) { 333 void insertCapturedEnvironments() {
293 checkBailout(instruction, instruction.next); 334 capturedEnvironments.forEach((HInstruction instruction, Environment env) {
294 super.visitInstruction(instruction); 335 BailoutInfo info = bailouts[instruction.id];
295 } 336 List<HInstruction> inputs = env.buildAndSetLast(instruction);
296 337 HBailoutTarget bailout = new HBailoutTarget(info.bailoutId, inputs);
297 void visitPhi(HPhi phi) { 338 HInstruction insertionPoint = (instruction is HPhi)
298 checkBailout(phi, phi.block.first); 339 ? phi.block.first
299 super.visitPhi(phi); 340 : instruction.next;
341 instruction.block.addBefore(insertionPoint, bailout);
342 });
300 } 343 }
301 } 344 }
302 345
303 /** 346 /**
304 * Propagates bailout information to blocks that need it. This visitor 347 * Propagates bailout information to blocks that need it. This visitor
305 * is run before codegen, to know which blocks have to deal with 348 * is run before codegen, to know which blocks have to deal with
306 * bailouts. 349 * bailouts.
307 */ 350 */
308 class SsaBailoutPropagator extends HBaseVisitor { 351 class SsaBailoutPropagator extends HBaseVisitor {
309 final Compiler compiler; 352 final Compiler compiler;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 compiler.internalError('Control flow instructions already dealt with.', 407 compiler.internalError('Control flow instructions already dealt with.',
365 instruction: instruction); 408 instruction: instruction);
366 } 409 }
367 410
368 visitBailoutTarget(HBailoutTarget target) { 411 visitBailoutTarget(HBailoutTarget target) {
369 blocks.forEach((HBasicBlock block) { 412 blocks.forEach((HBasicBlock block) {
370 block.bailouts.add(target); 413 block.bailouts.add(target);
371 }); 414 });
372 } 415 }
373 } 416 }
OLDNEW
« no previous file with comments | « frog/leg/emitter.dart ('k') | frog/leg/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698