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(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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |