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

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

Issue 10539106: Simplify generated code for trivial bailout methods. (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
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 (!instruction.isCodeMotionInvariant()) { 29 // We don't need to an code motion invariant instructions in the
kasperl 2012/06/12 12:18:40 need to an code?
ngeoffray 2012/06/12 12:28:18 Done.
30 // live set except for parameters that are not 'this' ('this' is
kasperl 2012/06/12 12:18:40 ('this' is -> , which is
ngeoffray 2012/06/12 12:28:18 Done.
31 // always passed as the receiver).
32 if (!instruction.isCodeMotionInvariant()
floitsch 2012/06/12 15:01:17 Explain that this is, because we generate these at
33 || (instruction is HParameterValue && instruction is !HThis)) {
30 lives.add(instruction); 34 lives.add(instruction);
31 } else { 35 } else {
32 for (int i = 0, len = instruction.inputs.length; i < len; i++) { 36 for (int i = 0, len = instruction.inputs.length; i < len; i++) {
33 add(instruction.inputs[i]); 37 add(instruction.inputs[i]);
34 } 38 }
35 } 39 }
36 } 40 }
37 41
38 void addLoopMarker(HBasicBlock block) { 42 void addLoopMarker(HBasicBlock block) {
39 loopMarkers.add(block); 43 loopMarkers.add(block);
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 if (speculativeType == computedType) return false; 196 if (speculativeType == computedType) return false;
193 // If a bailout check is more expensive than doing the actual operation 197 // If a bailout check is more expensive than doing the actual operation
194 // don't do it either. 198 // don't do it either.
195 return typeGuardWouldBeValuable(instruction, speculativeType); 199 return typeGuardWouldBeValuable(instruction, speculativeType);
196 } 200 }
197 201
198 void visitInstruction(HInstruction instruction) { 202 void visitInstruction(HInstruction instruction) {
199 HType speculativeType = instruction.propagatedType; 203 HType speculativeType = instruction.propagatedType;
200 if (shouldInsertTypeGuard(instruction)) { 204 if (shouldInsertTypeGuard(instruction)) {
201 List<HInstruction> inputs = <HInstruction>[instruction]; 205 List<HInstruction> inputs = <HInstruction>[instruction];
202 HTypeGuard guard = new HTypeGuard(speculativeType, stateId++, inputs); 206 HInstruction insertionPoint;
207 if (instruction is HPhi) {
208 insertionPoint = instruction.block.first;
209 } else if (instruction is HParameterValue) {
210 // We insert the type guard at the end of the entry block
211 // because if a parameter is live, it must be kept in the live
212 // environment. Not doing so would mean we could visit a
213 // parameter and remove it from the environment before
214 // visiting a type guard.
215 insertionPoint = instruction.block.last;
216 } else {
217 insertionPoint = instruction.next;
218 }
219 int state;
kasperl 2012/06/12 12:18:40 I would move 'int state' down below the comment.
ngeoffray 2012/06/12 12:28:18 Done.
220 // If the previous instruction is also a type guard, then both
221 // guards have the same environment, and can therefore share the
222 // same state id.
223 if (insertionPoint.previous is HTypeGuard) {
224 HTypeGuard other = insertionPoint.previous;
225 state = other.state;
226 } else {
227 state = stateId++;
228 }
229 HTypeGuard guard = new HTypeGuard(speculativeType, state, inputs);
203 guard.propagatedType = speculativeType; 230 guard.propagatedType = speculativeType;
204 work.guards.add(guard); 231 work.guards.add(guard);
205 instruction.block.rewrite(instruction, guard); 232 instruction.block.rewrite(instruction, guard);
206 HInstruction insertionPoint = (instruction is HPhi)
207 ? instruction.block.first
208 : instruction.next;
209 insertionPoint.block.addBefore(insertionPoint, guard); 233 insertionPoint.block.addBefore(insertionPoint, guard);
210 } 234 }
211 } 235 }
212 } 236 }
213 237
214 /** 238 /**
215 * Computes the environment for each SSA instruction: visits the graph 239 * Computes the environment for each SSA instruction: visits the graph
216 * in post-dominator order. Removes an instruction from the environment 240 * in post-dominator order. Removes an instruction from the environment
217 * and adds its inputs to the environment at the instruction's 241 * and adds its inputs to the environment at the instruction's
218 * definition. 242 * definition.
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 357
334 /** 358 /**
335 * Propagates bailout information to blocks that need it. This visitor 359 * Propagates bailout information to blocks that need it. This visitor
336 * is run before codegen, to know which blocks have to deal with 360 * is run before codegen, to know which blocks have to deal with
337 * bailouts. 361 * bailouts.
338 */ 362 */
339 class SsaBailoutPropagator extends HBaseVisitor { 363 class SsaBailoutPropagator extends HBaseVisitor {
340 final Compiler compiler; 364 final Compiler compiler;
341 final List<HBasicBlock> blocks; 365 final List<HBasicBlock> blocks;
342 final List<HLabeledBlockInformation> labeledBlockInformations; 366 final List<HLabeledBlockInformation> labeledBlockInformations;
367 final Set<HInstruction> generateAtUseSite;
368 final VariableNames variableNames;
343 SubGraph subGraph; 369 SubGraph subGraph;
344 370
345 SsaBailoutPropagator(Compiler this.compiler) 371 /**
372 * If set to true, the graph has either multiple bailouts in
373 * different places, or a bailout inside an if or a loop. For such a
374 * graph, the code generator will emit a generic switch.
375 */
376 bool hasComplexTypeGuards = false;
377
378 /**
379 * The first type guard in the graph.
380 */
381 HTypeGuard firstTypeGuard;
382
383 /**
384 * If set, it is the first block in the graph where we generate
385 * code. Blocks before this one are dead code in the bailout
386 * version.
387 */
388 HBasicBlock startGeneratingAt;
389
kasperl 2012/06/12 12:18:40 Remove one newline here.
ngeoffray 2012/06/12 12:28:18 Done.
390
391 SsaBailoutPropagator(this.compiler,
392 this.generateAtUseSite,
393 this.variableNames)
346 : blocks = <HBasicBlock>[], 394 : blocks = <HBasicBlock>[],
347 labeledBlockInformations = <HLabeledBlockInformation>[]; 395 labeledBlockInformations = <HLabeledBlockInformation>[];
348 396
349 void visitGraph(HGraph graph) { 397 void visitGraph(HGraph graph) {
350 subGraph = new SubGraph(graph.entry, graph.exit); 398 subGraph = new SubGraph(graph.entry, graph.exit);
351 blocks.addLast(graph.entry);
352 visitBasicBlock(graph.entry); 399 visitBasicBlock(graph.entry);
353 blocks.removeLast();
354 if (!blocks.isEmpty()) { 400 if (!blocks.isEmpty()) {
355 compiler.internalError('Bailout propagation', 401 compiler.internalError('Bailout propagation',
356 node: compiler.currentElement.parseNode(compiler)); 402 node: compiler.currentElement.parseNode(compiler));
357 } 403 }
358 } 404 }
359 405
360 void visitBasicBlock(HBasicBlock block) { 406 void visitBasicBlock(HBasicBlock block) {
361 // Abort traversal if we are leaving the currently active sub-graph. 407 // Abort traversal if we are leaving the currently active sub-graph.
362 if (!subGraph.contains(block)) return; 408 if (!subGraph.contains(block)) return;
363 409
364 if (block.isLoopHeader()) { 410 if (block.isLoopHeader()) {
365 blocks.addLast(block); 411 blocks.addLast(block);
366 } else if (block.isLabeledBlock() && blocks.last() !== block) { 412 } else if (block.isLabeledBlock()
413 && (blocks.isEmpty() || blocks.last() !== block)) {
367 HLabeledBlockInformation info = block.blockFlow.body; 414 HLabeledBlockInformation info = block.blockFlow.body;
368 visitStatements(info.body); 415 visitStatements(info.body);
369 return; 416 return;
370 } 417 }
371 418
372 HInstruction instruction = block.first; 419 HInstruction instruction = block.first;
373 while (instruction != null) { 420 while (instruction != null) {
374 instruction.accept(this); 421 instruction.accept(this);
375 instruction = instruction.next; 422 instruction = instruction.next;
376 } 423 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 500
454 visitBasicBlock(branchBlock.successors[1]); 501 visitBasicBlock(branchBlock.successors[1]);
455 // With labeled breaks we can have more dominated blocks. 502 // With labeled breaks we can have more dominated blocks.
456 if (dominated.length >= 3) { 503 if (dominated.length >= 3) {
457 for (int i = 2; i < dominated.length; i++) { 504 for (int i = 2; i < dominated.length; i++) {
458 visitBasicBlock(dominated[i]); 505 visitBasicBlock(dominated[i]);
459 } 506 }
460 } 507 }
461 } 508 }
462 509
510 // If argument is a [HCheck] and it does not have a name, we try to
511 // find the name of its checked input. Note that there must be a
512 // name, otherwise the instruction would not be in the live
513 // environment.
514 HInstruction unwrap(argument) {
515 while (argument is HCheck && !variableNames.hasName(argument)) {
516 argument = argument.checkedInput;
517 }
518 assert(variableNames.hasName(argument));
519 return argument;
520 }
521
463 visitTypeGuard(HTypeGuard guard) { 522 visitTypeGuard(HTypeGuard guard) {
464 blocks.forEach((HBasicBlock block) { 523 // Sort the names of all type guards, to be able to merge
kasperl 2012/06/12 12:18:40 to be able to -> so we can
ngeoffray 2012/06/12 12:28:18 Done.
465 block.guards.add(guard); 524 // guards that have the same state id.
466 }); 525 List<String> names = <String>[];
526 for (HInstruction input in guard.inputs) {
527 HInstruction instruction = unwrap(input);
528 names.add(variableNames.getName(instruction));
529 }
530 names.sort((a, b) => a.compareTo(b));
531 guard.sortedVariableNames = names;
532
533 if (firstTypeGuard === null || firstTypeGuard.state === guard.state) {
534 firstTypeGuard = guard;
535 if (!blocks.isEmpty()) {
536 hasComplexTypeGuards = true;
537 // We start generating at the first block that has control
538 // flow.
539 startGeneratingAt = blocks[0];
540 blocks.forEach((HBasicBlock block) {
541 block.guards.add(guard);
542 });
543 }
544 } else {
545 hasComplexTypeGuards = true;
546 blocks.forEach((HBasicBlock block) {
547 block.guards.add(guard);
548 });
549 }
467 } 550 }
468 } 551 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/codegen.dart » ('j') | lib/compiler/implementation/ssa/codegen.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698