Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |