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

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. 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 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(SsaBuilder builder);
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 BreakHandler previous;
566 final SsaBuilder builder;
567 final List<StatementElement> elements;
568 final List<BreakHandlerEntry> breaks;
569 BreakHandlerImpl(SsaBuilder builder)
570 : this.builder = builder,
571 previous = builder.currentBreakHandler,
572 elements = <StatementElement>[],
573 breaks = <BreakHandlerEntry>[] {
574 builder.currentBreakHandler = this;
575 }
576
577 void addTarget(StatementElement element) {
578 assert(builder.breakTargets[element] === null);
579 elements.add(element);
580 builder.breakTargets[element] = this;
581 }
582
583 void addBreak(HBreak breakInstruction,
584 LocalsHandler locals) {
585 breaks.add(new BreakHandlerEntry(breakInstruction, locals));
586 }
587
588 void forEachBreak(Function action) {
589 for (BreakHandlerEntry entry in breaks) {
590 action(entry.breakInstruction, entry.locals);
591 }
592 }
593
594 void close() {
595 assert(builder.currentBreakHandler === this);
596 // The mapping from StatementElement to BreakHandler is no longer needed.
597 for (StatementElement element in elements) {
598 assert(builder.breakTargets[element] === this);
599 builder.breakTargets.remove(element);
600 }
601 builder.currentBreakHandler = previous;
602 }
603
604 List<SourceString> labels() {
605 List<SourceString> result = null;
606 for (StatementElement element in elements) {
607 SourceString name = element.name;
608 if (!name.isEmpty()) {
609 if (result === null) result = <SourceString>[];
610 result.add(name);
611 }
612 }
613 return result === null ? const <SourceString>[] : result;
614 }
615 }
616
524 class SsaBuilder implements Visitor { 617 class SsaBuilder implements Visitor {
525 final Compiler compiler; 618 final Compiler compiler;
526 TreeElements elements; 619 TreeElements elements;
527 final Interceptors interceptors; 620 final Interceptors interceptors;
528 final WorkItem work; 621 final WorkItem work;
529 bool methodInterceptionEnabled; 622 bool methodInterceptionEnabled;
530 HGraph graph; 623 HGraph graph;
531 LocalsHandler localsHandler; 624 LocalsHandler localsHandler;
532 625
626 Map<StatementElement, BreakHandler> breakTargets;
627
533 // We build the Ssa graph by simulating a stack machine. 628 // We build the Ssa graph by simulating a stack machine.
534 List<HInstruction> stack; 629 List<HInstruction> stack;
535 630
536 // The current block to add instructions to. Might be null, if we are 631 // The current block to add instructions to. Might be null, if we are
537 // visiting dead code. 632 // visiting dead code.
538 HBasicBlock current; 633 HBasicBlock current;
539 634
635 // Linked list of active break-handlers. Will be removed in the order
636 // they are added.
637 BreakHandler currentBreakHandler = const NullBreakHandler();
638 // The break handler to use for an upcoming loop statement (temporarily set
639 // if a labeled statement is labeling a loop).
640 BreakHandler loopBreakHandler = null;
641
540 SsaBuilder(Compiler compiler, WorkItem work) 642 SsaBuilder(Compiler compiler, WorkItem work)
541 : this.compiler = compiler, 643 : this.compiler = compiler,
542 this.work = work, 644 this.work = work,
543 interceptors = compiler.builder.interceptors, 645 interceptors = compiler.builder.interceptors,
544 methodInterceptionEnabled = true, 646 methodInterceptionEnabled = true,
545 elements = work.resolutionTree, 647 elements = work.resolutionTree,
546 graph = new HGraph(), 648 graph = new HGraph(),
547 stack = new List<HInstruction>() { 649 stack = new List<HInstruction>(),
650 breakTargets = new Map<StatementElement, BreakHandler>() {
548 localsHandler = new LocalsHandler(this); 651 localsHandler = new LocalsHandler(this);
549 } 652 }
550 653
551 void disableMethodInterception() { 654 void disableMethodInterception() {
552 assert(methodInterceptionEnabled); 655 assert(methodInterceptionEnabled);
553 methodInterceptionEnabled = false; 656 methodInterceptionEnabled = false;
554 } 657 }
555 658
556 void enableMethodInterception() { 659 void enableMethodInterception() {
557 assert(!methodInterceptionEnabled); 660 assert(!methodInterceptionEnabled);
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 visitExpressionStatement(ExpressionStatement node) { 943 visitExpressionStatement(ExpressionStatement node) {
841 visit(node.expression); 944 visit(node.expression);
842 pop(); 945 pop();
843 } 946 }
844 947
845 /** 948 /**
846 * Creates a new loop-header block. The previous [current] block 949 * Creates a new loop-header block. The previous [current] block
847 * is closed with an [HGoto] and replaced by the newly created block. 950 * is closed with an [HGoto] and replaced by the newly created block.
848 * Also notifies the locals handler that we're entering a loop. 951 * Also notifies the locals handler that we're entering a loop.
849 */ 952 */
850 void beginLoopHeader(Node node) { 953 BreakHandler beginLoopHeader(Node node) {
851 assert(!isAborted()); 954 assert(!isAborted());
852 HBasicBlock previousBlock = close(new HGoto()); 955 HBasicBlock previousBlock = close(new HGoto());
853 956 BreakHandler breakHandler = getLoopBreakHandler(node);
854 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(); 957 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(breakHandler.labels());
855 previousBlock.addSuccessor(loopEntry); 958 previousBlock.addSuccessor(loopEntry);
856 open(loopEntry); 959 open(loopEntry);
857 960
858 localsHandler.beginLoopHeader(node, loopEntry); 961 localsHandler.beginLoopHeader(node, loopEntry);
962 return breakHandler;
859 } 963 }
860 964
861 /** 965 /**
862 * Ends the loop: 966 * Ends the loop:
863 * - creates a new block and adds it as successor to the [branchBlock]. 967 * - creates a new block and adds it as successor to the [branchBlock].
864 * - opens the new block (setting as [current]). 968 * - opens the new block (setting as [current]).
865 * - notifies the locals handler that we're exiting a loop. 969 * - notifies the locals handler that we're exiting a loop.
866 */ 970 */
867 void endLoop(HBasicBlock loopEntry, HBasicBlock branchBlock) { 971 void endLoop(HBasicBlock loopEntry,
972 HBasicBlock branchBlock,
973 BreakHandler breakHandler) {
868 HBasicBlock loopExitBlock = addNewBlock(); 974 HBasicBlock loopExitBlock = addNewBlock();
869 assert(branchBlock.successors.length == 1); 975 assert(branchBlock.successors.length == 1);
870 branchBlock.addSuccessor(loopExitBlock); 976 branchBlock.addSuccessor(loopExitBlock);
871 open(loopExitBlock); 977 open(loopExitBlock);
872 localsHandler.endLoop(loopEntry); 978 localsHandler.endLoop(loopEntry);
979 breakHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
980 HBasicBlock joinBlock = addNewBlock();
981 breakInstruction.block.addSuccessor(joinBlock);
982 goto(current, joinBlock);
983 open(joinBlock);
984 localsHandler.mergeWith(locals, joinBlock);
985 });
873 } 986 }
874 987
875 // For while loops, initializer and update are null. 988 // For while loops, initializer and update are null.
876 visitLoop(Node loop, Node initializer, Expression condition, NodeList updates, 989 visitLoop(Node loop, Node initializer, Expression condition, NodeList updates,
877 Node body) { 990 Node body) {
878 // Generate: 991 // Generate:
879 // <initializer> 992 // <initializer>
880 // loop-entry: 993 // loop-entry:
881 // if (!<condition>) goto loop-exit; 994 // if (!<condition>) goto loop-exit;
882 // <body> 995 // <body>
883 // <updates> 996 // <updates>
884 // goto loop-entry; 997 // goto loop-entry;
885 // loop-exit: 998 // loop-exit:
886 if (condition === null || body === null) { 999 if (condition === null || body === null) {
887 compiler.unimplemented( 1000 compiler.unimplemented(
888 'SsaBuilder.visitLoop with empty condition or body', 1001 'SsaBuilder.visitLoop with empty condition or body',
889 node: loop); 1002 node: loop);
890 } 1003 }
891 1004
892 localsHandler.startLoop(loop); 1005 localsHandler.startLoop(loop);
893 1006
894 // The initializer. 1007 // The initializer.
895 if (initializer !== null) { 1008 if (initializer !== null) {
896 visit(initializer); 1009 visit(initializer);
897 // We don't care about the value of the initialization. 1010 // We don't care about the value of the initialization.
898 if (initializer.asExpression() !== null) pop(); 1011 if (initializer.asExpression() !== null) pop();
899 } 1012 }
900 assert(!isAborted()); 1013 assert(!isAborted());
901 1014
902 beginLoopHeader(loop); 1015 BreakHandler breakHandler = beginLoopHeader(loop);
903 HBasicBlock conditionBlock = current; 1016 HBasicBlock conditionBlock = current;
904 1017
905 // The condition. 1018 // The condition.
906 visit(condition); 1019 visit(condition);
907 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified())); 1020 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified()));
908 1021
909 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 1022 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
910 1023
911 // The body. 1024 // The body.
912 HBasicBlock bodyBlock = addNewBlock(); 1025 HBasicBlock bodyBlock = addNewBlock();
(...skipping 24 matching lines...) Expand all
937 // The result of the update instruction isn't used, and can just 1050 // The result of the update instruction isn't used, and can just
938 // be dropped. 1051 // be dropped.
939 HInstruction updateInstruction = pop(); 1052 HInstruction updateInstruction = pop();
940 } 1053 }
941 } 1054 }
942 updateBlock = close(new HGoto()); 1055 updateBlock = close(new HGoto());
943 // The back-edge completing the cycle. 1056 // The back-edge completing the cycle.
944 updateBlock.addSuccessor(conditionBlock); 1057 updateBlock.addSuccessor(conditionBlock);
945 conditionBlock.postProcessLoopHeader(); 1058 conditionBlock.postProcessLoopHeader();
946 1059
947 endLoop(conditionBlock, conditionExitBlock); 1060 endLoop(conditionBlock, conditionExitBlock, breakHandler);
948 localsHandler = savedLocals; 1061 localsHandler = savedLocals;
949 } 1062 }
950 1063
951 visitFor(For node) { 1064 visitFor(For node) {
952 if (node.condition === null) { 1065 if (node.condition === null) {
953 compiler.unimplemented("SsaBuilder for loop without condition"); 1066 compiler.unimplemented("SsaBuilder for loop without condition");
954 } 1067 }
955 assert(node.body !== null); 1068 assert(node.body !== null);
956 visitLoop(node, node.initializer, node.condition, node.update, node.body); 1069 visitLoop(node, node.initializer, node.condition, node.update, node.body);
957 } 1070 }
958 1071
959 visitWhile(While node) { 1072 visitWhile(While node) {
960 visitLoop(node, null, node.condition, null, node.body); 1073 visitLoop(node, null, node.condition, null, node.body);
961 } 1074 }
962 1075
963 visitDoWhile(DoWhile node) { 1076 visitDoWhile(DoWhile node) {
964 localsHandler.startLoop(node); 1077 localsHandler.startLoop(node);
965 beginLoopHeader(node); 1078 BreakHandler breakHandler = beginLoopHeader(node);
966 HBasicBlock loopEntryBlock = current; 1079 HBasicBlock loopEntryBlock = current;
967 1080
968 localsHandler.enterLoopBody(node); 1081 localsHandler.enterLoopBody(node);
969 visit(node.body); 1082 visit(node.body);
970 if (isAborted()) { 1083 if (isAborted()) {
971 compiler.unimplemented("SsaBuilder for loop with aborting body"); 1084 compiler.unimplemented("SsaBuilder for loop with aborting body");
972 } 1085 }
973 1086
974 // If there are no continues we could avoid the creation of the condition 1087 // 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. 1088 // block. This could also lead to a block having multiple entries and exits.
976 HBasicBlock bodyExitBlock = close(new HGoto()); 1089 HBasicBlock bodyExitBlock = close(new HGoto());
977 HBasicBlock conditionBlock = addNewBlock(); 1090 HBasicBlock conditionBlock = addNewBlock();
978 bodyExitBlock.addSuccessor(conditionBlock); 1091 bodyExitBlock.addSuccessor(conditionBlock);
979 open(conditionBlock); 1092 open(conditionBlock);
980 visit(node.condition); 1093 visit(node.condition);
981 assert(!isAborted()); 1094 assert(!isAborted());
982 conditionBlock = close(new HLoopBranch(popBoolified())); 1095 conditionBlock = close(new HLoopBranch(popBoolified()));
983 1096
984 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge. 1097 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge.
985 loopEntryBlock.postProcessLoopHeader(); 1098 loopEntryBlock.postProcessLoopHeader();
986 1099
987 endLoop(loopEntryBlock, conditionBlock); 1100 endLoop(loopEntryBlock, conditionBlock, breakHandler);
988 } 1101 }
989 1102
990 visitFunctionExpression(FunctionExpression node) { 1103 visitFunctionExpression(FunctionExpression node) {
991 ClosureData nestedClosureData = closureDataCache[node]; 1104 ClosureData nestedClosureData = closureDataCache[node];
992 assert(nestedClosureData !== null); 1105 assert(nestedClosureData !== null);
993 assert(nestedClosureData.closureClassElement !== null); 1106 assert(nestedClosureData.closureClassElement !== null);
994 ClassElement closureClassElement = 1107 ClassElement closureClassElement =
995 nestedClosureData.closureClassElement; 1108 nestedClosureData.closureClassElement;
996 FunctionElement callElement = nestedClosureData.callElement; 1109 FunctionElement callElement = nestedClosureData.callElement;
997 compiler.enqueue(new WorkItem.toCodegen(callElement, elements)); 1110 compiler.enqueue(new WorkItem.toCodegen(callElement, elements));
(...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after
1874 visitEmptyStatement(EmptyStatement node) { 1987 visitEmptyStatement(EmptyStatement node) {
1875 compiler.unimplemented('SsaBuilder.visitEmptyStatement', 1988 compiler.unimplemented('SsaBuilder.visitEmptyStatement',
1876 node: node); 1989 node: node);
1877 } 1990 }
1878 1991
1879 visitModifiers(Modifiers node) { 1992 visitModifiers(Modifiers node) {
1880 compiler.unimplemented('SsaBuilder.visitModifiers', node: node); 1993 compiler.unimplemented('SsaBuilder.visitModifiers', node: node);
1881 } 1994 }
1882 1995
1883 visitBreakStatement(BreakStatement node) { 1996 visitBreakStatement(BreakStatement node) {
1884 compiler.unimplemented('SsaBuilder.visitBreakStatement', node: node); 1997 work.allowSpeculativeOptimization = false;
1998 assert(!isAborted());
1999 StatementElement target = elements[node];
2000 assert(target !== null);
2001 BreakHandler handler = breakTargets[target];
2002 assert(handler !== null);
2003 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2004 HBreak breakInstruction;
2005 if (node.target === null) {
2006 breakInstruction = new HBreak();
2007 } else {
2008 breakInstruction = new HBreak(node.target.source);
2009 }
2010 close(breakInstruction);
2011 handler.addBreak(breakInstruction, savedLocals);
1885 } 2012 }
1886 2013
1887 visitContinueStatement(ContinueStatement node) { 2014 visitContinueStatement(ContinueStatement node) {
1888 compiler.unimplemented('SsaBuilder.visitContinueStatement', node: node); 2015 compiler.unimplemented('SsaBuilder.visitContinueStatement', node: node);
1889 } 2016 }
1890 2017
2018 BreakHandler getLoopBreakHandler(Loop node) {
2019 StatementElement element = elements[node];
2020 BreakHandler handler;
2021 if (loopBreakHandler === null) {
2022 if (element === null) return const NullBreakHandler();
2023 handler = new BreakHandler(this);
2024 } else {
2025 handler = loopBreakHandler;
2026 loopBreakHandler = null;
2027 if (element === null) return handler;
2028 }
2029 handler.addTarget(element);
2030 return handler;
2031 }
2032
1891 visitForInStatement(ForInStatement node) { 2033 visitForInStatement(ForInStatement node) {
1892 // Generate a structure equivalent to: 2034 // Generate a structure equivalent to:
1893 // Iterator<E> $iter = <iterable>.iterator() 2035 // Iterator<E> $iter = <iterable>.iterator()
1894 // while ($iter.hasNext()) { 2036 // while ($iter.hasNext()) {
1895 // E <declaredIdentifier> = $iter.next(); 2037 // E <declaredIdentifier> = $iter.next();
1896 // <body> 2038 // <body>
1897 // } 2039 // }
1898 localsHandler.startLoop(node); 2040 localsHandler.startLoop(node);
1899 2041
1900 SourceString iteratorName = const SourceString("iterator"); 2042 SourceString iteratorName = const SourceString("iterator");
1901 2043
1902 Selector selector = Selector.INVOCATION_0; 2044 Selector selector = Selector.INVOCATION_0;
1903 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0); 2045 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0);
1904 assert(interceptor != null); 2046 assert(interceptor != null);
1905 HStatic target = new HStatic(interceptor); 2047 HStatic target = new HStatic(interceptor);
1906 add(target); 2048 add(target);
1907 visit(node.expression); 2049 visit(node.expression);
1908 List<HInstruction> inputs = <HInstruction>[target, pop()]; 2050 List<HInstruction> inputs = <HInstruction>[target, pop()];
1909 HInstruction iterator = new HInvokeInterceptor( 2051 HInstruction iterator = new HInvokeInterceptor(
1910 selector, iteratorName, false, inputs); 2052 selector, iteratorName, false, inputs);
1911 add(iterator); 2053 add(iterator);
1912 2054
1913 beginLoopHeader(node); 2055 BreakHandler breakHandler = beginLoopHeader(node);
1914 HBasicBlock conditionBlock = current; 2056 HBasicBlock conditionBlock = current;
1915 2057
1916 // The condition. 2058 // The condition.
1917 push(new HInvokeDynamicMethod( 2059 push(new HInvokeDynamicMethod(
1918 selector, const SourceString('hasNext'), [iterator])); 2060 selector, const SourceString('hasNext'), [iterator]));
1919 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified())); 2061 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified()));
1920 2062
1921 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 2063 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
1922 2064
1923 // The body. 2065 // The body.
(...skipping 29 matching lines...) Expand all
1953 // update block is the jump-target for continue statements. We could avoid 2095 // 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. 2096 // the creation if there is no continue, but for now we always create it.
1955 HBasicBlock updateBlock = addNewBlock(); 2097 HBasicBlock updateBlock = addNewBlock();
1956 bodyBlock.addSuccessor(updateBlock); 2098 bodyBlock.addSuccessor(updateBlock);
1957 open(updateBlock); 2099 open(updateBlock);
1958 updateBlock = close(new HGoto()); 2100 updateBlock = close(new HGoto());
1959 // The back-edge completing the cycle. 2101 // The back-edge completing the cycle.
1960 updateBlock.addSuccessor(conditionBlock); 2102 updateBlock.addSuccessor(conditionBlock);
1961 conditionBlock.postProcessLoopHeader(); 2103 conditionBlock.postProcessLoopHeader();
1962 2104
1963 endLoop(conditionBlock, conditionExitBlock); 2105 endLoop(conditionBlock, conditionExitBlock, breakHandler);
1964 localsHandler = savedLocals; 2106 localsHandler = savedLocals;
2107 breakHandler.close();
1965 } 2108 }
1966 2109
1967 visitLabelledStatement(LabelledStatement node) { 2110 visitLabelledStatement(LabelledStatement node) {
1968 compiler.unimplemented('SsaBuilder.visitLabelledStatement', node: node); 2111 BreakHandler handler = null;
2112 Node currentNode = node;
2113 do {
2114 StatementElement element = elements[currentNode];
2115 if (element !== null && element.isBreakTarget) {
2116 if (handler === null) handler = new BreakHandler(this);
2117 handler.addTarget(element);
2118 }
2119 currentNode = currentNode.statement;
2120 } while (currentNode is LabelledStatement);
2121 if (handler === null) {
2122 // The labels are not break targets.
2123 visit(currentNode);
2124 } else if (currentNode is Loop || currentNode is SwitchStatement) {
2125 // The labels apply to that statement, and will be handled there.
2126 loopBreakHandler = handler;
2127 visit(currentNode);
2128 assert(loopBreakHandler === null);
2129 } else {
2130 // Introduce a new basic block.
2131 HBasicBlock entryBlock = graph.addNewBlock();
2132 goto(current, entryBlock);
2133 open(entryBlock);
2134 visit(currentNode);
2135 if (isAborted()) {
2136 compiler.unimplemented(
2137 "SsaBuilder for labeled statement with aborting body", node: node);
2138 }
2139 // Always create at least one join block, even if there turns out to be
2140 // no breaks anyway.
2141 HBasicBlock firstJoinBlock = null;
floitsch 2012/02/22 13:17:21 As discussed. let's get rid of firstJoinBlock and
Lasse Reichstein Nielsen 2012/02/22 14:12:24 Done.
2142 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
2143 HBasicBlock joinBlock = graph.addNewBlock();
2144 if (firstJoinBlock === null) {
2145 firstJoinBlock = joinBlock;
2146 }
2147 breakInstruction.block.addSuccessor(joinBlock);
2148 if (!isAborted()) {
2149 goto(current, joinBlock);
2150 open(joinBlock);
2151 localsHandler.mergeWith(locals, joinBlock);
2152 } else {
2153 open(joinBlock);
2154 localsHandler = locals;
2155 }
2156 });
2157 if (firstJoinBlock === null) {
2158 firstJoinBlock = graph.addNewBlock();
2159 if (!isAborted()) goto(current, firstJoinBlock);
2160 open(firstJoinBlock);
2161 }
2162 HLabeledBlockInformation blockInfo =
2163 new HLabeledBlockInformation(entryBlock, firstJoinBlock,
2164 handler.labels());
2165 handler.close();
2166 // Mark both entry and exit with the information. You can
2167 // tell which one is which by comparing with blockInfo.start/end.
2168 entryBlock.labeledBlockInformation = blockInfo;
2169 firstJoinBlock.labeledBlockInformation = blockInfo;
2170 }
1969 } 2171 }
1970 2172
1971 visitLiteralMap(LiteralMap node) { 2173 visitLiteralMap(LiteralMap node) {
1972 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node); 2174 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node);
1973 } 2175 }
1974 2176
1975 visitLiteralMapEntry(LiteralMapEntry node) { 2177 visitLiteralMapEntry(LiteralMapEntry node) {
1976 compiler.unimplemented('SsaBuilder.visitLiteralMapEntry', node: node); 2178 compiler.unimplemented('SsaBuilder.visitLiteralMapEntry', node: node);
1977 } 2179 }
1978 2180
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2079 } 2281 }
2080 2282
2081 visitCatchBlock(CatchBlock node) { 2283 visitCatchBlock(CatchBlock node) {
2082 visit(node.block); 2284 visit(node.block);
2083 } 2285 }
2084 2286
2085 visitTypedef(Typedef node) { 2287 visitTypedef(Typedef node) {
2086 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); 2288 compiler.unimplemented('SsaBuilder.visitTypedef', node: node);
2087 } 2289 }
2088 } 2290 }
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