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

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

Issue 9421035: Support break and labeled statements. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Removed unused var. Better trace output. Created 8 years, 10 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 Interceptors { 5 class Interceptors {
6 Compiler compiler; 6 Compiler compiler;
7 Interceptors(Compiler this.compiler); 7 Interceptors(Compiler this.compiler);
8 8
9 SourceString mapOperatorToMethodName(Operator op) { 9 SourceString mapOperatorToMethodName(Operator op) {
10 String name = op.source.stringValue; 10 String name = op.source.stringValue;
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 void enterLoopUpdates(Loop node) { 475 void enterLoopUpdates(Loop node) {
476 // If there are declared boxed loop variables then the updates might have 476 // If there are declared boxed loop variables then the updates might have
477 // access to the box and we must switch to a new box before executing the 477 // access to the box and we must switch to a new box before executing the
478 // updates. 478 // updates.
479 // In all other cases a new box will be created when entering the body of 479 // In all other cases a new box will be created when entering the body of
480 // the next iteration. 480 // the next iteration.
481 ClosureScope scopeData = closureData.capturingScopes[node]; 481 ClosureScope scopeData = closureData.capturingScopes[node];
482 if (scopeData == null) return; 482 if (scopeData == null) return;
483 if (scopeData.hasBoxedLoopVariables()) { 483 if (scopeData.hasBoxedLoopVariables()) {
484 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables); 484 updateCaptureBox(scopeData.boxElement, scopeData.boxedLoopVariables);
485 } 485 }
486 } 486 }
487 487
488 void endLoop(HBasicBlock loopEntry) { 488 void endLoop(HBasicBlock loopEntry) {
489 loopEntry.forEachPhi((HPhi phi) { 489 loopEntry.forEachPhi((HPhi phi) {
490 Element element = phi.element; 490 Element element = phi.element;
491 HInstruction postLoopDefinition = directLocals[element]; 491 HInstruction postLoopDefinition = directLocals[element];
492 phi.addInput(postLoopDefinition); 492 phi.addInput(postLoopDefinition);
493 }); 493 });
494 } 494 }
495 495
496 /**
497 * Merge [otherLocals] into this locals handler, creating phi-nodes when
498 * there is a conflict.
499 * If a phi node is necessary, it will use the otherLocals instruction as the
500 * first input, and this handler's instruction as the second.
501 * NOTICE: This means that the predecessor corresponding to [otherLocals]
502 * should be the first predecessor of the current block, and the one
503 * corresponding to this locals handler should be the second.
504 */
496 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) { 505 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) {
497 // If an element is in one map but not the other we can safely 506 // If an element is in one map but not the other we can safely
498 // ignore it. It means that a variable was declared in the 507 // ignore it. It means that a variable was declared in the
499 // block. Since variable declarations are scoped the declared 508 // block. Since variable declarations are scoped the declared
500 // variable cannot be alive outside the block. Note: this is only 509 // variable cannot be alive outside the block. Note: this is only
501 // true for nodes where we do joins. 510 // true for nodes where we do joins.
502 Map<Element, HInstruction> joinedLocals = new Map<Element, HInstruction>(); 511 Map<Element, HInstruction> joinedLocals = new Map<Element, HInstruction>();
503 otherLocals.directLocals.forEach((element, instruction) { 512 otherLocals.directLocals.forEach((element, instruction) {
504 // We know 'this' cannot be modified. 513 // We know 'this' cannot be modified.
505 if (element === closureData.thisElement) { 514 if (element === closureData.thisElement) {
506 assert(directLocals[element] == instruction); 515 assert(directLocals[element] == instruction);
507 joinedLocals[element] = instruction; 516 joinedLocals[element] = instruction;
508 } else { 517 } else {
509 HInstruction mine = directLocals[element]; 518 HInstruction mine = directLocals[element];
510 if (mine === null) return; 519 if (mine === null) return;
511 if (instruction === mine) { 520 if (instruction === mine) {
512 joinedLocals[element] = instruction; 521 joinedLocals[element] = instruction;
513 } else { 522 } else {
514 HInstruction phi = new HPhi.manyInputs(element, [instruction, mine]); 523 HInstruction phi = new HPhi.manyInputs(element, [instruction, mine]);
515 joinBlock.addPhi(phi); 524 joinBlock.addPhi(phi);
516 joinedLocals[element] = phi; 525 joinedLocals[element] = phi;
517 } 526 }
518 } 527 }
519 }); 528 });
520 directLocals = joinedLocals; 529 directLocals = joinedLocals;
521 } 530 }
522 } 531 }
523 532
533
534 // Represents a single break instruction.
535 class BreakHandlerEntry {
536 final HBreak breakInstruction;
537 final LocalsHandler locals;
538 BreakHandlerEntry(this.breakInstruction, this.locals);
539 }
540
541 interface BreakHandler default BreakHandlerImpl {
542 BreakHandler(Map<StatementElement, BreakHandler> breakTargets);
543 void addTarget(StatementElement element);
544 void addBreak(HBreak breakInstruction);
545 void forEachBreak(Function action);
546 void close();
547 List<SourceString> labels();
548 }
549
550 // Inert break handler used to avoid null checks when a loop isn't
551 // used as the target of a break, and therefore doesn't need a break
552 // handler associated with it.
553 class NullBreakHandler implements BreakHandler {
554 const NullBreakHandler();
555 void addTarget(StatementElement element) { unreachable(); }
556 void addBreak(HBreak breakInstruction) { unreachable() }
557 void forEachBreak(Function ignored) { }
558 void close() { }
559 List<SourceString> labels() => const <SourceString>[];
560 }
561
562 // Records breaks until a target block is available.
563 // Breaks are always forward jumps.
564 class BreakHandlerImpl implements BreakHandler{
565 final Map<StatementElement, BreakHandler> breakTargets;
566 final List<StatementElement> elements;
567 final List<BreakHandlerEntry> breaks;
568 bool closed = false;
569 BreakHandlerImpl(this.breakTargets)
floitsch 2012/02/20 19:01:54 Instead of passing in breakTargets take the builde
Lasse Reichstein Nielsen 2012/02/21 13:53:56 Will do.
570 : elements = <StatementElement>[],
571 breaks = <BreakHandlerEntry>[];
572
573 void addTarget(StatementElement element) {
574 assert(breakTargets[element] === null);
575 elements.add(element);
576 breakTargets[element] = this;
577 }
578
579 void addBreak(HBreak breakInstruction,
580 LocalsHandler locals) {
581 breaks.add(new BreakHandlerEntry(breakInstruction, locals));
582 }
583
584 void forEachBreak(Function action) {
585 for (BreakHandlerEntry entry in breaks) {
586 action(entry.breakInstruction, entry.locals);
587 }
588 }
589
590 void close() {
591 assert(!closed);
592 closed = true;
593 // The mapping from StatementElement to BreakHandler is no longer needed.
594 for (StatementElement element in elements) {
595 assert(breakTargets[element] === this);
596 breakTargets.remove(element);
597 }
598 }
599
600 List<SourceString> labels() {
601 List<SourceString> result = null;
602 for (StatementElement element in elements) {
603 SourceString name = element.name;
604 if (!name.isEmpty()) {
605 if (result === null) result = <SourceString>[];
606 result.add(name);
607 }
608 }
609 return result === null ? const <SourceString>[] : result;
610 }
611 }
612
524 class SsaBuilder implements Visitor { 613 class SsaBuilder implements Visitor {
525 final Compiler compiler; 614 final Compiler compiler;
526 TreeElements elements; 615 TreeElements elements;
527 final Interceptors interceptors; 616 final Interceptors interceptors;
528 final WorkItem work; 617 final WorkItem work;
529 bool methodInterceptionEnabled; 618 bool methodInterceptionEnabled;
530 HGraph graph; 619 HGraph graph;
531 LocalsHandler localsHandler; 620 LocalsHandler localsHandler;
532 621
622 Map<StatementElement, BreakHandler> breakTargets;
623
533 // We build the Ssa graph by simulating a stack machine. 624 // We build the Ssa graph by simulating a stack machine.
534 List<HInstruction> stack; 625 List<HInstruction> stack;
535 626
536 // The current block to add instructions to. Might be null, if we are 627 // The current block to add instructions to. Might be null, if we are
537 // visiting dead code. 628 // visiting dead code.
538 HBasicBlock current; 629 HBasicBlock current;
539 630
540 SsaBuilder(Compiler compiler, WorkItem work) 631 SsaBuilder(Compiler compiler, WorkItem work)
541 : this.compiler = compiler, 632 : this.compiler = compiler,
542 this.work = work, 633 this.work = work,
543 interceptors = compiler.builder.interceptors, 634 interceptors = compiler.builder.interceptors,
544 methodInterceptionEnabled = true, 635 methodInterceptionEnabled = true,
545 elements = work.resolutionTree, 636 elements = work.resolutionTree,
546 graph = new HGraph(), 637 graph = new HGraph(),
547 stack = new List<HInstruction>() { 638 stack = new List<HInstruction>(),
639 breakTargets = new Map<StatementElement, BreakHandler>() {
548 localsHandler = new LocalsHandler(this); 640 localsHandler = new LocalsHandler(this);
549 } 641 }
550 642
551 void disableMethodInterception() { 643 void disableMethodInterception() {
552 assert(methodInterceptionEnabled); 644 assert(methodInterceptionEnabled);
553 methodInterceptionEnabled = false; 645 methodInterceptionEnabled = false;
554 } 646 }
555 647
556 void enableMethodInterception() { 648 void enableMethodInterception() {
557 assert(!methodInterceptionEnabled); 649 assert(!methodInterceptionEnabled);
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 visitExpressionStatement(ExpressionStatement node) { 932 visitExpressionStatement(ExpressionStatement node) {
841 visit(node.expression); 933 visit(node.expression);
842 pop(); 934 pop();
843 } 935 }
844 936
845 /** 937 /**
846 * Creates a new loop-header block. The previous [current] block 938 * Creates a new loop-header block. The previous [current] block
847 * is closed with an [HGoto] and replaced by the newly created block. 939 * is closed with an [HGoto] and replaced by the newly created block.
848 * Also notifies the locals handler that we're entering a loop. 940 * Also notifies the locals handler that we're entering a loop.
849 */ 941 */
850 void beginLoopHeader(Node node) { 942 BreakHandler beginLoopHeader(Node node) {
floitsch 2012/02/20 19:01:54 Instead of returning a BreakHandler make the Break
Lasse Reichstein Nielsen 2012/02/21 13:53:56 Done. Break handlers are now a list, and since the
851 assert(!isAborted()); 943 assert(!isAborted());
852 HBasicBlock previousBlock = close(new HGoto()); 944 HBasicBlock previousBlock = close(new HGoto());
853 945 BreakHandler breakHandler = getLoopBreakHandler(node);
854 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(); 946 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(breakHandler.labels());
855 previousBlock.addSuccessor(loopEntry); 947 previousBlock.addSuccessor(loopEntry);
856 open(loopEntry); 948 open(loopEntry);
857 949
858 localsHandler.beginLoopHeader(node, loopEntry); 950 localsHandler.beginLoopHeader(node, loopEntry);
951 return breakHandler;
859 } 952 }
860 953
861 /** 954 /**
862 * Ends the loop: 955 * Ends the loop:
863 * - creates a new block and adds it as successor to the [branchBlock]. 956 * - creates a new block and adds it as successor to the [branchBlock].
864 * - opens the new block (setting as [current]). 957 * - opens the new block (setting as [current]).
865 * - notifies the locals handler that we're exiting a loop. 958 * - notifies the locals handler that we're exiting a loop.
866 */ 959 */
867 void endLoop(HBasicBlock loopEntry, HBasicBlock branchBlock) { 960 void endLoop(HBasicBlock loopEntry,
961 HBasicBlock branchBlock,
962 BreakHandler breakHandler) {
868 HBasicBlock loopExitBlock = addNewBlock(); 963 HBasicBlock loopExitBlock = addNewBlock();
869 assert(branchBlock.successors.length == 1); 964 assert(branchBlock.successors.length == 1);
870 branchBlock.addSuccessor(loopExitBlock); 965 branchBlock.addSuccessor(loopExitBlock);
871 open(loopExitBlock); 966 open(loopExitBlock);
872 localsHandler.endLoop(loopEntry); 967 localsHandler.endLoop(loopEntry);
968 breakHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
969 HBasicBlock joinBlock = addNewBlock();
970 breakInstruction.block.addSuccessor(joinBlock);
971 goto(current, joinBlock);
972 open(joinBlock);
973 localsHandler.mergeWith(locals, joinBlock);
974 });
873 } 975 }
874 976
875 // For while loops, initializer and update are null. 977 // For while loops, initializer and update are null.
876 visitLoop(Node loop, Node initializer, Expression condition, NodeList updates, 978 visitLoop(Node loop, Node initializer, Expression condition, NodeList updates,
877 Node body) { 979 Node body) {
878 // Generate: 980 // Generate:
879 // <initializer> 981 // <initializer>
880 // loop-entry: 982 // loop-entry:
881 // if (!<condition>) goto loop-exit; 983 // if (!<condition>) goto loop-exit;
882 // <body> 984 // <body>
883 // <updates> 985 // <updates>
884 // goto loop-entry; 986 // goto loop-entry;
885 // loop-exit: 987 // loop-exit:
886 if (condition === null || body === null) { 988 if (condition === null || body === null) {
887 compiler.unimplemented( 989 compiler.unimplemented(
888 'SsaBuilder.visitLoop with empty condition or body', 990 'SsaBuilder.visitLoop with empty condition or body',
889 node: loop); 991 node: loop);
890 } 992 }
891 993
892 localsHandler.startLoop(loop); 994 localsHandler.startLoop(loop);
893 995
894 // The initializer. 996 // The initializer.
895 if (initializer !== null) { 997 if (initializer !== null) {
896 visit(initializer); 998 visit(initializer);
897 // We don't care about the value of the initialization. 999 // We don't care about the value of the initialization.
898 if (initializer.asExpression() !== null) pop(); 1000 if (initializer.asExpression() !== null) pop();
899 } 1001 }
900 assert(!isAborted()); 1002 assert(!isAborted());
901 1003
902 beginLoopHeader(loop); 1004 BreakHandler breakHandler = beginLoopHeader(loop);
903 HBasicBlock conditionBlock = current; 1005 HBasicBlock conditionBlock = current;
904 1006
905 // The condition. 1007 // The condition.
906 visit(condition); 1008 visit(condition);
907 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified())); 1009 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified()));
908 1010
909 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 1011 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
910 1012
911 // The body. 1013 // The body.
912 HBasicBlock bodyBlock = addNewBlock(); 1014 HBasicBlock bodyBlock = addNewBlock();
(...skipping 24 matching lines...) Expand all
937 // The result of the update instruction isn't used, and can just 1039 // The result of the update instruction isn't used, and can just
938 // be dropped. 1040 // be dropped.
939 HInstruction updateInstruction = pop(); 1041 HInstruction updateInstruction = pop();
940 } 1042 }
941 } 1043 }
942 updateBlock = close(new HGoto()); 1044 updateBlock = close(new HGoto());
943 // The back-edge completing the cycle. 1045 // The back-edge completing the cycle.
944 updateBlock.addSuccessor(conditionBlock); 1046 updateBlock.addSuccessor(conditionBlock);
945 conditionBlock.postProcessLoopHeader(); 1047 conditionBlock.postProcessLoopHeader();
946 1048
947 endLoop(conditionBlock, conditionExitBlock); 1049 endLoop(conditionBlock, conditionExitBlock, breakHandler);
948 localsHandler = savedLocals; 1050 localsHandler = savedLocals;
949 } 1051 }
950 1052
951 visitFor(For node) { 1053 visitFor(For node) {
952 if (node.condition === null) { 1054 if (node.condition === null) {
953 compiler.unimplemented("SsaBuilder for loop without condition"); 1055 compiler.unimplemented("SsaBuilder for loop without condition");
954 } 1056 }
955 assert(node.body !== null); 1057 assert(node.body !== null);
956 visitLoop(node, node.initializer, node.condition, node.update, node.body); 1058 visitLoop(node, node.initializer, node.condition, node.update, node.body);
957 } 1059 }
958 1060
959 visitWhile(While node) { 1061 visitWhile(While node) {
960 visitLoop(node, null, node.condition, null, node.body); 1062 visitLoop(node, null, node.condition, null, node.body);
961 } 1063 }
962 1064
963 visitDoWhile(DoWhile node) { 1065 visitDoWhile(DoWhile node) {
964 localsHandler.startLoop(node); 1066 localsHandler.startLoop(node);
965 beginLoopHeader(node); 1067 BreakHandler breakHandler = beginLoopHeader(node);
966 HBasicBlock loopEntryBlock = current; 1068 HBasicBlock loopEntryBlock = current;
967 1069
968 localsHandler.enterLoopBody(node); 1070 localsHandler.enterLoopBody(node);
969 visit(node.body); 1071 visit(node.body);
970 if (isAborted()) { 1072 if (isAborted()) {
971 compiler.unimplemented("SsaBuilder for loop with aborting body"); 1073 compiler.unimplemented("SsaBuilder for loop with aborting body");
972 } 1074 }
973 1075
974 // If there are no continues we could avoid the creation of the condition 1076 // If there are no continues we could avoid the creation of the condition
975 // block. This could also lead to a block having multiple entries and exits. 1077 // block. This could also lead to a block having multiple entries and exits.
976 HBasicBlock bodyExitBlock = close(new HGoto()); 1078 HBasicBlock bodyExitBlock = close(new HGoto());
977 HBasicBlock conditionBlock = addNewBlock(); 1079 HBasicBlock conditionBlock = addNewBlock();
978 bodyExitBlock.addSuccessor(conditionBlock); 1080 bodyExitBlock.addSuccessor(conditionBlock);
979 open(conditionBlock); 1081 open(conditionBlock);
980 visit(node.condition); 1082 visit(node.condition);
981 assert(!isAborted()); 1083 assert(!isAborted());
982 conditionBlock = close(new HLoopBranch(popBoolified())); 1084 conditionBlock = close(new HLoopBranch(popBoolified()));
983 1085
984 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge. 1086 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge.
985 loopEntryBlock.postProcessLoopHeader(); 1087 loopEntryBlock.postProcessLoopHeader();
986 1088
987 endLoop(loopEntryBlock, conditionBlock); 1089 endLoop(loopEntryBlock, conditionBlock, breakHandler);
988 } 1090 }
989 1091
990 visitFunctionExpression(FunctionExpression node) { 1092 visitFunctionExpression(FunctionExpression node) {
991 ClosureData nestedClosureData = closureDataCache[node]; 1093 ClosureData nestedClosureData = closureDataCache[node];
992 assert(nestedClosureData !== null); 1094 assert(nestedClosureData !== null);
993 assert(nestedClosureData.closureClassElement !== null); 1095 assert(nestedClosureData.closureClassElement !== null);
994 ClassElement closureClassElement = 1096 ClassElement closureClassElement =
995 nestedClosureData.closureClassElement; 1097 nestedClosureData.closureClassElement;
996 FunctionElement callElement = nestedClosureData.callElement; 1098 FunctionElement callElement = nestedClosureData.callElement;
997 compiler.enqueue(new WorkItem.toCodegen(callElement, elements)); 1099 compiler.enqueue(new WorkItem.toCodegen(callElement, elements));
(...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after
1874 visitEmptyStatement(EmptyStatement node) { 1976 visitEmptyStatement(EmptyStatement node) {
1875 compiler.unimplemented('SsaBuilder.visitEmptyStatement', 1977 compiler.unimplemented('SsaBuilder.visitEmptyStatement',
1876 node: node); 1978 node: node);
1877 } 1979 }
1878 1980
1879 visitModifiers(Modifiers node) { 1981 visitModifiers(Modifiers node) {
1880 compiler.unimplemented('SsaBuilder.visitModifiers', node: node); 1982 compiler.unimplemented('SsaBuilder.visitModifiers', node: node);
1881 } 1983 }
1882 1984
1883 visitBreakStatement(BreakStatement node) { 1985 visitBreakStatement(BreakStatement node) {
1884 compiler.unimplemented('SsaBuilder.visitBreakStatement', node: node); 1986 work.allowSpeculativeOptimization = false;
1987 assert(!isAborted());
1988 StatementElement target = elements[node];
1989 assert(target !== null);
1990 BreakHandler handler = breakTargets[target];
1991 assert(handler !== null);
1992 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
1993 HBreak breakInstruction;
1994 if (node.target === null) {
1995 breakInstruction = new HBreak();
1996 } else {
1997 breakInstruction = new HBreak(node.target.source);
1998 }
1999 close(breakInstruction);
2000 handler.addBreak(breakInstruction, savedLocals);
1885 } 2001 }
1886 2002
1887 visitContinueStatement(ContinueStatement node) { 2003 visitContinueStatement(ContinueStatement node) {
1888 compiler.unimplemented('SsaBuilder.visitContinueStatement', node: node); 2004 compiler.unimplemented('SsaBuilder.visitContinueStatement', node: node);
1889 } 2005 }
1890 2006
2007 BreakHandler getLoopBreakHandler(Loop node) {
2008 StatementElement element = elements[node];
2009 BreakHandler handler;
2010 if (currentBreakHandler === null) {
2011 if (element === null) return const NullBreakHandler();
2012 handler = new BreakHandler(breakTargets);
2013 } else {
2014 handler = currentBreakHandler;
2015 currentBreakHandler = null;
2016 if (element === null) return handler;
2017 }
2018 handler.addTarget(element);
2019 return handler;
2020 }
2021
1891 visitForInStatement(ForInStatement node) { 2022 visitForInStatement(ForInStatement node) {
1892 // Generate a structure equivalent to: 2023 // Generate a structure equivalent to:
1893 // Iterator<E> $iter = <iterable>.iterator() 2024 // Iterator<E> $iter = <iterable>.iterator()
1894 // while ($iter.hasNext()) { 2025 // while ($iter.hasNext()) {
1895 // E <declaredIdentifier> = $iter.next(); 2026 // E <declaredIdentifier> = $iter.next();
1896 // <body> 2027 // <body>
1897 // } 2028 // }
1898 localsHandler.startLoop(node); 2029 localsHandler.startLoop(node);
1899 2030
1900 SourceString iteratorName = const SourceString("iterator"); 2031 SourceString iteratorName = const SourceString("iterator");
1901 2032
1902 Selector selector = Selector.INVOCATION_0; 2033 Selector selector = Selector.INVOCATION_0;
1903 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0); 2034 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0);
1904 assert(interceptor != null); 2035 assert(interceptor != null);
1905 HStatic target = new HStatic(interceptor); 2036 HStatic target = new HStatic(interceptor);
1906 add(target); 2037 add(target);
1907 visit(node.expression); 2038 visit(node.expression);
1908 List<HInstruction> inputs = <HInstruction>[target, pop()]; 2039 List<HInstruction> inputs = <HInstruction>[target, pop()];
1909 HInstruction iterator = new HInvokeInterceptor( 2040 HInstruction iterator = new HInvokeInterceptor(
1910 selector, iteratorName, false, inputs); 2041 selector, iteratorName, false, inputs);
1911 add(iterator); 2042 add(iterator);
1912 2043
1913 beginLoopHeader(node); 2044 BreakHandler breakHandler = beginLoopHeader(node);
1914 HBasicBlock conditionBlock = current; 2045 HBasicBlock conditionBlock = current;
1915 2046
1916 // The condition. 2047 // The condition.
1917 push(new HInvokeDynamicMethod( 2048 push(new HInvokeDynamicMethod(
1918 selector, const SourceString('hasNext'), [iterator])); 2049 selector, const SourceString('hasNext'), [iterator]));
1919 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified())); 2050 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified()));
1920 2051
1921 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 2052 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
1922 2053
1923 // The body. 2054 // The body.
(...skipping 29 matching lines...) Expand all
1953 // update block is the jump-target for continue statements. We could avoid 2084 // update block is the jump-target for continue statements. We could avoid
1954 // the creation if there is no continue, but for now we always create it. 2085 // the creation if there is no continue, but for now we always create it.
1955 HBasicBlock updateBlock = addNewBlock(); 2086 HBasicBlock updateBlock = addNewBlock();
1956 bodyBlock.addSuccessor(updateBlock); 2087 bodyBlock.addSuccessor(updateBlock);
1957 open(updateBlock); 2088 open(updateBlock);
1958 updateBlock = close(new HGoto()); 2089 updateBlock = close(new HGoto());
1959 // The back-edge completing the cycle. 2090 // The back-edge completing the cycle.
1960 updateBlock.addSuccessor(conditionBlock); 2091 updateBlock.addSuccessor(conditionBlock);
1961 conditionBlock.postProcessLoopHeader(); 2092 conditionBlock.postProcessLoopHeader();
1962 2093
1963 endLoop(conditionBlock, conditionExitBlock); 2094 endLoop(conditionBlock, conditionExitBlock, breakHandler);
1964 localsHandler = savedLocals; 2095 localsHandler = savedLocals;
2096 breakHandler.close();
1965 } 2097 }
1966 2098
2099 BreakHandler currentBreakHandler = null;
2100
1967 visitLabelledStatement(LabelledStatement node) { 2101 visitLabelledStatement(LabelledStatement node) {
1968 compiler.unimplemented('SsaBuilder.visitLabelledStatement', node: node); 2102 BreakHandler handler = null;
2103 Node currentNode = node;
2104 do {
2105 StatementElement element = elements[currentNode];
2106 if (element !== null && element.isBreakTarget) {
2107 if (handler === null) handler = new BreakHandler(breakTargets);
2108 handler.addTarget(element);
2109 }
2110 currentNode = currentNode.statement;
2111 } while (currentNode is LabelledStatement);
2112 if (handler === null) {
2113 // The labels are not break targets.
2114 visit(currentNode);
2115 } else if (currentNode is Loop || currentNode is SwitchStatement) {
2116 // The labels apply to that statement, and will be handled there.
2117 currentBreakHandler = handler;
floitsch 2012/02/20 19:01:54 This looks like work that the resolver should have
Lasse Reichstein Nielsen 2012/02/21 13:53:56 I agree, and agreed when doing the resolution, but
floitsch 2012/02/22 13:17:21 What I wanted: a LabelElement that points to its A
Lasse Reichstein Nielsen 2012/02/22 14:12:24 Touche. I'll consider redoing this in a different
2118 visit(currentNode);
2119 assert(currentBreakHandler === null);
2120 } else {
2121 // Introduce a new basic block.
2122 HBasicBlock entryBlock = graph.addNewBlock();
2123 goto(current, entryBlock);
2124 open(entryBlock);
2125 visit(currentNode);
2126 // Always create at least one join block, even if there turns out to be
2127 // no breaks anyway.
floitsch 2012/02/20 19:01:54 How can this be possible? I thought that the handl
Lasse Reichstein Nielsen 2012/02/21 13:53:56 Some analysis might have turned a break into dead
floitsch 2012/02/22 13:17:21 As long as we don't have such an optimization, ass
Lasse Reichstein Nielsen 2012/02/22 14:12:24 As discussed offline, the break could be dead code
2128 HBasicBlock firstJoinBlock = graph.addNewBlock();
2129 bool isFirst = true;
2130 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
2131 HBasicBlock joinBlock = isFirst ? firstJoinBlock : graph.addNewBlock();
2132 isFirst = false;
2133 breakInstruction.block.addSuccessor(joinBlock);
2134 if (!isAborted()) {
2135 goto(current, joinBlock);
2136 }
2137 open(joinBlock);
2138 localsHandler.mergeWith(locals, joinBlock);
2139 });
2140 HLabeledBlockInformation blockInfo =
2141 new HLabeledBlockInformation(entryBlock, firstJoinBlock,
2142 handler.labels());
2143 handler.close();
2144 // Mark both entry and exit with the information. You can
2145 // tell which one is which by comparing with blockInfo.start/end.
2146 entryBlock.labeledBlockInformation = blockInfo;
2147 firstJoinBlock.labeledBlockInformation = blockInfo;
2148 }
1969 } 2149 }
1970 2150
1971 visitLiteralMap(LiteralMap node) { 2151 visitLiteralMap(LiteralMap node) {
1972 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node); 2152 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node);
1973 } 2153 }
1974 2154
1975 visitLiteralMapEntry(LiteralMapEntry node) { 2155 visitLiteralMapEntry(LiteralMapEntry node) {
1976 compiler.unimplemented('SsaBuilder.visitLiteralMapEntry', node: node); 2156 compiler.unimplemented('SsaBuilder.visitLiteralMapEntry', node: node);
1977 } 2157 }
1978 2158
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2079 } 2259 }
2080 2260
2081 visitCatchBlock(CatchBlock node) { 2261 visitCatchBlock(CatchBlock node) {
2082 visit(node.block); 2262 visit(node.block);
2083 } 2263 }
2084 2264
2085 visitTypedef(Typedef node) { 2265 visitTypedef(Typedef node) {
2086 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); 2266 compiler.unimplemented('SsaBuilder.visitTypedef', node: node);
2087 } 2267 }
2088 } 2268 }
OLDNEW
« no previous file with comments | « frog/leg/ssa/bailout.dart ('k') | frog/leg/ssa/codegen.dart » ('j') | frog/leg/ssa/codegen.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698