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

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: 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
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 String generate(WorkItem work, HGraph graph) { 9 String generate(WorkItem work, HGraph graph) {
10 return measure(() { 10 return measure(() {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 } 73 }
74 }); 74 });
75 compiler.enqueue(new WorkItem.bailoutVersion( 75 compiler.enqueue(new WorkItem.bailoutVersion(
76 work.element, work.resolutionTree, bailouts)); 76 work.element, work.resolutionTree, bailouts));
77 } 77 }
78 } 78 }
79 79
80 typedef void ElementAction(Element element); 80 typedef void ElementAction(Element element);
81 81
82 class SsaCodeGenerator implements HVisitor { 82 class SsaCodeGenerator implements HVisitor {
83 /**
84 * Current state for generating simple (non-local-control) code.
85 * It is generated as either statements (indented and ';'-terminated),
86 * expressions (comma separated) or declarations (also comma separated,
87 * but expected to be preceeded by a 'var' so it declares its variables);
88 */
89 static final int STATE_STATEMENT = 0;
90 static final int STATE_FIRST_EXPRESSION = 1;
91 static final int STATE_FIRST_DECLARATION = 2;
floitsch 2012/03/28 04:03:48 FIRST_DECLARATION and STATE_DECLARATION are unused
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Yes. They are preparing for including the initiali
92 static final int STATE_EXPRESSION = 3;
93 static final int STATE_DECLARATION = 4;
94
83 final Compiler compiler; 95 final Compiler compiler;
84 final WorkItem work; 96 final WorkItem work;
85 final StringBuffer buffer; 97 final StringBuffer buffer;
86 final StringBuffer parameters; 98 final StringBuffer parameters;
87 99
88 final Map<Element, String> parameterNames; 100 final Map<Element, String> parameterNames;
89 final Map<int, String> names; 101 final Map<int, String> names;
90 final Map<String, int> prefixes; 102 final Map<String, int> prefixes;
91 final Set<HInstruction> generateAtUseSite; 103 final Set<HInstruction> generateAtUseSite;
92 final Map<HPhi, String> logicalOperations; 104 final Map<HPhi, String> logicalOperations;
93 final Map<Element, ElementAction> breakAction; 105 final Map<Element, ElementAction> breakAction;
94 final Map<Element, ElementAction> continueAction; 106 final Map<Element, ElementAction> continueAction;
95 107
96 Element equalsNullElement; 108 Element equalsNullElement;
97 int indent = 0; 109 int indent = 0;
98 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; 110 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE;
99 HGraph currentGraph; 111 HGraph currentGraph;
112 /**
113 * Whether the code-generation should try to generate an expression
114 * instead of a sequence of statements.
115 */
116 int generationState = STATE_STATEMENT;
117 /**
118 * While generating expressions, we can't insert variable declarations.
119 * Instead we declare them at the end of the function
120 */
121 Link<String> delayedVarDecl = const EmptyLink<String>();
100 HBasicBlock currentBlock; 122 HBasicBlock currentBlock;
101 123
102 // Records a block-information that is being handled specially. 124 // Records a block-information that is being handled specially.
103 // Used to break bad recursion. 125 // Used to break bad recursion.
104 HLabeledBlockInformation currentBlockInformation; 126 HBlockInformation currentBlockInformation;
105 // The subgraph is used to delimit traversal for some constructions, e.g., 127 // The subgraph is used to delimit traversal for some constructions, e.g.,
106 // if branches. 128 // if branches.
107 SubGraph subGraph; 129 SubGraph subGraph;
108 130
109 LibraryElement get currentLibrary() => work.element.getLibrary(); 131 LibraryElement get currentLibrary() => work.element.getLibrary();
110 132
111 bool isGenerateAtUseSite(HInstruction instruction) { 133 bool isGenerateAtUseSite(HInstruction instruction) {
112 return generateAtUseSite.contains(instruction); 134 return generateAtUseSite.contains(instruction);
113 } 135 }
114 136
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 logicalOperations).visitGraph(graph); 189 logicalOperations).visitGraph(graph);
168 } 190 }
169 191
170 visitGraph(HGraph graph) { 192 visitGraph(HGraph graph) {
171 preGenerateMethod(graph); 193 preGenerateMethod(graph);
172 currentGraph = graph; 194 currentGraph = graph;
173 indent++; // We are already inside a function. 195 indent++; // We are already inside a function.
174 subGraph = new SubGraph(graph.entry, graph.exit); 196 subGraph = new SubGraph(graph.entry, graph.exit);
175 beginGraph(graph); 197 beginGraph(graph);
176 visitBasicBlock(graph.entry); 198 visitBasicBlock(graph.entry);
199 if (!delayedVarDecl.isEmpty()) {
200 addIndentation();
201 buffer.add("var ");
202 while (true) {
203 buffer.add(delayedVarDecl.head);
204 delayedVarDecl = delayedVarDecl.tail;
205 if (delayedVarDecl.isEmpty()) break;
206 buffer.add(", ");
207 }
208 buffer.add(";\n");
209 }
177 endGraph(graph); 210 endGraph(graph);
178 } 211 }
179 212
180 void visitSubGraph(SubGraph newSubGraph) { 213 void visitSubGraph(SubGraph newSubGraph) {
181 SubGraph oldSubGraph = subGraph; 214 SubGraph oldSubGraph = subGraph;
182 subGraph = newSubGraph; 215 subGraph = newSubGraph;
183 visitBasicBlock(subGraph.start); 216 visitBasicBlock(subGraph.start);
184 subGraph = oldSubGraph; 217 subGraph = oldSubGraph;
185 } 218 }
186 219
220 bool isExpression(SubGraph limits) {
221 HBasicBlock basicBlock = limits.start;
222 do {
223 HInstruction current = basicBlock.first;
224 while (current != basicBlock.last) {
225 // E.g, BailoutTarget.
ngeoffray 2012/03/28 15:28:04 BailoutTarget does not exist anymore.
226 if (current.isControlFlow()) {
227 print("[isExpression FAIL: $current]");
floitsch 2012/03/28 04:03:48 debug code?
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Ah, yes. Will remove them all.
228 return false;
229 }
230 current = current.next;
231 }
232 if (current is HGoto) {
233 basicBlock = basicBlock.successors[0];
234 } else if (current is HConditionalBranch) {
235 if (generateAtUseSite.contains(current)) {
236 // Short-circuit logical operator trickery.
237 // Check the second half, which will continue into the join.
floitsch 2012/03/28 04:03:48 Isn't the second half successors[1]? Can't we just
Lasse Reichstein Nielsen 2012/03/29 13:09:38 No, successors[1] is the join node, the first half
floitsch 2012/03/29 21:44:10 Right... missed that. Please add as comment.
Lasse Reichstein Nielsen 2012/03/30 09:37:17 Done.
238 basicBlock = basicBlock.successors[0];
239 } else {
240 // We allow an expression to end on an HIf (a condition expression).
241 if (basicBlock !== limits.end) print("[isExpression IF_FAIL: $current] ");
floitsch 2012/03/28 04:03:48 debug code?
242 return basicBlock === limits.end;
243 }
244 } else {
245 print("[isExpression CC-FAIL: $current");
floitsch 2012/03/28 04:03:48 debug code?
246 // Expression-incompatible control flow.
247 return false;
248 }
249 } while (limits.contains(basicBlock));
250 return true;
251 }
252
253 bool isCondition(SubGraph limits) {
254 return isExpression(limits) && (limits.end.last is HConditionalBranch);
255 }
256
257 void visitExpressionGraph(SubGraph subGraph) {
258 int oldState = generationState;
259 generationState = STATE_FIRST_EXPRESSION;
260 visitSubGraph(subGraph);
261 generationState = oldState;
262 }
263
264 void visitConditionGraph(SubGraph subGraph) {
265 visitExpressionGraph(subGraph);
266 }
267
187 String temporary(HInstruction instruction) { 268 String temporary(HInstruction instruction) {
188 int id = instruction.id; 269 int id = instruction.id;
189 String name = names[id]; 270 String name = names[id];
190 if (name !== null) return name; 271 if (name !== null) return name;
191 272
192 if (instruction is HPhi) { 273 if (instruction is HPhi) {
193 HPhi phi = instruction; 274 HPhi phi = instruction;
194 Element element = phi.element; 275 Element element = phi.element;
195 if (element != null && element.kind == ElementKind.PARAMETER) { 276 if (element != null && element.kind == ElementKind.PARAMETER) {
196 name = parameterNames[element]; 277 name = parameterNames[element];
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 void visitArguments(List<HInstruction> inputs) { 314 void visitArguments(List<HInstruction> inputs) {
234 assert(inputs.length >= HInvoke.ARGUMENTS_OFFSET); 315 assert(inputs.length >= HInvoke.ARGUMENTS_OFFSET);
235 buffer.add('('); 316 buffer.add('(');
236 for (int i = HInvoke.ARGUMENTS_OFFSET; i < inputs.length; i++) { 317 for (int i = HInvoke.ARGUMENTS_OFFSET; i < inputs.length; i++) {
237 if (i != HInvoke.ARGUMENTS_OFFSET) buffer.add(', '); 318 if (i != HInvoke.ARGUMENTS_OFFSET) buffer.add(', ');
238 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); 319 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE);
239 } 320 }
240 buffer.add(')'); 321 buffer.add(')');
241 } 322 }
242 323
324
325
326 /**
327 * Whether we are currently generating expressions instead of statements.
328 * This includes declarations, which are generated as expressions.
329 */
330 bool isGeneratingExpression() {
331 return generationState != STATE_STATEMENT;
332 }
333
334 /**
335 * Whether we are generating a declaration.
336 */
337 bool isGeneratingDeclaration() {
338 assert(generationState != STATE_STATEMENT);
339 return (generationState & 0x01) == 0;
floitsch 2012/03/28 04:03:48 magic constant. I don't see generationState as a b
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Yep. Fixed.
340 }
341
342 /**
343 * Called before writing an expression.
344 * Ensures that expressions are comma spearated.
345 */
346 void addExpressionSeparator() {
347 if (generationState <= STATE_FIRST_DECLARATION) {
floitsch 2012/03/28 04:03:48 if (generationState == STATE_FIRST_EXPRESSION) gen
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Done.
348 // From STATE_FIRST_EXPRESSION to STATE_EXPRESSION or from
349 // STATE_FIRST_DECLARATION to STATE_DECLARATION.
350 generationState += 2;
351 } else {
352 buffer.add(", ");
353 }
354 }
355
243 void define(HInstruction instruction) { 356 void define(HInstruction instruction) {
244 buffer.add('var ${temporary(instruction)} = '); 357 String temporaryVar = temporary(instruction);
245 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); 358 if (isGeneratingExpression()) {
359 // As expression.
360 if (!isGeneratingDeclaration()) {
361 delayedVarDecl = delayedVarDecl.prepend(temporaryVar);
362 }
363 addExpressionSeparator();
364 buffer.add('$temporaryVar = ');
365 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE);
366 } else {
367 // As statement.
368 buffer.add('var $temporaryVar = ');
369 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE);
370 }
246 } 371 }
247 372
248 void use(HInstruction argument, int expectedPrecedence) { 373 void use(HInstruction argument, int expectedPrecedence) {
249 if (isGenerateAtUseSite(argument)) { 374 if (isGenerateAtUseSite(argument)) {
250 visit(argument, expectedPrecedence); 375 visit(argument, expectedPrecedence);
251 } else if (argument is HIntegerCheck) { 376 } else if (argument is HIntegerCheck) {
252 HIntegerCheck instruction = argument; 377 HIntegerCheck instruction = argument;
253 use(instruction.value, expectedPrecedence); 378 use(instruction.value, expectedPrecedence);
254 } else if (argument is HBoundsCheck) { 379 } else if (argument is HBoundsCheck) {
255 HBoundsCheck instruction = argument; 380 HBoundsCheck instruction = argument;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 void emitLogicalOperation(HPhi node, String operation) { 481 void emitLogicalOperation(HPhi node, String operation) {
357 JSBinaryOperatorPrecedence operatorPrecedence = 482 JSBinaryOperatorPrecedence operatorPrecedence =
358 JSPrecedence.binary[operation]; 483 JSPrecedence.binary[operation];
359 beginExpression(operatorPrecedence.precedence); 484 beginExpression(operatorPrecedence.precedence);
360 use(node.inputs[0], operatorPrecedence.left); 485 use(node.inputs[0], operatorPrecedence.left);
361 buffer.add(" $operation "); 486 buffer.add(" $operation ");
362 use(node.inputs[1], operatorPrecedence.right); 487 use(node.inputs[1], operatorPrecedence.right);
363 endExpression(operatorPrecedence.precedence); 488 endExpression(operatorPrecedence.precedence);
364 } 489 }
365 490
366 visitBasicBlock(HBasicBlock node) { 491 bool handleLoop(HBasicBlock node) {
492 assert(node.isLoopHeader());
493 HLoopInformation info = node.loopInformation;
494 SubExpression condition = info.condition;
495 print("LOOP: [${["WHILE","FOR","DO-WHILE","FOR-IN"][info.type]}]");
floitsch 2012/03/28 04:03:48 debug code?
496 if (isCondition(condition)) {
497 print("--[Condition is Expression!]");
498 switch (info.type) {
499 case HLoopInformation.WHILE_LOOP:
500 case HLoopInformation.FOR_IN_LOOP: {
501 addIndentation();
502 for (LabelElement label in info.labels) {
503 writeLabel(label);
504 buffer.add(":");
505 }
506 buffer.add("while (");
507 visitConditionGraph(condition);
508 buffer.add(") {\n");
509 indent++;
510 visitSubGraph(info.body);
511 if (info.updates !== null) {
512 // Even in while loops the updates block may be needed to
513 // handle phi nodes of its successors.
514 visitSubGraph(info.updates);
515 }
516 indent--;
517 addIndentation();
518 buffer.add("}\n");
519 break;
520 }
521 case HLoopInformation.FOR_LOOP: {
522 // TODO(lrn): Find a way to put initialization into the for.
523 // It's currently handled before we reach the [HLoopInformation].
524 addIndentation();
525 for (LabelElement label in info.labels) {
526 if (label.isTarget) {
527 writeLabel(label);
528 buffer.add(":");
529 }
530 }
531 buffer.add("for(;");
532 visitConditionGraph(info.condition);
533 buffer.add(";");
534 if (isExpression(info.updates)) {
535 visitExpressionGraph(info.updates);
536 buffer.add(") {\n");
537 indent++;
538 visitSubGraph(info.body);
539 indent--;
540 addIndentation();
541 buffer.add("}\n");
542 } else {
543 buffer.add(") {\n");
544 indent++;
545 if (info.target !== null && info.target.isContinueTarget) {
546 addIndentation();
547 for (LabelElement label in info.labels) {
548 if (label.isContinueTarget) {
549 writeContinueLabel(label);
550 buffer.add(":");
551 continueActions[label] = continueAsBreak;
floitsch 2012/03/28 04:03:48 continueAction. Add test.
552 }
553 }
554 addImplicitContinueLabel();
555 buffer.add(":{\n");
556 continueAction[info.target] = implicitContinueAsBreak;
557 indent++;
floitsch 2012/03/28 04:03:48 move indent++ closer to "{" ?
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Refactored away.
558 }
559 visitSubGraph(info.body);
floitsch 2012/03/28 04:03:48 I would keep the 'if' open and duplicate the 'visi
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Done.
560 if (info.target !== null && info.target.isContinueTarget) {
561 indent--;
562 buffer.add("}\n");
563 continueAction.remove(info.target);
564 for (LabelElement label in info.labels) {
565 if (label.isContinueTarget) {
566 continueAction.remove(label);
567 }
568 }
569 }
570 visitSubGraph(info.updates);
571 indent--;
572 buffer.add("}\n");
573 }
574 break;
575 }
576 case HLoopInformation.DO_WHILE_LOOP:
577 default:
578 return false;
floitsch 2012/03/28 04:03:48 I don't like these "return false/true" where it is
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Done.
579 }
580 return true;
581 }
582 return false;
583 }
584
585 void visitBasicBlock(HBasicBlock node) {
367 // Abort traversal if we are leaving the currently active sub-graph. 586 // Abort traversal if we are leaving the currently active sub-graph.
368 if (!subGraph.contains(node)) return; 587 if (!subGraph.contains(node)) return;
369 588
370 // If this node has special behavior attached, handle it. 589 // If this node has special behavior attached, handle it.
371 // If we reach here again while handling the attached information, 590 // If we reach here again while handling the attached information,
372 // e.g., because we call visitSubGraph on a subgraph starting here, 591 // e.g., because we call visitSubGraph on a subgraph starting here,
373 // don't handle it again. 592 // don't handle it again.
374 if (node.hasLabeledBlockInformation() && 593 if (node.hasLabeledBlockInformation() &&
375 node.labeledBlockInformation !== currentBlockInformation) { 594 node.labeledBlockInformation !== currentBlockInformation) {
376 HLabeledBlockInformation oldBlockInformation = currentBlockInformation; 595 HBlockInformation oldBlockInformation = currentBlockInformation;
377 currentBlockInformation = node.labeledBlockInformation; 596 currentBlockInformation = node.labeledBlockInformation;
378 handleLabeledBlock(currentBlockInformation); 597 handleLabeledBlock(currentBlockInformation);
379 currentBlockInformation = oldBlockInformation; 598 currentBlockInformation = oldBlockInformation;
380 return; 599 return;
381 } 600 }
382 601
383 currentBlock = node; 602 if (node.isLoopHeader() &&
384 603 node.loopInformation !== currentBlockInformation) {
385 if (node.isLoopHeader()) { 604 HBlockInformation oldBlockInformation = currentBlockInformation;
386 // While loop will be closed by the conditional loop-branch. 605 currentBlockInformation = node.loopInformation;
387 // TODO(floitsch): HACK HACK HACK. 606 if (handleLoop(node)) {
floitsch 2012/03/28 04:03:48 WOOT!!! ;)
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Don't be too happy, the code is still there as a f
floitsch 2012/03/28 04:03:48 not a strong preference but I would prefer: bool s
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Done.
607 currentBlockInformation = oldBlockInformation;
608 visitBasicBlock(node.loopInformation.joinBlock);
609 return;
610 }
611 currentBlockInformation = oldBlockInformation;
388 beginLoop(node); 612 beginLoop(node);
389 } 613 }
390 614
615 iterateBasicBlock(node);
616 }
617
618 void iterateBasicBlock(HBasicBlock node) {
619 currentBlock = node;
620 bool firstExpression = true;
floitsch 2012/03/28 04:03:48 unused variable.
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Done.
391 HInstruction instruction = node.first; 621 HInstruction instruction = node.first;
392 while (instruction != null) { 622 while (instruction != null) {
393 if (instruction === node.last) { 623 if (instruction === node.last) {
394 for (HBasicBlock successor in node.successors) { 624 for (HBasicBlock successor in node.successors) {
395 int index = successor.predecessors.indexOf(node); 625 int index = successor.predecessors.indexOf(node);
396 successor.forEachPhi((HPhi phi) { 626 successor.forEachPhi((HPhi phi) {
397 bool isLogicalOperation = logicalOperations.containsKey(phi); 627 bool isLogicalOperation = logicalOperations.containsKey(phi);
398 // In case the phi is being generated by another 628 // In case the phi is being generated by another
399 // instruction. 629 // instruction.
400 if (isLogicalOperation && isGenerateAtUseSite(phi)) return; 630 if (isLogicalOperation && isGenerateAtUseSite(phi)) return;
401 addIndentation(); 631 if (isGeneratingExpression()) {
402 if (!temporaryExists(phi)) buffer.add('var '); 632 addExpressionSeparator();
403 buffer.add('${temporary(phi)} = '); 633 String temporaryVar;
634 if (!temporaryExists(phi) && !isGeneratingDeclaration()) {
635 temporaryVar = temporary(phi);
636 delayedVarDecl = delayedVarDecl.prepend(temporaryVar);
637 } else {
638 temporaryVar = temporary(phi);
639 }
640 buffer.add(temporaryVar);
641 buffer.add(" = ");
642 } else {
643 addIndentation();
644 if (!temporaryExists(phi)) buffer.add('var ');
645 buffer.add('${temporary(phi)} = ');
646 }
404 if (isLogicalOperation) { 647 if (isLogicalOperation) {
405 emitLogicalOperation(phi, logicalOperations[phi]); 648 emitLogicalOperation(phi, logicalOperations[phi]);
406 } else { 649 } else {
407 use(phi.inputs[index], JSPrecedence.ASSIGNMENT_PRECEDENCE); 650 use(phi.inputs[index], JSPrecedence.ASSIGNMENT_PRECEDENCE);
408 } 651 }
409 buffer.add(';\n'); 652 if (!isGeneratingExpression()) {
653 buffer.add(';\n');
654 }
410 }); 655 });
411 } 656 }
412 } 657 }
413 658
414 if (instruction is HGoto || instruction is HExit || instruction is HTry) { 659 if (instruction is HGoto || instruction is HExit || instruction is HTry) {
415 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 660 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
416 return; 661 return;
417 } else if (!isGenerateAtUseSite(instruction)) { 662 } else if (!isGenerateAtUseSite(instruction)) {
418 if (instruction is !HIf && instruction is !HBailoutTarget) { 663 if (instruction is !HIf && instruction is !HBailoutTarget &&
664 !isGeneratingExpression()) {
419 addIndentation(); 665 addIndentation();
420 } 666 }
421 if (instruction.usedBy.isEmpty() 667 if (instruction.usedBy.isEmpty()
422 || instruction is HTypeGuard 668 || instruction is HTypeGuard
423 || instruction is HCheck) { 669 || instruction is HCheck) {
670 if (isGeneratingExpression()) {
671 addExpressionSeparator();
672 }
424 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 673 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
425 } else { 674 } else {
426 define(instruction); 675 define(instruction);
427 } 676 }
428 // Control flow instructions know how to handle ';'. 677 // Control flow instructions know how to handle ';'.
429 if (instruction is !HControlFlow && instruction is !HBailoutTarget) { 678 if (instruction is! HControlFlow && instruction is! HBailoutTarget &&
679 !isGeneratingExpression()) {
430 buffer.add(';\n'); 680 buffer.add(';\n');
431 } 681 }
432 } else if (instruction is HIf) { 682 } else if (instruction is HIf) {
433 HIf hif = instruction; 683 HIf hif = instruction;
434 // The "if" is implementing part of a logical expression. 684 // The "if" is implementing part of a logical expression.
435 // Skip directly forward to to its latest successor, since everything 685 // Skip directly forward to to its latest successor, since everything
436 // in-between must also be generateAtUseSite. 686 // in-between must also be generateAtUseSite.
437 assert(hif.trueBranch.id < hif.falseBranch.id); 687 assert(hif.trueBranch.id < hif.falseBranch.id);
438 visitBasicBlock(hif.falseBranch); 688 visitBasicBlock(hif.falseBranch);
439 return; 689 return;
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 visitBasicBlock(node.finallyBlock); 889 visitBasicBlock(node.finallyBlock);
640 indent--; 890 indent--;
641 } 891 }
642 addIndentation(); 892 addIndentation();
643 buffer.add('}\n'); 893 buffer.add('}\n');
644 894
645 visitBasicBlock(node.joinBlock); 895 visitBasicBlock(node.joinBlock);
646 } 896 }
647 897
648 visitIf(HIf node) { 898 visitIf(HIf node) {
899 if (isGeneratingExpression()) {
floitsch 2012/03/28 04:03:48 can you give an example when this is happening?
Lasse Reichstein Nielsen 2012/03/29 13:09:38 When we are expression-generating the condition of
floitsch 2012/03/29 21:44:10 But then it should be a loop-condition and end wit
Lasse Reichstein Nielsen 2012/03/30 09:37:17 True. A HIf is only part of an expression if it's
900 assert(node.block == subGraph.end);
901 // We are generating an expression for a condition.
902 addExpressionSeparator();
903 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
904 return;
905 }
649 List<HBasicBlock> dominated = node.block.dominatedBlocks; 906 List<HBasicBlock> dominated = node.block.dominatedBlocks;
650 HIfBlockInformation info = node.blockInformation; 907 HIfBlockInformation info = node.blockInformation;
651 startIf(node); 908 startIf(node);
652 assert(!isGenerateAtUseSite(node)); 909 assert(!isGenerateAtUseSite(node));
653 startThen(node); 910 startThen(node);
654 assert(node.thenBlock === dominated[0]); 911 assert(node.thenBlock === dominated[0]);
655 visitSubGraph(info.thenGraph); 912 visitSubGraph(info.thenGraph);
656 int preVisitedBlocks = 1; 913 int preVisitedBlocks = 1;
657 endThen(node); 914 endThen(node);
658 if (node.hasElse) { 915 if (node.hasElse) {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 1037 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
781 buffer.add('.'); 1038 buffer.add('.');
782 buffer.add(name); 1039 buffer.add(name);
783 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); 1040 beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
784 } else { 1041 } else {
785 buffer.add(name); 1042 buffer.add(name);
786 } 1043 }
787 } 1044 }
788 1045
789 visitFieldSet(HFieldSet node) { 1046 visitFieldSet(HFieldSet node) {
1047 bool delayDeclaration = false;
ngeoffray 2012/03/28 15:28:04 Please add a comment on why FieldSet needs to part
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Even better, instead of deferring it to a later cl
790 if (node.receiver !== null) { 1048 if (node.receiver !== null) {
791 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 1049 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
792 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 1050 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
793 buffer.add('.'); 1051 buffer.add('.');
794 } else { 1052 } else {
795 // TODO(ngeoffray): Remove the 'var' once we don't globally box 1053 // TODO(ngeoffray): Remove the 'var' once we don't globally box
796 // variables used in a try/catch. 1054 // variables used in a try/catch.
797 buffer.add('var '); 1055 if (isGeneratingExpression()) {
1056 delayDeclaration = !isGeneratingDeclaration();
1057 } else {
1058 buffer.add('var ');
1059 }
798 } 1060 }
799 String name = JsNames.getValid(node.element.name.slowToString()); 1061 String name = JsNames.getValid(node.element.name.slowToString());
800 buffer.add(name); 1062 buffer.add(name);
1063 if (delayDeclaration) delayedVarDecl = delayedVarDecl.prepend(name);
801 buffer.add(' = '); 1064 buffer.add(' = ');
802 use(node.value, JSPrecedence.ASSIGNMENT_PRECEDENCE); 1065 use(node.value, JSPrecedence.ASSIGNMENT_PRECEDENCE);
803 if (node.receiver !== null) { 1066 if (node.receiver !== null) {
804 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 1067 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
805 } 1068 }
806 } 1069 }
807 1070
808 visitForeign(HForeign node) { 1071 visitForeign(HForeign node) {
809 String code = node.code.slowToString(); 1072 String code = node.code.slowToString();
810 List<HInstruction> inputs = node.inputs; 1073 List<HInstruction> inputs = node.inputs;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 node.constant.writeJsCode(buffer, handler); 1117 node.constant.writeJsCode(buffer, handler);
855 } 1118 }
856 } else { 1119 } else {
857 buffer.add(compiler.namer.CURRENT_ISOLATE); 1120 buffer.add(compiler.namer.CURRENT_ISOLATE);
858 buffer.add("."); 1121 buffer.add(".");
859 buffer.add(name); 1122 buffer.add(name);
860 } 1123 }
861 } 1124 }
862 1125
863 visitLoopBranch(HLoopBranch node) { 1126 visitLoopBranch(HLoopBranch node) {
1127 if (subGraph !== null && node.block == subGraph.end) {
ngeoffray 2012/03/28 15:28:04 How can that happen? Please add a comment.
Lasse Reichstein Nielsen 2012/03/29 13:09:38 Done.
1128 if (isGeneratingExpression()) {
floitsch 2012/03/28 04:03:48 when can we enter here, but not generate an expres
Lasse Reichstein Nielsen 2012/03/29 13:09:38 We can't yet. Eventually I'll want to handle loops
floitsch 2012/03/29 21:44:10 If we can't reach this unless it's an expression,
Lasse Reichstein Nielsen 2012/03/30 09:37:17 Done.
1129 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
1130 }
1131 return;
1132 }
864 HBasicBlock branchBlock = currentBlock; 1133 HBasicBlock branchBlock = currentBlock;
865 handleLoopCondition(node); 1134 handleLoopCondition(node);
866 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; 1135 List<HBasicBlock> dominated = currentBlock.dominatedBlocks;
867 // For a do while loop, the body has already been visited. 1136 // For a do while loop, the body has already been visited.
868 if (!node.isDoWhile()) { 1137 if (!node.isDoWhile()) {
869 visitBasicBlock(dominated[0]); 1138 visitBasicBlock(dominated[0]);
870 } 1139 }
871 endLoop(node.block); 1140 endLoop(node.block);
872 visitBasicBlock(branchBlock.successors[1]); 1141 visitBasicBlock(branchBlock.successors[1]);
873 // With labeled breaks we can have more dominated blocks. 1142 // With labeled breaks we can have more dominated blocks.
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 1699
1431 void endGraph(HGraph graph) { 1700 void endGraph(HGraph graph) {
1432 if (!graph.entry.hasBailouts()) return; 1701 if (!graph.entry.hasBailouts()) return;
1433 indent--; // Close original case. 1702 indent--; // Close original case.
1434 indent--; 1703 indent--;
1435 addIndentation(); 1704 addIndentation();
1436 buffer.add('}\n'); // Close 'switch'. 1705 buffer.add('}\n'); // Close 'switch'.
1437 setup.add(' }\n'); 1706 setup.add(' }\n');
1438 } 1707 }
1439 1708
1709 bool handleLoop(HBasicBlock node) => false;
1710
1440 void visitTypeGuard(HTypeGuard guard) { 1711 void visitTypeGuard(HTypeGuard guard) {
1441 compiler.internalError('Type guard in an unoptimized method'); 1712 compiler.internalError('Type guard in an unoptimized method');
1442 } 1713 }
1443 1714
1444 void visitBailoutTarget(HBailoutTarget node) { 1715 void visitBailoutTarget(HBailoutTarget node) {
1445 indent--; 1716 indent--;
1446 addIndentation(); 1717 addIndentation();
1447 buffer.add('case ${node.state}:\n'); 1718 buffer.add('case ${node.state}:\n');
1448 indent++; 1719 indent++;
1449 addIndentation(); 1720 addIndentation();
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1585 startBailoutSwitch(); 1856 startBailoutSwitch();
1586 } 1857 }
1587 } 1858 }
1588 1859
1589 void endElse(HIf node) { 1860 void endElse(HIf node) {
1590 if (node.elseBlock.hasBailouts()) { 1861 if (node.elseBlock.hasBailouts()) {
1591 endBailoutSwitch(); 1862 endBailoutSwitch();
1592 } 1863 }
1593 } 1864 }
1594 } 1865 }
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