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

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

Issue 9863037: Generate prettier loops. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Adressed review comments. A few fixes. Created 8 years, 8 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 SsaCodeGeneratorTask extends CompilerTask { 5 class SsaCodeGeneratorTask extends CompilerTask {
6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler);
7 String get name() => 'SSA code generator'; 7 String get name() => 'SSA code generator';
8 8
9 9
10 String generateMethod(WorkItem work, HGraph graph) { 10 String generateMethod(WorkItem work, HGraph graph) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 ? element.name.slowToString() 54 ? element.name.slowToString()
55 : JsNames.getValid('${element.name.slowToString()}'); 55 : JsNames.getValid('${element.name.slowToString()}');
56 }); 56 });
57 return parameterNames; 57 return parameterNames;
58 } 58 }
59 } 59 }
60 60
61 typedef void ElementAction(Element element); 61 typedef void ElementAction(Element element);
62 62
63 class SsaCodeGenerator implements HVisitor { 63 class SsaCodeGenerator implements HVisitor {
64 /**
65 * Current state for generating simple (non-local-control) code.
66 * It is generated as either statements (indented and ';'-terminated),
67 * expressions (comma separated) or declarations (also comma separated,
68 * but expected to be preceeded by a 'var' so it declares its variables);
69 */
70 static final int STATE_STATEMENT = 0;
71 static final int STATE_FIRST_EXPRESSION = 1;
72 static final int STATE_FIRST_DECLARATION = 2;
73 static final int STATE_EXPRESSION = 3;
74 static final int STATE_DECLARATION = 4;
75
64 final Compiler compiler; 76 final Compiler compiler;
65 final WorkItem work; 77 final WorkItem work;
66 final StringBuffer buffer; 78 final StringBuffer buffer;
67 final String parameters; 79 final String parameters;
68 80
69 final Map<Element, String> parameterNames; 81 final Map<Element, String> parameterNames;
70 final Map<int, String> names; 82 final Map<int, String> names;
71 final Map<String, int> prefixes; 83 final Map<String, int> prefixes;
72 final Set<HInstruction> generateAtUseSite; 84 final Set<HInstruction> generateAtUseSite;
73 final Map<HPhi, String> logicalOperations; 85 final Map<HPhi, String> logicalOperations;
74 final Map<Element, ElementAction> breakAction; 86 final Map<Element, ElementAction> breakAction;
75 final Map<Element, ElementAction> continueAction; 87 final Map<Element, ElementAction> continueAction;
76 88
77 Element equalsNullElement; 89 Element equalsNullElement;
78 int indent = 0; 90 int indent = 0;
79 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; 91 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE;
80 HGraph currentGraph; 92 HGraph currentGraph;
93 /**
94 * Whether the code-generation should try to generate an expression
95 * instead of a sequence of statements.
96 */
97 int generationState = STATE_STATEMENT;
98 /**
99 * While generating expressions, we can't insert variable declarations.
100 * Instead we declare them at the end of the function
101 */
102 Link<String> delayedVarDecl = const EmptyLink<String>();
81 HBasicBlock currentBlock; 103 HBasicBlock currentBlock;
82 104
83 // Records a block-information that is being handled specially. 105 // Records a block-information that is being handled specially.
84 // Used to break bad recursion. 106 // Used to break bad recursion.
85 HLabeledBlockInformation currentBlockInformation; 107 HBlockInformation currentBlockInformation;
86 // The subgraph is used to delimit traversal for some constructions, e.g., 108 // The subgraph is used to delimit traversal for some constructions, e.g.,
87 // if branches. 109 // if branches.
88 SubGraph subGraph; 110 SubGraph subGraph;
89 111
90 LibraryElement get currentLibrary() => work.element.getLibrary(); 112 LibraryElement get currentLibrary() => work.element.getLibrary();
91 113
92 bool isGenerateAtUseSite(HInstruction instruction) { 114 bool isGenerateAtUseSite(HInstruction instruction) {
93 return generateAtUseSite.contains(instruction); 115 return generateAtUseSite.contains(instruction);
94 } 116 }
95 117
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 logicalOperations).visitGraph(graph); 169 logicalOperations).visitGraph(graph);
148 } 170 }
149 171
150 visitGraph(HGraph graph) { 172 visitGraph(HGraph graph) {
151 preGenerateMethod(graph); 173 preGenerateMethod(graph);
152 currentGraph = graph; 174 currentGraph = graph;
153 indent++; // We are already inside a function. 175 indent++; // We are already inside a function.
154 subGraph = new SubGraph(graph.entry, graph.exit); 176 subGraph = new SubGraph(graph.entry, graph.exit);
155 beginGraph(graph); 177 beginGraph(graph);
156 visitBasicBlock(graph.entry); 178 visitBasicBlock(graph.entry);
179 if (!delayedVarDecl.isEmpty()) {
180 addIndentation();
181 buffer.add("var ");
182 while (true) {
183 buffer.add(delayedVarDecl.head);
184 delayedVarDecl = delayedVarDecl.tail;
185 if (delayedVarDecl.isEmpty()) break;
186 buffer.add(", ");
187 }
188 buffer.add(";\n");
189 }
157 endGraph(graph); 190 endGraph(graph);
158 } 191 }
159 192
160 void visitSubGraph(SubGraph newSubGraph) { 193 void visitSubGraph(SubGraph newSubGraph) {
161 SubGraph oldSubGraph = subGraph; 194 SubGraph oldSubGraph = subGraph;
162 subGraph = newSubGraph; 195 subGraph = newSubGraph;
163 visitBasicBlock(subGraph.start); 196 visitBasicBlock(subGraph.start);
164 subGraph = oldSubGraph; 197 subGraph = oldSubGraph;
165 } 198 }
166 199
200 bool isExpression(SubGraph limits) {
201 HBasicBlock basicBlock = limits.start;
202 do {
203 HInstruction current = basicBlock.first;
204 while (current != basicBlock.last) {
205 // E.g, type guards.
206 if (current.isControlFlow()) {
207 return false;
208 }
209 current = current.next;
210 }
211 if (current is HGoto) {
212 basicBlock = basicBlock.successors[0];
213 } else if (current is HConditionalBranch) {
214 if (generateAtUseSite.contains(current)) {
215 // Short-circuit logical operator trickery.
216 // Check the second half, which will continue into the join.
217 basicBlock = basicBlock.successors[0];
218 } else {
219 // We allow an expression to end on an HIf (a condition expression).
220 return basicBlock === limits.end;
221 }
222 } else {
223 // Expression-incompatible control flow.
224 return false;
225 }
226 } while (limits.contains(basicBlock));
227 return true;
228 }
229
230 bool isCondition(SubGraph limits) {
231 return isExpression(limits) && (limits.end.last is HConditionalBranch);
232 }
233
234 void visitExpressionGraph(SubGraph subGraph) {
235 int oldState = generationState;
236 generationState = STATE_FIRST_EXPRESSION;
237 visitSubGraph(subGraph);
238 generationState = oldState;
239 }
240
241 void visitConditionGraph(SubGraph subGraph) {
242 visitExpressionGraph(subGraph);
243 }
244
167 String temporary(HInstruction instruction) { 245 String temporary(HInstruction instruction) {
168 int id = instruction.id; 246 int id = instruction.id;
169 String name = names[id]; 247 String name = names[id];
170 if (name !== null) return name; 248 if (name !== null) return name;
171 249
172 if (instruction is HPhi) { 250 if (instruction is HPhi) {
173 HPhi phi = instruction; 251 HPhi phi = instruction;
174 Element element = phi.element; 252 Element element = phi.element;
175 if (element != null && element.kind == ElementKind.PARAMETER) { 253 if (element != null && element.kind == ElementKind.PARAMETER) {
176 name = parameterNames[element]; 254 name = parameterNames[element];
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 void visitArguments(List<HInstruction> inputs) { 291 void visitArguments(List<HInstruction> inputs) {
214 assert(inputs.length >= HInvoke.ARGUMENTS_OFFSET); 292 assert(inputs.length >= HInvoke.ARGUMENTS_OFFSET);
215 buffer.add('('); 293 buffer.add('(');
216 for (int i = HInvoke.ARGUMENTS_OFFSET; i < inputs.length; i++) { 294 for (int i = HInvoke.ARGUMENTS_OFFSET; i < inputs.length; i++) {
217 if (i != HInvoke.ARGUMENTS_OFFSET) buffer.add(', '); 295 if (i != HInvoke.ARGUMENTS_OFFSET) buffer.add(', ');
218 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); 296 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE);
219 } 297 }
220 buffer.add(')'); 298 buffer.add(')');
221 } 299 }
222 300
301
302
303 /**
304 * Whether we are currently generating expressions instead of statements.
305 * This includes declarations, which are generated as expressions.
306 */
307 bool isGeneratingExpression() {
308 return generationState != STATE_STATEMENT;
309 }
310
311 /**
312 * Whether we are generating a declaration.
313 */
314 bool isGeneratingDeclaration() {
315 return (generationState == STATE_DECLARATION ||
316 generationState == STATE_FIRST_DECLARATION);
317 }
318
319 /**
320 * Called before writing an expression.
321 * Ensures that expressions are comma spearated.
322 */
323 void addExpressionSeparator() {
324 if (generationState == STATE_FIRST_DECLARATION) {
325 generationState = STATE_DECLARATION;
326 } else if (generationState == STATE_FIRST_EXPRESSION) {
327 generationState = STATE_EXPRESSION;
328 } else {
329 buffer.add(", ");
330 }
331 }
332
333 void declareVariable(String variableName) {
334 if (isGeneratingExpression()) {
335 buffer.add(variableName);
336 if (!isGeneratingDeclaration()) {
337 delayedVarDecl = delayedVarDecl.prepend(variableName);
338 }
339 } else {
340 buffer.add("var ");
341 buffer.add(variableName);
342 }
343 }
344
223 void define(HInstruction instruction) { 345 void define(HInstruction instruction) {
224 buffer.add('var ${temporary(instruction)} = '); 346 String name = temporary(instruction);
347 declareVariable(name);
348 buffer.add(" = ");
225 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); 349 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE);
226 } 350 }
227 351
228 void use(HInstruction argument, int expectedPrecedence) { 352 void use(HInstruction argument, int expectedPrecedence) {
229 if (isGenerateAtUseSite(argument)) { 353 if (isGenerateAtUseSite(argument)) {
230 visit(argument, expectedPrecedence); 354 visit(argument, expectedPrecedence);
231 } else if (argument is HIntegerCheck) { 355 } else if (argument is HIntegerCheck) {
232 HIntegerCheck instruction = argument; 356 HIntegerCheck instruction = argument;
233 use(instruction.value, expectedPrecedence); 357 use(instruction.value, expectedPrecedence);
234 } else if (argument is HBoundsCheck) { 358 } else if (argument is HBoundsCheck) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 void emitLogicalOperation(HPhi node, String operation) { 460 void emitLogicalOperation(HPhi node, String operation) {
337 JSBinaryOperatorPrecedence operatorPrecedence = 461 JSBinaryOperatorPrecedence operatorPrecedence =
338 JSPrecedence.binary[operation]; 462 JSPrecedence.binary[operation];
339 beginExpression(operatorPrecedence.precedence); 463 beginExpression(operatorPrecedence.precedence);
340 use(node.inputs[0], operatorPrecedence.left); 464 use(node.inputs[0], operatorPrecedence.left);
341 buffer.add(" $operation "); 465 buffer.add(" $operation ");
342 use(node.inputs[1], operatorPrecedence.right); 466 use(node.inputs[1], operatorPrecedence.right);
343 endExpression(operatorPrecedence.precedence); 467 endExpression(operatorPrecedence.precedence);
344 } 468 }
345 469
346 visitBasicBlock(HBasicBlock node) { 470 // Wraps a loop body in a block to make continues have a target to break
471 // to (if necessary).
472 void wrapLoopBodyForContinue(HLoopInformation info) {
473 TargetElement target = info.target;
474 if (target !== null && target.isContinueTarget) {
475 addIndentation();
476 for (LabelElement label in info.labels) {
477 if (label.isContinueTarget) {
478 writeContinueLabel(label);
479 buffer.add(":");
480 continueAction[label] = continueAsBreak;
481 }
482 }
483 addImplicitContinueLabel();
484 buffer.add(":{\n");
485 continueAction[info.target] = implicitContinueAsBreak;
486 indent++;
487 visitSubGraph(info.body);
488 indent--;
489 addIndentation();
490 buffer.add("}\n");
491 continueAction.remove(info.target);
492 for (LabelElement label in info.labels) {
493 if (label.isContinueTarget) {
494 continueAction.remove(label);
495 }
496 }
497 } else {
498 // Loop body contains no continues, so we don't need a break target.
499 visitSubGraph(info.body);
500 }
501 }
502
503 bool handleLoop(HBasicBlock node) {
504 bool success = false;
505 assert(node.isLoopHeader());
506 HLoopInformation info = node.loopInformation;
507 SubExpression condition = info.condition;
508 if (isCondition(condition)) {
509 switch (info.type) {
510 case HLoopInformation.WHILE_LOOP:
511 case HLoopInformation.FOR_IN_LOOP: {
512 addIndentation();
513 for (LabelElement label in info.labels) {
514 writeLabel(label);
515 buffer.add(":");
516 }
517 bool inlineUpdates =
518 info.updates !== null && isExpression(info.updates);
519 if (inlineUpdates) {
520 buffer.add("for (; ");
521 visitConditionGraph(condition);
522 buffer.add("; ");
523 visitExpressionGraph(info.updates);
524 buffer.add(") {\n");
525 indent++;
526 // The body might be labeled. Ignore this when recursing on the
527 // subgraph.
528 // TODO(lrn): Remove this extra labeling when handling all loops
529 // using subgraphs.
530 HBlockInformation oldInfo = currentBlockInformation;
531 currentBlockInformation = info.body.start.labeledBlockInformation;
532 visitSubGraph(info.body);
533 currentBlockInformation = oldInfo;
534
535 indent--;
536 } else {
537 buffer.add("while (");
538 visitConditionGraph(condition);
539 buffer.add(") {\n");
540 indent++;
541 wrapLoopBodyForContinue(info);
542 if (info.updates !== null) visitSubGraph(info.updates);
543 indent--;
544 }
545 addIndentation();
546 buffer.add("}\n");
547 success = true;
548 break;
549 }
550 case HLoopInformation.FOR_LOOP: {
551 // TODO(lrn): Find a way to put initialization into the for.
552 // It's currently handled before we reach the [HLoopInformation].
553 addIndentation();
554 for (LabelElement label in info.labels) {
555 if (label.isTarget) {
556 writeLabel(label);
557 buffer.add(":");
558 }
559 }
560 buffer.add("for(;");
561 visitConditionGraph(info.condition);
562 buffer.add(";");
563 if (isExpression(info.updates)) {
564 visitExpressionGraph(info.updates);
565 buffer.add(") {\n");
566 indent++;
567
568 HBlockInformation oldInfo = currentBlockInformation;
569 currentBlockInformation = info.body.start.labeledBlockInformation;
570 visitSubGraph(info.body);
571 currentBlockInformation = oldInfo;
572
573 indent--;
574 addIndentation();
575 buffer.add("}\n");
576 } else {
577 buffer.add(") {\n");
578 indent++;
579 wrapLoopBodyForContinue(info);
580 visitSubGraph(info.updates);
581 indent--;
582 buffer.add("}\n");
583 }
584 success = true;
585 break;
586 }
587 case HLoopInformation.DO_WHILE_LOOP:
588 // Currently unhandled.
589 default:
590 }
591 }
592 return success;
593 }
594
595 void visitBasicBlock(HBasicBlock node) {
347 // Abort traversal if we are leaving the currently active sub-graph. 596 // Abort traversal if we are leaving the currently active sub-graph.
348 if (!subGraph.contains(node)) return; 597 if (!subGraph.contains(node)) return;
349 598
350 // If this node has special behavior attached, handle it. 599 // If this node has special behavior attached, handle it.
351 // If we reach here again while handling the attached information, 600 // If we reach here again while handling the attached information,
352 // e.g., because we call visitSubGraph on a subgraph starting here, 601 // e.g., because we call visitSubGraph on a subgraph starting here,
353 // don't handle it again. 602 // don't handle it again.
354 if (node.hasLabeledBlockInformation() && 603 if (node.hasLabeledBlockInformation() &&
355 node.labeledBlockInformation !== currentBlockInformation) { 604 node.labeledBlockInformation !== currentBlockInformation) {
356 HLabeledBlockInformation oldBlockInformation = currentBlockInformation; 605 HBlockInformation oldBlockInformation = currentBlockInformation;
357 currentBlockInformation = node.labeledBlockInformation; 606 currentBlockInformation = node.labeledBlockInformation;
358 handleLabeledBlock(currentBlockInformation); 607 handleLabeledBlock(currentBlockInformation);
359 currentBlockInformation = oldBlockInformation; 608 currentBlockInformation = oldBlockInformation;
360 return; 609 return;
361 } 610 }
362 611
363 currentBlock = node; 612 if (node.isLoopHeader() &&
364 613 node.loopInformation !== currentBlockInformation) {
365 if (node.isLoopHeader()) { 614 HBlockInformation oldBlockInformation = currentBlockInformation;
366 // While loop will be closed by the conditional loop-branch. 615 currentBlockInformation = node.loopInformation;
367 // TODO(floitsch): HACK HACK HACK. 616 bool prettyLoop = handleLoop(node);
617 currentBlockInformation = oldBlockInformation;
618 if (prettyLoop) {
619 visitBasicBlock(node.loopInformation.joinBlock);
620 return;
621 }
368 beginLoop(node); 622 beginLoop(node);
369 } 623 }
370 624
625 iterateBasicBlock(node);
626 }
627
628 void iterateBasicBlock(HBasicBlock node) {
629 currentBlock = node;
371 HInstruction instruction = node.first; 630 HInstruction instruction = node.first;
372 while (instruction != null) { 631 while (instruction != null) {
373 if (instruction === node.last) { 632 if (instruction === node.last) {
374 for (HBasicBlock successor in node.successors) { 633 for (HBasicBlock successor in node.successors) {
375 int index = successor.predecessors.indexOf(node); 634 int index = successor.predecessors.indexOf(node);
376 successor.forEachPhi((HPhi phi) { 635 successor.forEachPhi((HPhi phi) {
377 bool isLogicalOperation = logicalOperations.containsKey(phi); 636 bool isLogicalOperation = logicalOperations.containsKey(phi);
378 // In case the phi is being generated by another 637 // In case the phi is being generated by another
379 // instruction. 638 // instruction.
380 if (isLogicalOperation && isGenerateAtUseSite(phi)) return; 639 if (isLogicalOperation && isGenerateAtUseSite(phi)) return;
381 addIndentation(); 640 if (isGeneratingExpression()) {
382 if (!temporaryExists(phi)) buffer.add('var '); 641 addExpressionSeparator();
383 buffer.add('${temporary(phi)} = '); 642 } else {
643 addIndentation();
644 }
645 if (!temporaryExists(phi)) {
646 declareVariable(temporary(phi));
647 } else {
648 buffer.add(temporary(phi));
649 }
650 buffer.add(" = ");
384 if (isLogicalOperation) { 651 if (isLogicalOperation) {
385 emitLogicalOperation(phi, logicalOperations[phi]); 652 emitLogicalOperation(phi, logicalOperations[phi]);
386 } else { 653 } else {
387 use(phi.inputs[index], JSPrecedence.ASSIGNMENT_PRECEDENCE); 654 use(phi.inputs[index], JSPrecedence.ASSIGNMENT_PRECEDENCE);
388 } 655 }
389 buffer.add(';\n'); 656 if (!isGeneratingExpression()) {
657 buffer.add(';\n');
658 }
390 }); 659 });
391 } 660 }
392 } 661 }
393 662
394 if (instruction is HGoto || instruction is HExit || instruction is HTry) { 663 if (instruction is HGoto || instruction is HExit || instruction is HTry) {
395 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 664 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
396 return; 665 return;
397 } else if (!isGenerateAtUseSite(instruction)) { 666 } else if (!isGenerateAtUseSite(instruction)) {
398 if (instruction is !HIf && instruction is !HTypeGuard) { 667 if (instruction is !HIf && instruction is !HTypeGuard &&
668 !isGeneratingExpression()) {
399 addIndentation(); 669 addIndentation();
400 } 670 }
671 if (isGeneratingExpression()) {
672 addExpressionSeparator();
673 }
401 if (instruction.usedBy.isEmpty() 674 if (instruction.usedBy.isEmpty()
402 || instruction is HTypeGuard 675 || instruction is HTypeGuard
403 || instruction is HCheck) { 676 || instruction is HCheck) {
404 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 677 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
405 } else { 678 } else {
406 define(instruction); 679 define(instruction);
407 } 680 }
408 // Control flow instructions know how to handle ';'. 681 // Control flow instructions know how to handle ';'.
409 if (instruction is !HControlFlow && instruction is !HTypeGuard) { 682 if (instruction is !HControlFlow && instruction is !HTypeGuard &&
683 !isGeneratingExpression()) {
410 buffer.add(';\n'); 684 buffer.add(';\n');
411 } 685 }
412 } else if (instruction is HIf) { 686 } else if (instruction is HIf) {
413 HIf hif = instruction; 687 HIf hif = instruction;
414 // The "if" is implementing part of a logical expression. 688 // The "if" is implementing part of a logical expression.
415 // Skip directly forward to to its latest successor, since everything 689 // Skip directly forward to to its latest successor, since everything
416 // in-between must also be generateAtUseSite. 690 // in-between must also be generateAtUseSite.
417 assert(hif.trueBranch.id < hif.falseBranch.id); 691 assert(hif.trueBranch.id < hif.falseBranch.id);
418 visitBasicBlock(hif.falseBranch); 692 visitBasicBlock(hif.falseBranch);
419 return; 693 return;
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 addIndentation(); 844 addIndentation();
571 buffer.add("break;\n"); 845 buffer.add("break;\n");
572 } 846 }
573 } 847 }
574 } 848 }
575 849
576 visitContinue(HContinue node) { 850 visitContinue(HContinue node) {
577 assert(currentBlock.successors.length == 1); 851 assert(currentBlock.successors.length == 1);
578 if (node.label !== null) { 852 if (node.label !== null) {
579 LabelElement label = node.label; 853 LabelElement label = node.label;
854 buffer.add("/*b*/");
floitsch 2012/03/29 21:44:11 debug?
Lasse Reichstein Nielsen 2012/03/30 09:37:17 Done.
580 if (!tryCallAction(continueAction, label)) { 855 if (!tryCallAction(continueAction, label)) {
856 buffer.add("/*a*/");
floitsch 2012/03/29 21:44:11 ditto.
Lasse Reichstein Nielsen 2012/03/30 09:37:17 Done.
581 addIndentation(); 857 addIndentation();
582 buffer.add("continue "); 858 buffer.add("continue ");
583 writeLabel(label); 859 writeLabel(label);
584 buffer.add(";\n"); 860 buffer.add(";\n");
585 } 861 }
586 } else { 862 } else {
587 TargetElement target = node.target; 863 TargetElement target = node.target;
588 if (!tryCallAction(continueAction, target)) { 864 if (!tryCallAction(continueAction, target)) {
589 addIndentation(); 865 addIndentation();
590 buffer.add("continue;\n"); 866 buffer.add("continue;\n");
(...skipping 28 matching lines...) Expand all
619 visitBasicBlock(node.finallyBlock); 895 visitBasicBlock(node.finallyBlock);
620 indent--; 896 indent--;
621 } 897 }
622 addIndentation(); 898 addIndentation();
623 buffer.add('}\n'); 899 buffer.add('}\n');
624 900
625 visitBasicBlock(node.joinBlock); 901 visitBasicBlock(node.joinBlock);
626 } 902 }
627 903
628 visitIf(HIf node) { 904 visitIf(HIf node) {
905 if (isGeneratingExpression()) {
906 assert(node.block == subGraph.end);
907 // We are generating an expression for a condition.
908 addExpressionSeparator();
909 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
910 return;
911 }
629 List<HBasicBlock> dominated = node.block.dominatedBlocks; 912 List<HBasicBlock> dominated = node.block.dominatedBlocks;
630 HIfBlockInformation info = node.blockInformation; 913 HIfBlockInformation info = node.blockInformation;
631 startIf(node); 914 startIf(node);
632 assert(!isGenerateAtUseSite(node)); 915 assert(!isGenerateAtUseSite(node));
633 startThen(node); 916 startThen(node);
634 assert(node.thenBlock === dominated[0]); 917 assert(node.thenBlock === dominated[0]);
635 visitSubGraph(info.thenGraph); 918 visitSubGraph(info.thenGraph);
636 int preVisitedBlocks = 1; 919 int preVisitedBlocks = 1;
637 endThen(node); 920 endThen(node);
638 if (node.hasElse) { 921 if (node.hasElse) {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 1043 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
761 buffer.add('.'); 1044 buffer.add('.');
762 buffer.add(name); 1045 buffer.add(name);
763 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); 1046 beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
764 } else { 1047 } else {
765 buffer.add(name); 1048 buffer.add(name);
766 } 1049 }
767 } 1050 }
768 1051
769 visitFieldSet(HFieldSet node) { 1052 visitFieldSet(HFieldSet node) {
1053 // This method may introduce variable declarations in the JS code.
1054 // If we are generating an expression, those variable declarations
1055 // must be delayed until later.
1056 bool delayDeclaration = false;
1057 String name = JsNames.getValid(node.element.name.slowToString());
770 if (node.receiver !== null) { 1058 if (node.receiver !== null) {
771 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 1059 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
772 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 1060 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
773 buffer.add('.'); 1061 buffer.add('.');
1062 buffer.add(name);
774 } else { 1063 } else {
775 // TODO(ngeoffray): Remove the 'var' once we don't globally box 1064 // TODO(ngeoffray): Remove the 'var' once we don't globally box
776 // variables used in a try/catch. 1065 // variables used in a try/catch.
777 buffer.add('var '); 1066 declareVariable(name);
778 } 1067 }
779 String name = JsNames.getValid(node.element.name.slowToString()); 1068 if (delayDeclaration) delayedVarDecl = delayedVarDecl.prepend(name);
780 buffer.add(name);
781 buffer.add(' = '); 1069 buffer.add(' = ');
782 use(node.value, JSPrecedence.ASSIGNMENT_PRECEDENCE); 1070 use(node.value, JSPrecedence.ASSIGNMENT_PRECEDENCE);
783 if (node.receiver !== null) { 1071 if (node.receiver !== null) {
784 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 1072 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
785 } 1073 }
786 } 1074 }
787 1075
788 visitForeign(HForeign node) { 1076 visitForeign(HForeign node) {
789 String code = node.code.slowToString(); 1077 String code = node.code.slowToString();
790 List<HInstruction> inputs = node.inputs; 1078 List<HInstruction> inputs = node.inputs;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 node.constant.writeJsCode(buffer, handler); 1122 node.constant.writeJsCode(buffer, handler);
835 } 1123 }
836 } else { 1124 } else {
837 buffer.add(compiler.namer.CURRENT_ISOLATE); 1125 buffer.add(compiler.namer.CURRENT_ISOLATE);
838 buffer.add("."); 1126 buffer.add(".");
839 buffer.add(name); 1127 buffer.add(name);
840 } 1128 }
841 } 1129 }
842 1130
843 visitLoopBranch(HLoopBranch node) { 1131 visitLoopBranch(HLoopBranch node) {
1132 if (subGraph !== null && node.block == subGraph.end) {
1133 // We are generating code for a loop condition.
1134 // If doing this as part of a SubGraph traversal, the
1135 // calling code will handle the control flow logic.
1136 if (isGeneratingExpression()) {
1137 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
1138 }
1139 return;
1140 }
844 HBasicBlock branchBlock = currentBlock; 1141 HBasicBlock branchBlock = currentBlock;
845 handleLoopCondition(node); 1142 handleLoopCondition(node);
846 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; 1143 List<HBasicBlock> dominated = currentBlock.dominatedBlocks;
847 // For a do while loop, the body has already been visited. 1144 // For a do while loop, the body has already been visited.
848 if (!node.isDoWhile()) { 1145 if (!node.isDoWhile()) {
849 visitBasicBlock(dominated[0]); 1146 visitBasicBlock(dominated[0]);
850 } 1147 }
851 endLoop(node.block); 1148 endLoop(node.block);
852 visitBasicBlock(branchBlock.successors[1]); 1149 visitBasicBlock(branchBlock.successors[1]);
853 // With labeled breaks we can have more dominated blocks. 1150 // With labeled breaks we can have more dominated blocks.
(...skipping 550 matching lines...) Expand 10 before | Expand all | Expand 10 after
1404 HBoundsCheck instruction = argument; 1701 HBoundsCheck instruction = argument;
1405 return unwrap(instruction.index); 1702 return unwrap(instruction.index);
1406 } else if (argument is HTypeGuard) { 1703 } else if (argument is HTypeGuard) {
1407 HTypeGuard instruction = argument; 1704 HTypeGuard instruction = argument;
1408 return unwrap(instruction.guarded); 1705 return unwrap(instruction.guarded);
1409 } else { 1706 } else {
1410 return argument; 1707 return argument;
1411 } 1708 }
1412 } 1709 }
1413 1710
1711 bool handleLoop(HBasicBlock node) => false;
1712
1414 void visitTypeGuard(HTypeGuard node) { 1713 void visitTypeGuard(HTypeGuard node) {
1415 indent--; 1714 indent--;
1416 addIndentation(); 1715 addIndentation();
1417 buffer.add('case ${node.state}:\n'); 1716 buffer.add('case ${node.state}:\n');
1418 indent++; 1717 indent++;
1419 addIndentation(); 1718 addIndentation();
1420 buffer.add('state = 0;\n'); 1719 buffer.add('state = 0;\n');
1421 1720
1422 setup.add(' case ${node.state}:\n'); 1721 setup.add(' case ${node.state}:\n');
1423 int i = 0; 1722 int i = 0;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 startBailoutSwitch(); 1855 startBailoutSwitch();
1557 } 1856 }
1558 } 1857 }
1559 1858
1560 void endElse(HIf node) { 1859 void endElse(HIf node) {
1561 if (node.elseBlock.hasGuards()) { 1860 if (node.elseBlock.hasGuards()) {
1562 endBailoutSwitch(); 1861 endBailoutSwitch();
1563 } 1862 }
1564 } 1863 }
1565 } 1864 }
OLDNEW
« no previous file with comments | « frog/leg/ssa/builder.dart ('k') | frog/leg/ssa/nodes.dart » ('j') | frog/leg/ssa/nodes.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698