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

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

Issue 10544132: Revert r8592: failures on checked mode and some web tests. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 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 | « no previous file | lib/compiler/implementation/ssa/codegen.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 final Set<HBasicBlock> loopMarkers; 17 final Set<HBasicBlock> loopMarkers;
18 Environment() : lives = new Set<HInstruction>(), 18 Environment() : lives = new Set<HInstruction>(),
19 loopMarkers = new Set<HBasicBlock>(); 19 loopMarkers = new Set<HBasicBlock>();
20 Environment.from(Environment other) 20 Environment.from(Environment other)
21 : lives = new Set<HInstruction>.from(other.lives), 21 : lives = new Set<HInstruction>.from(other.lives),
22 loopMarkers = new Set<HBasicBlock>.from(other.loopMarkers); 22 loopMarkers = new Set<HBasicBlock>.from(other.loopMarkers);
23 23
24 void remove(HInstruction instruction) { 24 void remove(HInstruction instruction) {
25 lives.remove(instruction); 25 lives.remove(instruction);
26 } 26 }
27 27
28 void add(HInstruction instruction) { 28 void add(HInstruction instruction) {
29 // If the instruction is a type guard, we add its checked input 29 if (!instruction.isCodeMotionInvariant()) {
30 // instead. This allows sharing the same environment between
31 // different type guards.
32 //
33 // Also, we don't need to add code motion invariant instructions
34 // in the live set (because we generate them at use-site), except
35 // for parameters that are not 'this', which is always passed as
36 // the receiver.
37 if (instruction is HTypeGuard) {
38 add(instruction.checkedInput);
39 } else if (!instruction.isCodeMotionInvariant()
40 || (instruction is HParameterValue && instruction is !HThis)) {
41 lives.add(instruction); 30 lives.add(instruction);
42 } else { 31 } else {
43 for (int i = 0, len = instruction.inputs.length; i < len; i++) { 32 for (int i = 0, len = instruction.inputs.length; i < len; i++) {
44 add(instruction.inputs[i]); 33 add(instruction.inputs[i]);
45 } 34 }
46 } 35 }
47 } 36 }
48 37
49 void addLoopMarker(HBasicBlock block) { 38 void addLoopMarker(HBasicBlock block) {
50 loopMarkers.add(block); 39 loopMarkers.add(block);
51 } 40 }
52 41
53 void removeLoopMarker(HBasicBlock block) { 42 void removeLoopMarker(HBasicBlock block) {
54 loopMarkers.remove(block); 43 loopMarkers.remove(block);
55 } 44 }
56 45
57 void addAll(Environment other) { 46 void addAll(Environment other) {
58 lives.addAll(other.lives); 47 lives.addAll(other.lives);
59 loopMarkers.addAll(other.loopMarkers); 48 loopMarkers.addAll(other.loopMarkers);
60 } 49 }
61 50
51 /**
52 * Stores all live variables in the guard. The guarded instruction will be the
53 * last input in the guard's input list.
54 */
55 void storeInGuard(HTypeGuard guard) {
56 HInstruction guarded = guard.guarded;
57 List<HInstruction> inputs = guard.inputs;
58 assert(inputs.length == 1);
59 inputs.clear();
60 // Remove the guarded from the environment, so that we are sure it is last
61 // when we add it again.
62 remove(guarded);
63 inputs.addAll(lives);
64 inputs.addLast(guarded);
65 add(guarded);
66 for (int i = 0; i < inputs.length - 1; i++) {
67 HInstruction input = inputs[i];
68 input.usedBy.add(guard);
69 }
70 }
71
62 bool isEmpty() => lives.isEmpty() && loopMarkers.isEmpty(); 72 bool isEmpty() => lives.isEmpty() && loopMarkers.isEmpty();
63 } 73 }
64 74
65 75
66 /** 76 /**
67 * Visits the graph in dominator order and inserts TypeGuards in places where 77 * Visits the graph in dominator order and inserts TypeGuards in places where
68 * we consider the guard to be of value. 78 * we consider the guard to be of value.
69 * 79 *
70 * Might modify the [:propagatedType:] fields of the instructions in an 80 * Might modify the [:propagatedType:] fields of the instructions in an
71 * inconsistent way. No further analysis should rely on them. 81 * inconsistent way. No further analysis should rely on them.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 if (speculativeType == computedType) return false; 177 if (speculativeType == computedType) return false;
168 // If a bailout check is more expensive than doing the actual operation 178 // If a bailout check is more expensive than doing the actual operation
169 // don't do it either. 179 // don't do it either.
170 return typeGuardWouldBeValuable(instruction, speculativeType); 180 return typeGuardWouldBeValuable(instruction, speculativeType);
171 } 181 }
172 182
173 void visitInstruction(HInstruction instruction) { 183 void visitInstruction(HInstruction instruction) {
174 HType speculativeType = instruction.propagatedType; 184 HType speculativeType = instruction.propagatedType;
175 if (shouldInsertTypeGuard(instruction)) { 185 if (shouldInsertTypeGuard(instruction)) {
176 List<HInstruction> inputs = <HInstruction>[instruction]; 186 List<HInstruction> inputs = <HInstruction>[instruction];
177 HInstruction insertionPoint; 187 HTypeGuard guard = new HTypeGuard(speculativeType, stateId++, inputs);
178 if (instruction is HPhi) {
179 insertionPoint = instruction.block.first;
180 } else if (instruction is HParameterValue) {
181 // We insert the type guard at the end of the entry block
182 // because if a parameter is live, it must be kept in the live
183 // environment. Not doing so would mean we could visit a
184 // parameter and remove it from the environment before
185 // visiting a type guard.
186 insertionPoint = instruction.block.last;
187 } else {
188 insertionPoint = instruction.next;
189 }
190 // If the previous instruction is also a type guard, then both
191 // guards have the same environment, and can therefore share the
192 // same state id.
193 int state;
194 if (insertionPoint.previous is HTypeGuard) {
195 HTypeGuard other = insertionPoint.previous;
196 state = other.state;
197 } else {
198 state = stateId++;
199 }
200 HTypeGuard guard = new HTypeGuard(speculativeType, state, inputs);
201 guard.propagatedType = speculativeType; 188 guard.propagatedType = speculativeType;
202 work.guards.add(guard); 189 work.guards.add(guard);
203 instruction.block.rewrite(instruction, guard); 190 instruction.block.rewrite(instruction, guard);
191 HInstruction insertionPoint = (instruction is HPhi)
192 ? instruction.block.first
193 : instruction.next;
204 insertionPoint.block.addBefore(insertionPoint, guard); 194 insertionPoint.block.addBefore(insertionPoint, guard);
205 } 195 }
206 } 196 }
207 } 197 }
208 198
209 /** 199 /**
210 * Computes the environment for each SSA instruction: visits the graph 200 * Computes the environment for each SSA instruction: visits the graph
211 * in post-dominator order. Removes an instruction from the environment 201 * in post-dominator order. Removes an instruction from the environment
212 * and adds its inputs to the environment at the instruction's 202 * and adds its inputs to the environment at the instruction's
213 * definition. 203 * definition.
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 } 303 }
314 304
315 void visitInstruction(HInstruction instruction) { 305 void visitInstruction(HInstruction instruction) {
316 environment.remove(instruction); 306 environment.remove(instruction);
317 for (int i = 0, len = instruction.inputs.length; i < len; i++) { 307 for (int i = 0, len = instruction.inputs.length; i < len; i++) {
318 environment.add(instruction.inputs[i]); 308 environment.add(instruction.inputs[i]);
319 } 309 }
320 } 310 }
321 311
322 void insertCapturedEnvironments() { 312 void insertCapturedEnvironments() {
323 Map<int, HTypeGuard> seenGuardStates = new Map<int, HTypeGuard>();
324 capturedEnvironments.forEach((HTypeGuard guard, Environment env) { 313 capturedEnvironments.forEach((HTypeGuard guard, Environment env) {
325 storeInGuard(guard, env.lives, seenGuardStates); 314 env.storeInGuard(guard);
326 }); 315 });
327 } 316 }
328
329 /**
330 * Stores all live variables in the guard.
331 */
332 void storeInGuard(HTypeGuard guard,
333 Set<HInstruction> lives,
334 Map<int, HTypeGuard> seenGuardStates) {
335 HInstruction guarded = guard.guarded;
336 List<HInstruction> inputs = guard.inputs;
337 assert(inputs.length == 1);
338 inputs.clear();
339 HTypeGuard other = seenGuardStates[guard.state];
340 if (other !== null) {
341 // The guards are sharing the same state. Also share the same
342 // environment, in the same order.
343 inputs.addAll(other.inputs);
344 assert(inputs.length == lives.length);
345 } else {
346 seenGuardStates[guard.state] = guard;
347 inputs.addAll(lives);
348 }
349
350 for (int i = 0; i < inputs.length; i++) {
351 HInstruction input = inputs[i];
352 if (input == guarded) {
353 guard.checkedInputIndex = i;
354 // No need to update [input.usedBy], the guard is already
355 // there.
356 } else {
357 input.usedBy.add(guard);
358 }
359 }
360 }
361 } 317 }
362 318
363 /** 319 /**
364 * Propagates bailout information to blocks that need it. This visitor 320 * Propagates bailout information to blocks that need it. This visitor
365 * is run before codegen, to know which blocks have to deal with 321 * is run before codegen, to know which blocks have to deal with
366 * bailouts. 322 * bailouts.
367 */ 323 */
368 class SsaBailoutPropagator extends HBaseVisitor { 324 class SsaBailoutPropagator extends HBaseVisitor {
369 final Compiler compiler; 325 final Compiler compiler;
370 final List<HBasicBlock> blocks; 326 final List<HBasicBlock> blocks;
371 final List<HLabeledBlockInformation> labeledBlockInformations; 327 final List<HLabeledBlockInformation> labeledBlockInformations;
372 final Set<HInstruction> generateAtUseSite;
373 SubGraph subGraph; 328 SubGraph subGraph;
374 329
375 /** 330 SsaBailoutPropagator(Compiler this.compiler)
376 * If set to true, the graph has either multiple bailouts in
377 * different places, or a bailout inside an if or a loop. For such a
378 * graph, the code generator will emit a generic switch.
379 */
380 bool hasComplexTypeGuards = false;
381
382 /**
383 * The first type guard in the graph.
384 */
385 HTypeGuard firstTypeGuard;
386
387 /**
388 * If set, it is the first block in the graph where we generate
389 * code. Blocks before this one are dead code in the bailout
390 * version.
391 */
392
393 SsaBailoutPropagator(this.compiler, this.generateAtUseSite)
394 : blocks = <HBasicBlock>[], 331 : blocks = <HBasicBlock>[],
395 labeledBlockInformations = <HLabeledBlockInformation>[]; 332 labeledBlockInformations = <HLabeledBlockInformation>[];
396 333
397 void visitGraph(HGraph graph) { 334 void visitGraph(HGraph graph) {
398 subGraph = new SubGraph(graph.entry, graph.exit); 335 subGraph = new SubGraph(graph.entry, graph.exit);
336 blocks.addLast(graph.entry);
399 visitBasicBlock(graph.entry); 337 visitBasicBlock(graph.entry);
338 blocks.removeLast();
400 if (!blocks.isEmpty()) { 339 if (!blocks.isEmpty()) {
401 compiler.internalError('Bailout propagation', 340 compiler.internalError('Bailout propagation',
402 node: compiler.currentElement.parseNode(compiler)); 341 node: compiler.currentElement.parseNode(compiler));
403 } 342 }
404 } 343 }
405 344
406 void visitBasicBlock(HBasicBlock block) { 345 void visitBasicBlock(HBasicBlock block) {
407 // Abort traversal if we are leaving the currently active sub-graph. 346 // Abort traversal if we are leaving the currently active sub-graph.
408 if (!subGraph.contains(block)) return; 347 if (!subGraph.contains(block)) return;
409 348
410 if (block.isLoopHeader()) { 349 if (block.isLoopHeader()) {
411 blocks.addLast(block); 350 blocks.addLast(block);
412 } else if (block.isLabeledBlock() 351 } else if (block.isLabeledBlock() && blocks.last() !== block) {
413 && (blocks.isEmpty() || blocks.last() !== block)) {
414 HLabeledBlockInformation info = block.blockFlow.body; 352 HLabeledBlockInformation info = block.blockFlow.body;
415 visitStatements(info.body); 353 visitStatements(info.body);
416 return; 354 return;
417 } 355 }
418 356
419 HInstruction instruction = block.first; 357 HInstruction instruction = block.first;
420 while (instruction != null) { 358 while (instruction != null) {
421 instruction.accept(this); 359 instruction.accept(this);
422 instruction = instruction.next; 360 instruction = instruction.next;
423 } 361 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 visitBasicBlock(branchBlock.successors[1]); 439 visitBasicBlock(branchBlock.successors[1]);
502 // With labeled breaks we can have more dominated blocks. 440 // With labeled breaks we can have more dominated blocks.
503 if (dominated.length >= 3) { 441 if (dominated.length >= 3) {
504 for (int i = 2; i < dominated.length; i++) { 442 for (int i = 2; i < dominated.length; i++) {
505 visitBasicBlock(dominated[i]); 443 visitBasicBlock(dominated[i]);
506 } 444 }
507 } 445 }
508 } 446 }
509 447
510 visitTypeGuard(HTypeGuard guard) { 448 visitTypeGuard(HTypeGuard guard) {
511 if (blocks.isEmpty()) { 449 blocks.forEach((HBasicBlock block) {
512 if (firstTypeGuard === null || firstTypeGuard.state === guard.state) { 450 block.guards.add(guard);
513 firstTypeGuard = guard; 451 });
514 } else {
515 hasComplexTypeGuards = true;
516 }
517 } else {
518 hasComplexTypeGuards = true;
519 blocks.forEach((HBasicBlock block) {
520 block.guards.add(guard);
521 });
522 }
523 } 452 }
524 } 453 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698