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

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: Address review comments. Update expectations. 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
« no previous file with comments | « frog/leg/ssa/bailout.dart ('k') | frog/leg/ssa/codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 class 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 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 } 492 }
493 493
494 void endLoop(HBasicBlock loopEntry) { 494 void endLoop(HBasicBlock loopEntry) {
495 loopEntry.forEachPhi((HPhi phi) { 495 loopEntry.forEachPhi((HPhi phi) {
496 Element element = phi.element; 496 Element element = phi.element;
497 HInstruction postLoopDefinition = directLocals[element]; 497 HInstruction postLoopDefinition = directLocals[element];
498 phi.addInput(postLoopDefinition); 498 phi.addInput(postLoopDefinition);
499 }); 499 });
500 } 500 }
501 501
502 /**
503 * Merge [otherLocals] into this locals handler, creating phi-nodes when
504 * there is a conflict.
505 * If a phi node is necessary, it will use the otherLocals instruction as the
506 * first input, and this handler's instruction as the second.
507 * NOTICE: This means that the predecessor corresponding to [otherLocals]
508 * should be the first predecessor of the current block, and the one
509 * corresponding to this locals handler should be the second.
510 */
502 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) { 511 void mergeWith(LocalsHandler otherLocals, HBasicBlock joinBlock) {
503 // If an element is in one map but not the other we can safely 512 // If an element is in one map but not the other we can safely
504 // ignore it. It means that a variable was declared in the 513 // ignore it. It means that a variable was declared in the
505 // block. Since variable declarations are scoped the declared 514 // block. Since variable declarations are scoped the declared
506 // variable cannot be alive outside the block. Note: this is only 515 // variable cannot be alive outside the block. Note: this is only
507 // true for nodes where we do joins. 516 // true for nodes where we do joins.
508 Map<Element, HInstruction> joinedLocals = new Map<Element, HInstruction>(); 517 Map<Element, HInstruction> joinedLocals = new Map<Element, HInstruction>();
509 otherLocals.directLocals.forEach((element, instruction) { 518 otherLocals.directLocals.forEach((element, instruction) {
510 // We know 'this' cannot be modified. 519 // We know 'this' cannot be modified.
511 if (element === closureData.thisElement) { 520 if (element === closureData.thisElement) {
512 assert(directLocals[element] == instruction); 521 assert(directLocals[element] == instruction);
513 joinedLocals[element] = instruction; 522 joinedLocals[element] = instruction;
514 } else { 523 } else {
515 HInstruction mine = directLocals[element]; 524 HInstruction mine = directLocals[element];
516 if (mine === null) return; 525 if (mine === null) return;
517 if (instruction === mine) { 526 if (instruction === mine) {
518 joinedLocals[element] = instruction; 527 joinedLocals[element] = instruction;
519 } else { 528 } else {
520 HInstruction phi = new HPhi.manyInputs(element, [instruction, mine]); 529 HInstruction phi = new HPhi.manyInputs(element, [instruction, mine]);
521 joinBlock.addPhi(phi); 530 joinBlock.addPhi(phi);
522 joinedLocals[element] = phi; 531 joinedLocals[element] = phi;
523 } 532 }
524 } 533 }
525 }); 534 });
526 directLocals = joinedLocals; 535 directLocals = joinedLocals;
527 } 536 }
528 } 537 }
529 538
539
540 // Represents a single break instruction.
541 class BreakHandlerEntry {
542 final HBreak breakInstruction;
543 final LocalsHandler locals;
544 BreakHandlerEntry(this.breakInstruction, this.locals);
545 }
546
547 interface BreakHandler default BreakHandlerImpl {
548 BreakHandler(SsaBuilder builder);
549 void addTarget(StatementElement element);
550 void addBreak(HBreak breakInstruction);
551 void forEachBreak(Function action);
552 void close();
553 List<SourceString> labels();
554 }
555
556 // Inert break handler used to avoid null checks when a loop isn't
557 // used as the target of a break, and therefore doesn't need a break
558 // handler associated with it.
559 class NullBreakHandler implements BreakHandler {
560 const NullBreakHandler();
561 void addTarget(StatementElement element) { unreachable(); }
562 void addBreak(HBreak breakInstruction) { unreachable() }
563 void forEachBreak(Function ignored) { }
564 void close() { }
565 List<SourceString> labels() => const <SourceString>[];
566 }
567
568 // Records breaks until a target block is available.
569 // Breaks are always forward jumps.
570 class BreakHandlerImpl implements BreakHandler{
571 final BreakHandler previous;
572 final SsaBuilder builder;
573 final List<StatementElement> elements;
574 final List<BreakHandlerEntry> breaks;
575 BreakHandlerImpl(SsaBuilder builder)
576 : this.builder = builder,
577 previous = builder.currentBreakHandler,
578 elements = <StatementElement>[],
579 breaks = <BreakHandlerEntry>[] {
580 builder.currentBreakHandler = this;
581 }
582
583 void addTarget(StatementElement element) {
584 assert(builder.breakTargets[element] === null);
585 elements.add(element);
586 builder.breakTargets[element] = this;
587 }
588
589 void addBreak(HBreak breakInstruction,
590 LocalsHandler locals) {
591 breaks.add(new BreakHandlerEntry(breakInstruction, locals));
592 }
593
594 void forEachBreak(Function action) {
595 for (BreakHandlerEntry entry in breaks) {
596 action(entry.breakInstruction, entry.locals);
597 }
598 }
599
600 void close() {
601 assert(builder.currentBreakHandler === this);
602 // The mapping from StatementElement to BreakHandler is no longer needed.
603 for (StatementElement element in elements) {
604 assert(builder.breakTargets[element] === this);
605 builder.breakTargets.remove(element);
606 }
607 builder.currentBreakHandler = previous;
608 }
609
610 List<SourceString> labels() {
611 List<SourceString> result = null;
612 for (StatementElement element in elements) {
613 SourceString name = element.name;
614 if (!name.isEmpty()) {
615 if (result === null) result = <SourceString>[];
616 result.add(name);
617 }
618 }
619 return result === null ? const <SourceString>[] : result;
620 }
621 }
622
530 class SsaBuilder implements Visitor { 623 class SsaBuilder implements Visitor {
531 final Compiler compiler; 624 final Compiler compiler;
532 TreeElements elements; 625 TreeElements elements;
533 final Interceptors interceptors; 626 final Interceptors interceptors;
534 final WorkItem work; 627 final WorkItem work;
535 bool methodInterceptionEnabled; 628 bool methodInterceptionEnabled;
536 HGraph graph; 629 HGraph graph;
537 LocalsHandler localsHandler; 630 LocalsHandler localsHandler;
538 631
632 Map<StatementElement, BreakHandler> breakTargets;
633
539 // We build the Ssa graph by simulating a stack machine. 634 // We build the Ssa graph by simulating a stack machine.
540 List<HInstruction> stack; 635 List<HInstruction> stack;
541 636
542 // The current block to add instructions to. Might be null, if we are 637 // The current block to add instructions to. Might be null, if we are
543 // visiting dead code. 638 // visiting dead code.
544 HBasicBlock current; 639 HBasicBlock current;
545 640
641 // Linked list of active break-handlers. Will be removed in the order
642 // they are added.
643 BreakHandler currentBreakHandler = const NullBreakHandler();
644 // The break handler to use for an upcoming loop statement (temporarily set
645 // if a labeled statement is labeling a loop).
646 BreakHandler loopBreakHandler = null;
647
546 SsaBuilder(Compiler compiler, WorkItem work) 648 SsaBuilder(Compiler compiler, WorkItem work)
547 : this.compiler = compiler, 649 : this.compiler = compiler,
548 this.work = work, 650 this.work = work,
549 interceptors = compiler.builder.interceptors, 651 interceptors = compiler.builder.interceptors,
550 methodInterceptionEnabled = true, 652 methodInterceptionEnabled = true,
551 elements = work.resolutionTree, 653 elements = work.resolutionTree,
552 graph = new HGraph(), 654 graph = new HGraph(),
553 stack = new List<HInstruction>() { 655 stack = new List<HInstruction>(),
656 breakTargets = new Map<StatementElement, BreakHandler>() {
554 localsHandler = new LocalsHandler(this); 657 localsHandler = new LocalsHandler(this);
555 } 658 }
556 659
557 void disableMethodInterception() { 660 void disableMethodInterception() {
558 assert(methodInterceptionEnabled); 661 assert(methodInterceptionEnabled);
559 methodInterceptionEnabled = false; 662 methodInterceptionEnabled = false;
560 } 663 }
561 664
562 void enableMethodInterception() { 665 void enableMethodInterception() {
563 assert(!methodInterceptionEnabled); 666 assert(!methodInterceptionEnabled);
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 visitExpressionStatement(ExpressionStatement node) { 946 visitExpressionStatement(ExpressionStatement node) {
844 visit(node.expression); 947 visit(node.expression);
845 pop(); 948 pop();
846 } 949 }
847 950
848 /** 951 /**
849 * Creates a new loop-header block. The previous [current] block 952 * Creates a new loop-header block. The previous [current] block
850 * is closed with an [HGoto] and replaced by the newly created block. 953 * is closed with an [HGoto] and replaced by the newly created block.
851 * Also notifies the locals handler that we're entering a loop. 954 * Also notifies the locals handler that we're entering a loop.
852 */ 955 */
853 void beginLoopHeader(Node node) { 956 BreakHandler beginLoopHeader(Node node) {
854 assert(!isAborted()); 957 assert(!isAborted());
855 HBasicBlock previousBlock = close(new HGoto()); 958 HBasicBlock previousBlock = close(new HGoto());
856 959 BreakHandler breakHandler = getLoopBreakHandler(node);
857 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(); 960 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(breakHandler.labels());
858 previousBlock.addSuccessor(loopEntry); 961 previousBlock.addSuccessor(loopEntry);
859 open(loopEntry); 962 open(loopEntry);
860 963
861 localsHandler.beginLoopHeader(node, loopEntry); 964 localsHandler.beginLoopHeader(node, loopEntry);
965 return breakHandler;
862 } 966 }
863 967
864 /** 968 /**
865 * Ends the loop: 969 * Ends the loop:
866 * - creates a new block and adds it as successor to the [branchBlock]. 970 * - creates a new block and adds it as successor to the [branchBlock].
867 * - opens the new block (setting as [current]). 971 * - opens the new block (setting as [current]).
868 * - notifies the locals handler that we're exiting a loop. 972 * - notifies the locals handler that we're exiting a loop.
869 */ 973 */
870 void endLoop(HBasicBlock loopEntry, HBasicBlock branchBlock) { 974 void endLoop(HBasicBlock loopEntry,
975 HBasicBlock branchBlock,
976 BreakHandler breakHandler) {
871 HBasicBlock loopExitBlock = addNewBlock(); 977 HBasicBlock loopExitBlock = addNewBlock();
872 assert(branchBlock.successors.length == 1); 978 assert(branchBlock.successors.length == 1);
873 branchBlock.addSuccessor(loopExitBlock); 979 branchBlock.addSuccessor(loopExitBlock);
874 open(loopExitBlock); 980 open(loopExitBlock);
875 localsHandler.endLoop(loopEntry); 981 localsHandler.endLoop(loopEntry);
982 breakHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
983 HBasicBlock joinBlock = addNewBlock();
984 breakInstruction.block.addSuccessor(joinBlock);
985 goto(current, joinBlock);
986 open(joinBlock);
987 localsHandler.mergeWith(locals, joinBlock);
988 });
876 } 989 }
877 990
878 // For while loops, initializer and update are null. 991 // For while loops, initializer and update are null.
879 visitLoop(Node loop, Node initializer, Expression condition, NodeList updates, 992 visitLoop(Node loop, Node initializer, Expression condition, NodeList updates,
880 Node body) { 993 Node body) {
881 // Generate: 994 // Generate:
882 // <initializer> 995 // <initializer>
883 // loop-entry: 996 // loop-entry:
884 // if (!<condition>) goto loop-exit; 997 // if (!<condition>) goto loop-exit;
885 // <body> 998 // <body>
886 // <updates> 999 // <updates>
887 // goto loop-entry; 1000 // goto loop-entry;
888 // loop-exit: 1001 // loop-exit:
889 if (condition === null || body === null) { 1002 if (condition === null || body === null) {
890 compiler.unimplemented( 1003 compiler.unimplemented(
891 'SsaBuilder.visitLoop with empty condition or body', 1004 'SsaBuilder.visitLoop with empty condition or body',
892 node: loop); 1005 node: loop);
893 } 1006 }
894 1007
895 localsHandler.startLoop(loop); 1008 localsHandler.startLoop(loop);
896 1009
897 // The initializer. 1010 // The initializer.
898 if (initializer !== null) { 1011 if (initializer !== null) {
899 visit(initializer); 1012 visit(initializer);
900 // We don't care about the value of the initialization. 1013 // We don't care about the value of the initialization.
901 if (initializer.asExpression() !== null) pop(); 1014 if (initializer.asExpression() !== null) pop();
902 } 1015 }
903 assert(!isAborted()); 1016 assert(!isAborted());
904 1017
905 beginLoopHeader(loop); 1018 BreakHandler breakHandler = beginLoopHeader(loop);
906 HBasicBlock conditionBlock = current; 1019 HBasicBlock conditionBlock = current;
907 1020
908 // The condition. 1021 // The condition.
909 visit(condition); 1022 visit(condition);
910 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified())); 1023 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified()));
911 1024
912 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 1025 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
913 1026
914 // The body. 1027 // The body.
915 HBasicBlock bodyBlock = addNewBlock(); 1028 HBasicBlock bodyBlock = addNewBlock();
(...skipping 24 matching lines...) Expand all
940 // The result of the update instruction isn't used, and can just 1053 // The result of the update instruction isn't used, and can just
941 // be dropped. 1054 // be dropped.
942 HInstruction updateInstruction = pop(); 1055 HInstruction updateInstruction = pop();
943 } 1056 }
944 } 1057 }
945 updateBlock = close(new HGoto()); 1058 updateBlock = close(new HGoto());
946 // The back-edge completing the cycle. 1059 // The back-edge completing the cycle.
947 updateBlock.addSuccessor(conditionBlock); 1060 updateBlock.addSuccessor(conditionBlock);
948 conditionBlock.postProcessLoopHeader(); 1061 conditionBlock.postProcessLoopHeader();
949 1062
950 endLoop(conditionBlock, conditionExitBlock); 1063 endLoop(conditionBlock, conditionExitBlock, breakHandler);
951 localsHandler = savedLocals; 1064 localsHandler = savedLocals;
952 } 1065 }
953 1066
954 visitFor(For node) { 1067 visitFor(For node) {
955 if (node.condition === null) { 1068 if (node.condition === null) {
956 compiler.unimplemented("SsaBuilder for loop without condition"); 1069 compiler.unimplemented("SsaBuilder for loop without condition");
957 } 1070 }
958 assert(node.body !== null); 1071 assert(node.body !== null);
959 visitLoop(node, node.initializer, node.condition, node.update, node.body); 1072 visitLoop(node, node.initializer, node.condition, node.update, node.body);
960 } 1073 }
961 1074
962 visitWhile(While node) { 1075 visitWhile(While node) {
963 visitLoop(node, null, node.condition, null, node.body); 1076 visitLoop(node, null, node.condition, null, node.body);
964 } 1077 }
965 1078
966 visitDoWhile(DoWhile node) { 1079 visitDoWhile(DoWhile node) {
967 localsHandler.startLoop(node); 1080 localsHandler.startLoop(node);
968 beginLoopHeader(node); 1081 BreakHandler breakHandler = beginLoopHeader(node);
969 HBasicBlock loopEntryBlock = current; 1082 HBasicBlock loopEntryBlock = current;
970 1083
971 localsHandler.enterLoopBody(node); 1084 localsHandler.enterLoopBody(node);
972 visit(node.body); 1085 visit(node.body);
973 if (isAborted()) { 1086 if (isAborted()) {
974 compiler.unimplemented("SsaBuilder for loop with aborting body"); 1087 compiler.unimplemented("SsaBuilder for loop with aborting body");
975 } 1088 }
976 1089
977 // If there are no continues we could avoid the creation of the condition 1090 // If there are no continues we could avoid the creation of the condition
978 // block. This could also lead to a block having multiple entries and exits. 1091 // block. This could also lead to a block having multiple entries and exits.
979 HBasicBlock bodyExitBlock = close(new HGoto()); 1092 HBasicBlock bodyExitBlock = close(new HGoto());
980 HBasicBlock conditionBlock = addNewBlock(); 1093 HBasicBlock conditionBlock = addNewBlock();
981 bodyExitBlock.addSuccessor(conditionBlock); 1094 bodyExitBlock.addSuccessor(conditionBlock);
982 open(conditionBlock); 1095 open(conditionBlock);
983 visit(node.condition); 1096 visit(node.condition);
984 assert(!isAborted()); 1097 assert(!isAborted());
985 conditionBlock = close(new HLoopBranch(popBoolified())); 1098 conditionBlock = close(new HLoopBranch(popBoolified()));
986 1099
987 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge. 1100 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge.
988 loopEntryBlock.postProcessLoopHeader(); 1101 loopEntryBlock.postProcessLoopHeader();
989 1102
990 endLoop(loopEntryBlock, conditionBlock); 1103 endLoop(loopEntryBlock, conditionBlock, breakHandler);
991 } 1104 }
992 1105
993 visitFunctionExpression(FunctionExpression node) { 1106 visitFunctionExpression(FunctionExpression node) {
994 ClosureData nestedClosureData = closureDataCache[node]; 1107 ClosureData nestedClosureData = closureDataCache[node];
995 assert(nestedClosureData !== null); 1108 assert(nestedClosureData !== null);
996 assert(nestedClosureData.closureClassElement !== null); 1109 assert(nestedClosureData.closureClassElement !== null);
997 ClassElement closureClassElement = 1110 ClassElement closureClassElement =
998 nestedClosureData.closureClassElement; 1111 nestedClosureData.closureClassElement;
999 FunctionElement callElement = nestedClosureData.callElement; 1112 FunctionElement callElement = nestedClosureData.callElement;
1000 compiler.enqueue(new WorkItem.toCodegen(callElement, elements)); 1113 compiler.enqueue(new WorkItem.toCodegen(callElement, elements));
(...skipping 889 matching lines...) Expand 10 before | Expand all | Expand 10 after
1890 2003
1891 visitEmptyStatement(EmptyStatement node) { 2004 visitEmptyStatement(EmptyStatement node) {
1892 // Do nothing, empty statement. 2005 // Do nothing, empty statement.
1893 } 2006 }
1894 2007
1895 visitModifiers(Modifiers node) { 2008 visitModifiers(Modifiers node) {
1896 compiler.unimplemented('SsaBuilder.visitModifiers', node: node); 2009 compiler.unimplemented('SsaBuilder.visitModifiers', node: node);
1897 } 2010 }
1898 2011
1899 visitBreakStatement(BreakStatement node) { 2012 visitBreakStatement(BreakStatement node) {
1900 compiler.unimplemented('SsaBuilder.visitBreakStatement', node: node); 2013 work.allowSpeculativeOptimization = false;
2014 assert(!isAborted());
2015 StatementElement target = elements[node];
2016 assert(target !== null);
2017 BreakHandler handler = breakTargets[target];
2018 assert(handler !== null);
2019 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2020 HBreak breakInstruction;
2021 if (node.target === null) {
2022 breakInstruction = new HBreak();
2023 } else {
2024 breakInstruction = new HBreak(node.target.source);
2025 }
2026 close(breakInstruction);
2027 handler.addBreak(breakInstruction, savedLocals);
1901 } 2028 }
1902 2029
1903 visitContinueStatement(ContinueStatement node) { 2030 visitContinueStatement(ContinueStatement node) {
1904 compiler.unimplemented('SsaBuilder.visitContinueStatement', node: node); 2031 compiler.unimplemented('SsaBuilder.visitContinueStatement', node: node);
1905 } 2032 }
1906 2033
2034 BreakHandler getLoopBreakHandler(Loop node) {
2035 StatementElement element = elements[node];
2036 BreakHandler handler;
2037 if (loopBreakHandler === null) {
2038 if (element === null) return const NullBreakHandler();
2039 handler = new BreakHandler(this);
2040 } else {
2041 handler = loopBreakHandler;
2042 loopBreakHandler = null;
2043 if (element === null) return handler;
2044 }
2045 handler.addTarget(element);
2046 return handler;
2047 }
2048
1907 visitForInStatement(ForInStatement node) { 2049 visitForInStatement(ForInStatement node) {
1908 // Generate a structure equivalent to: 2050 // Generate a structure equivalent to:
1909 // Iterator<E> $iter = <iterable>.iterator() 2051 // Iterator<E> $iter = <iterable>.iterator()
1910 // while ($iter.hasNext()) { 2052 // while ($iter.hasNext()) {
1911 // E <declaredIdentifier> = $iter.next(); 2053 // E <declaredIdentifier> = $iter.next();
1912 // <body> 2054 // <body>
1913 // } 2055 // }
1914 localsHandler.startLoop(node); 2056 localsHandler.startLoop(node);
1915 2057
1916 SourceString iteratorName = const SourceString("iterator"); 2058 SourceString iteratorName = const SourceString("iterator");
1917 2059
1918 Selector selector = Selector.INVOCATION_0; 2060 Selector selector = Selector.INVOCATION_0;
1919 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0); 2061 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0);
1920 assert(interceptor != null); 2062 assert(interceptor != null);
1921 HStatic target = new HStatic(interceptor); 2063 HStatic target = new HStatic(interceptor);
1922 add(target); 2064 add(target);
1923 visit(node.expression); 2065 visit(node.expression);
1924 List<HInstruction> inputs = <HInstruction>[target, pop()]; 2066 List<HInstruction> inputs = <HInstruction>[target, pop()];
1925 HInstruction iterator = new HInvokeInterceptor( 2067 HInstruction iterator = new HInvokeInterceptor(
1926 selector, iteratorName, false, inputs); 2068 selector, iteratorName, false, inputs);
1927 add(iterator); 2069 add(iterator);
1928 2070
1929 beginLoopHeader(node); 2071 BreakHandler breakHandler = beginLoopHeader(node);
1930 HBasicBlock conditionBlock = current; 2072 HBasicBlock conditionBlock = current;
1931 2073
1932 // The condition. 2074 // The condition.
1933 push(new HInvokeDynamicMethod( 2075 push(new HInvokeDynamicMethod(
1934 selector, const SourceString('hasNext'), [iterator])); 2076 selector, const SourceString('hasNext'), [iterator]));
1935 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified())); 2077 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified()));
1936 2078
1937 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 2079 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
1938 2080
1939 // The body. 2081 // The body.
(...skipping 29 matching lines...) Expand all
1969 // update block is the jump-target for continue statements. We could avoid 2111 // update block is the jump-target for continue statements. We could avoid
1970 // the creation if there is no continue, but for now we always create it. 2112 // the creation if there is no continue, but for now we always create it.
1971 HBasicBlock updateBlock = addNewBlock(); 2113 HBasicBlock updateBlock = addNewBlock();
1972 bodyBlock.addSuccessor(updateBlock); 2114 bodyBlock.addSuccessor(updateBlock);
1973 open(updateBlock); 2115 open(updateBlock);
1974 updateBlock = close(new HGoto()); 2116 updateBlock = close(new HGoto());
1975 // The back-edge completing the cycle. 2117 // The back-edge completing the cycle.
1976 updateBlock.addSuccessor(conditionBlock); 2118 updateBlock.addSuccessor(conditionBlock);
1977 conditionBlock.postProcessLoopHeader(); 2119 conditionBlock.postProcessLoopHeader();
1978 2120
1979 endLoop(conditionBlock, conditionExitBlock); 2121 endLoop(conditionBlock, conditionExitBlock, breakHandler);
1980 localsHandler = savedLocals; 2122 localsHandler = savedLocals;
2123 breakHandler.close();
1981 } 2124 }
1982 2125
1983 visitLabelledStatement(LabelledStatement node) { 2126 visitLabelledStatement(LabelledStatement node) {
1984 compiler.unimplemented('SsaBuilder.visitLabelledStatement', node: node); 2127 BreakHandler handler = null;
2128 Node currentNode = node;
2129 do {
2130 StatementElement element = elements[currentNode];
2131 if (element !== null && element.isBreakTarget) {
2132 if (handler === null) handler = new BreakHandler(this);
2133 handler.addTarget(element);
2134 }
2135 currentNode = currentNode.statement;
2136 } while (currentNode is LabelledStatement);
2137 if (handler === null) {
2138 // The labels are not break targets.
2139 visit(currentNode);
2140 } else if (currentNode is Loop || currentNode is SwitchStatement) {
2141 // The labels apply to that statement, and will be handled there.
2142 loopBreakHandler = handler;
2143 visit(currentNode);
2144 assert(loopBreakHandler === null);
2145 } else {
2146 // Introduce a new basic block.
2147 HBasicBlock entryBlock = graph.addNewBlock();
2148 goto(current, entryBlock);
2149 open(entryBlock);
2150 visit(currentNode);
2151 if (isAborted()) {
2152 compiler.unimplemented(
2153 "SsaBuilder for labeled statement with aborting body", node: node);
2154 }
2155 HBasicBlock exitBlock = current;
2156 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
2157 HBasicBlock joinBlock = graph.addNewBlock();
2158 breakInstruction.block.addSuccessor(joinBlock);
2159 if (!isAborted()) {
2160 goto(current, joinBlock);
2161 open(joinBlock);
2162 localsHandler.mergeWith(locals, joinBlock);
2163 } else {
2164 open(joinBlock);
2165 localsHandler = locals;
2166 }
2167 });
2168 if (current !== exitBlock) {
2169 // There was at least one reachable break, so the label is needed.
2170 HLabeledBlockInformation blockInfo =
2171 new HLabeledBlockInformation(entryBlock, current,
2172 handler.labels());
2173 handler.close();
2174 entryBlock.labeledBlockInformation = blockInfo;
2175 // Mark both entry and exit with the information. You can
2176 // tell which one is which by comparing with blockInfo.start/end.
2177 // It doesn't matter which merge block we use, they won't be generating
2178 // any code, so put the end-marker on the last join block.
2179 current.labeledBlockInformation = blockInfo;
2180 }
2181 }
1985 } 2182 }
1986 2183
1987 visitLiteralMap(LiteralMap node) { 2184 visitLiteralMap(LiteralMap node) {
1988 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node); 2185 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node);
1989 } 2186 }
1990 2187
1991 visitLiteralMapEntry(LiteralMapEntry node) { 2188 visitLiteralMapEntry(LiteralMapEntry node) {
1992 compiler.unimplemented('SsaBuilder.visitLiteralMapEntry', node: node); 2189 compiler.unimplemented('SsaBuilder.visitLiteralMapEntry', node: node);
1993 } 2190 }
1994 2191
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
2092 } 2289 }
2093 2290
2094 visitCatchBlock(CatchBlock node) { 2291 visitCatchBlock(CatchBlock node) {
2095 visit(node.block); 2292 visit(node.block);
2096 } 2293 }
2097 2294
2098 visitTypedef(Typedef node) { 2295 visitTypedef(Typedef node) {
2099 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); 2296 compiler.unimplemented('SsaBuilder.visitTypedef', node: node);
2100 } 2297 }
2101 } 2298 }
OLDNEW
« no previous file with comments | « frog/leg/ssa/bailout.dart ('k') | frog/leg/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698