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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 13947004: dart2js: Allow 'throw' when inlining (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Nicolas' Code review feedback Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of ssa; 5 part of ssa;
6 6
7 /** 7 /**
8 * A special element for the extra parameter taken by intercepted 8 * A special element for the extra parameter taken by intercepted
9 * methods. We need to override [Element.computeType] because our 9 * methods. We need to override [Element.computeType] because our
10 * optimizers may look at its declared type. 10 * optimizers may look at its declared type.
(...skipping 18 matching lines...) Expand all
29 super(backend.compiler); 29 super(backend.compiler);
30 30
31 HGraph build(CodegenWorkItem work) { 31 HGraph build(CodegenWorkItem work) {
32 return measure(() { 32 return measure(() {
33 Element element = work.element.implementation; 33 Element element = work.element.implementation;
34 HInstruction.idCounter = 0; 34 HInstruction.idCounter = 0;
35 ConstantSystem constantSystem = compiler.backend.constantSystem; 35 ConstantSystem constantSystem = compiler.backend.constantSystem;
36 SsaBuilder builder = new SsaBuilder(constantSystem, this, work); 36 SsaBuilder builder = new SsaBuilder(constantSystem, this, work);
37 HGraph graph; 37 HGraph graph;
38 ElementKind kind = element.kind; 38 ElementKind kind = element.kind;
39 if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR)) { 39 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
40 graph = compileConstructor(builder, work); 40 graph = compileConstructor(builder, work);
41 } else if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR_BODY) || 41 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
42 identical(kind, ElementKind.FUNCTION) || 42 kind == ElementKind.FUNCTION ||
43 identical(kind, ElementKind.GETTER) || 43 kind == ElementKind.GETTER ||
44 identical(kind, ElementKind.SETTER)) { 44 kind == ElementKind.SETTER) {
45 graph = builder.buildMethod(element); 45 graph = builder.buildMethod(element);
46 } else if (identical(kind, ElementKind.FIELD)) { 46 } else if (kind == ElementKind.FIELD) {
47 graph = builder.buildLazyInitializer(element); 47 graph = builder.buildLazyInitializer(element);
48 } else { 48 } else {
49 compiler.internalErrorOnElement(element, 49 compiler.internalErrorOnElement(element,
50 'unexpected element kind $kind'); 50 'unexpected element kind $kind');
51 } 51 }
52 assert(graph.isValid()); 52 assert(graph.isValid());
53 if (!identical(kind, ElementKind.FIELD)) { 53 if (!identical(kind, ElementKind.FIELD)) {
54 FunctionElement function = element; 54 FunctionElement function = element;
55 graph.calledInLoop = compiler.world.isCalledInLoop(function); 55 graph.calledInLoop = compiler.world.isCalledInLoop(function);
56 OptionalParameterTypes defaultValueTypes = null; 56 OptionalParameterTypes defaultValueTypes = null;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 } 103 }
104 104
105 HGraph compileConstructor(SsaBuilder builder, CodegenWorkItem work) { 105 HGraph compileConstructor(SsaBuilder builder, CodegenWorkItem work) {
106 // The body of the constructor will be generated in a separate function. 106 // The body of the constructor will be generated in a separate function.
107 final ClassElement classElement = work.element.getEnclosingClass(); 107 final ClassElement classElement = work.element.getEnclosingClass();
108 return builder.buildFactory(classElement.implementation, 108 return builder.buildFactory(classElement.implementation,
109 work.element.implementation); 109 work.element.implementation);
110 } 110 }
111 } 111 }
112 112
113
113 /** 114 /**
114 * Keeps track of locals (including parameters and phis) when building. The 115 * Keeps track of locals (including parameters and phis) when building. The
115 * 'this' reference is treated as parameter and hence handled by this class, 116 * 'this' reference is treated as parameter and hence handled by this class,
116 * too. 117 * too.
117 */ 118 */
118 class LocalsHandler { 119 class LocalsHandler {
119 /** 120 /**
120 * The values of locals that can be directly accessed (without redirections 121 * The values of locals that can be directly accessed (without redirections
121 * to boxes or closure-fields). 122 * to boxes or closure-fields).
122 * 123 *
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 HInstruction box = readLocal(redirect.enclosingElement); 434 HInstruction box = readLocal(redirect.enclosingElement);
434 builder.add(new HFieldSet(redirect, box, value)); 435 builder.add(new HFieldSet(redirect, box, value));
435 } else { 436 } else {
436 assert(isUsedInTry(element)); 437 assert(isUsedInTry(element));
437 HLocalValue local = getLocal(element); 438 HLocalValue local = getLocal(element);
438 builder.add(new HLocalSet(element, local, value)); 439 builder.add(new HLocalSet(element, local, value));
439 } 440 }
440 } 441 }
441 442
442 /** 443 /**
443 * This function must be called before visiting any children of the loop. In 444 * This function, startLoop, must be called before visiting any children of
444 * particular it needs to be called before executing the initializers. 445 * the loop. In particular it needs to be called before executing the
446 * initializers.
445 * 447 *
446 * The [LocalsHandler] will make the boxes and updates at the right moment. 448 * The [LocalsHandler] will make the boxes and updates at the right moment.
447 * The builder just needs to call [enterLoopBody] and [enterLoopUpdates] (for 449 * The builder just needs to call [enterLoopBody] and [enterLoopUpdates] (for
448 * [For] loops) at the correct places. For phi-handling [beginLoopHeader] and 450 * [For] loops) at the correct places. For phi-handling [beginLoopHeader] and
449 * [endLoop] must also be called. 451 * [endLoop] must also be called.
450 * 452 *
451 * The correct place for the box depends on the given loop. In most cases 453 * The correct place for the box depends on the given loop. In most cases
452 * the box will be created when entering the loop-body: while, do-while, and 454 * the box will be created when entering the loop-body: while, do-while, and
453 * for-in (assuming the call to [:next:] is inside the body) can always be 455 * for-in (assuming the call to [:next:] is inside the body) can always be
454 * constructed this way. 456 * constructed this way.
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 /** 789 /**
788 * Variables stored in the current activation. These variables are 790 * Variables stored in the current activation. These variables are
789 * being updated in try/catch blocks, and should be 791 * being updated in try/catch blocks, and should be
790 * accessed indirectly through [HLocalGet] and [HLocalSet]. 792 * accessed indirectly through [HLocalGet] and [HLocalSet].
791 */ 793 */
792 Map<Element, HLocalValue> activationVariables; 794 Map<Element, HLocalValue> activationVariables;
793 795
794 // We build the Ssa graph by simulating a stack machine. 796 // We build the Ssa graph by simulating a stack machine.
795 List<HInstruction> stack; 797 List<HInstruction> stack;
796 798
797 // The current block to add instructions to. Might be null, if we are 799 /**
798 // visiting dead code. 800 * The current block to add instructions to. Might be null, if we are
799 HBasicBlock current; 801 * visiting dead code, but see [isReachable].
800 // The most recently opened block. Has the same value as [current] while 802 */
801 // the block is open, but unlike [current], it isn't cleared when the current 803 HBasicBlock _current;
802 // block is closed. 804
805 /**
806 * The most recently opened block. Has the same value as [_current] while
807 * the block is open, but unlike [_current], it isn't cleared when the
808 * current block is closed.
809 */
803 HBasicBlock lastOpenedBlock; 810 HBasicBlock lastOpenedBlock;
804 811
812 /**
813 * Indicates whether the current block is dead (because it has a throw or a
814 * return further up). If this is false, then [_current] may be null. If the
815 * block is dead then it may also be aborted, but for simplicity we only
816 * abort on statement boundaries, not in the middle of expressions. See
817 * isAborted.
818 */
819 bool isReachable = true;
820
805 final List<Element> sourceElementStack; 821 final List<Element> sourceElementStack;
806 822
807 Element get currentElement => sourceElementStack.last.declaration; 823 Element get currentElement => sourceElementStack.last.declaration;
808 Compiler get compiler => builder.compiler; 824 Compiler get compiler => builder.compiler;
809 CodeEmitterTask get emitter => builder.emitter; 825 CodeEmitterTask get emitter => builder.emitter;
810 826
811 SsaBuilder(this.constantSystem, SsaBuilderTask builder, CodegenWorkItem work) 827 SsaBuilder(this.constantSystem, SsaBuilderTask builder, CodegenWorkItem work)
812 : this.builder = builder, 828 : this.builder = builder,
813 this.backend = builder.backend, 829 this.backend = builder.backend,
814 this.work = work, 830 this.work = work,
815 graph = new HGraph(), 831 graph = new HGraph(),
816 stack = new List<HInstruction>(), 832 stack = new List<HInstruction>(),
817 activationVariables = new Map<Element, HLocalValue>(), 833 activationVariables = new Map<Element, HLocalValue>(),
818 jumpTargets = new Map<TargetElement, JumpHandler>(), 834 jumpTargets = new Map<TargetElement, JumpHandler>(),
819 parameters = new Map<Element, HInstruction>(), 835 parameters = new Map<Element, HInstruction>(),
820 sourceElementStack = <Element>[work.element], 836 sourceElementStack = <Element>[work.element],
821 inliningStack = <InliningState>[], 837 inliningStack = <InliningState>[],
822 rti = builder.backend.rti, 838 rti = builder.backend.rti,
823 super(work.resolutionTree) { 839 super(work.resolutionTree) {
824 localsHandler = new LocalsHandler(this); 840 localsHandler = new LocalsHandler(this);
825 } 841 }
826 842
827 static const MAX_INLINING_DEPTH = 3; 843 static const MAX_INLINING_DEPTH = 3;
828 static const MAX_INLINING_NODES = 46; 844 static const MAX_INLINING_NODES = 46;
829 List<InliningState> inliningStack; 845 List<InliningState> inliningStack;
830 Element returnElement; 846 Element returnElement;
831 DartType returnType; 847 DartType returnType;
832 bool inTryStatement = false; 848 bool inTryStatement = false;
833 849
850 HBasicBlock get current => _current;
851 void set current(c) {
852 isReachable = c != null;
853 _current = c;
854 }
855
834 /** 856 /**
835 * Compiles compile-time constants. Never returns [:null:]. If the 857 * Compiles compile-time constants. Never returns [:null:]. If the
836 * initial value is not a compile-time constants, it reports an 858 * initial value is not a compile-time constants, it reports an
837 * internal error. 859 * internal error.
838 */ 860 */
839 Constant compileConstant(VariableElement element) { 861 Constant compileConstant(VariableElement element) {
840 return compiler.constantHandler.compileConstant(element); 862 return compiler.constantHandler.compileConstant(element);
841 } 863 }
842 864
843 Constant compileVariable(VariableElement element) { 865 Constant compileVariable(VariableElement element) {
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after
1656 current = null; 1678 current = null;
1657 return result; 1679 return result;
1658 } 1680 }
1659 1681
1660 void goto(HBasicBlock from, HBasicBlock to) { 1682 void goto(HBasicBlock from, HBasicBlock to) {
1661 from.close(new HGoto()); 1683 from.close(new HGoto());
1662 from.addSuccessor(to); 1684 from.addSuccessor(to);
1663 } 1685 }
1664 1686
1665 bool isAborted() { 1687 bool isAborted() {
1666 return current == null; 1688 return _current == null;
1667 } 1689 }
1668 1690
1669 /** 1691 /**
1670 * Creates a new block, transitions to it from any current block, and 1692 * Creates a new block, transitions to it from any current block, and
1671 * opens the new block. 1693 * opens the new block.
1672 */ 1694 */
1673 HBasicBlock openNewBlock() { 1695 HBasicBlock openNewBlock() {
1674 HBasicBlock newBlock = addNewBlock(); 1696 HBasicBlock newBlock = addNewBlock();
1675 if (!isAborted()) goto(current, newBlock); 1697 if (!isAborted()) goto(current, newBlock);
1676 open(newBlock); 1698 open(newBlock);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1743 'length': sourceFile.text.length}); 1765 'length': sourceFile.text.length});
1744 } 1766 }
1745 return location; 1767 return location;
1746 } 1768 }
1747 1769
1748 void visit(Node node) { 1770 void visit(Node node) {
1749 if (node != null) node.accept(this); 1771 if (node != null) node.accept(this);
1750 } 1772 }
1751 1773
1752 visitBlock(Block node) { 1774 visitBlock(Block node) {
1775 if (!isReachable) return; // This can happen when inlining.
ngeoffray 2013/04/11 09:31:08 // This only happens when inlining Can you add: a
1753 for (Link<Node> link = node.statements.nodes; 1776 for (Link<Node> link = node.statements.nodes;
1754 !link.isEmpty; 1777 !link.isEmpty;
1755 link = link.tail) { 1778 link = link.tail) {
1756 visit(link.head); 1779 visit(link.head);
1757 if (isAborted()) { 1780 if (!isReachable) {
1758 // The block has been aborted by a return or a throw. 1781 // The block has been aborted by a return or a throw.
1759 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack'); 1782 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack');
1760 return; 1783 return;
1761 } 1784 }
1762 } 1785 }
1763 assert(!current.isClosed()); 1786 assert(!current.isClosed());
1764 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack'); 1787 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack');
1765 } 1788 }
1766 1789
1767 visitClassNode(ClassNode node) { 1790 visitClassNode(ClassNode node) {
1768 compiler.internalError('visitClassNode should not be called', node: node); 1791 compiler.internalError('visitClassNode should not be called', node: node);
1769 } 1792 }
1770 1793
1771 visitExpressionStatement(ExpressionStatement node) { 1794 visitExpressionStatement(ExpressionStatement node) {
1795 assert(isReachable);
1772 visit(node.expression); 1796 visit(node.expression);
1773 pop(); 1797 pop();
1774 } 1798 }
1775 1799
1776 /** 1800 /**
1777 * Creates a new loop-header block. The previous [current] block 1801 * Creates a new loop-header block. The previous [current] block
1778 * is closed with an [HGoto] and replaced by the newly created block. 1802 * is closed with an [HGoto] and replaced by the newly created block.
1779 * Also notifies the locals handler that we're entering a loop. 1803 * Also notifies the locals handler that we're entering a loop.
1780 */ 1804 */
1781 JumpHandler beginLoopHeader(Node node) { 1805 JumpHandler beginLoopHeader(Node node) {
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
2040 HBasicBlock block = breakInstruction.block; 2064 HBasicBlock block = breakInstruction.block;
2041 block.addAtExit(new HBreak.toLabel(label)); 2065 block.addAtExit(new HBreak.toLabel(label));
2042 block.remove(breakInstruction); 2066 block.remove(breakInstruction);
2043 }); 2067 });
2044 } 2068 }
2045 } 2069 }
2046 jumpHandler.close(); 2070 jumpHandler.close();
2047 } 2071 }
2048 2072
2049 visitFor(For node) { 2073 visitFor(For node) {
2074 assert(isReachable);
2050 assert(node.body != null); 2075 assert(node.body != null);
2051 void buildInitializer() { 2076 void buildInitializer() {
2052 if (node.initializer == null) return; 2077 if (node.initializer == null) return;
2053 Node initializer = node.initializer; 2078 Node initializer = node.initializer;
2054 if (initializer != null) { 2079 if (initializer != null) {
2055 visit(initializer); 2080 visit(initializer);
2056 if (initializer.asExpression() != null) { 2081 if (initializer.asExpression() != null) {
2057 pop(); 2082 pop();
2058 } 2083 }
2059 } 2084 }
(...skipping 14 matching lines...) Expand all
2074 HInstruction updateInstruction = pop(); 2099 HInstruction updateInstruction = pop();
2075 } 2100 }
2076 } 2101 }
2077 void buildBody() { 2102 void buildBody() {
2078 visit(node.body); 2103 visit(node.body);
2079 } 2104 }
2080 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody); 2105 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody);
2081 } 2106 }
2082 2107
2083 visitWhile(While node) { 2108 visitWhile(While node) {
2109 assert(isReachable);
2084 HInstruction buildCondition() { 2110 HInstruction buildCondition() {
2085 visit(node.condition); 2111 visit(node.condition);
2086 return popBoolified(); 2112 return popBoolified();
2087 } 2113 }
2088 handleLoop(node, 2114 handleLoop(node,
2089 () {}, 2115 () {},
2090 buildCondition, 2116 buildCondition,
2091 () {}, 2117 () {},
2092 () { visit(node.body); }); 2118 () { visit(node.body); });
2093 } 2119 }
2094 2120
2095 visitDoWhile(DoWhile node) { 2121 visitDoWhile(DoWhile node) {
2122 assert(isReachable);
2096 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 2123 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2097 localsHandler.startLoop(node); 2124 localsHandler.startLoop(node);
2098 JumpHandler jumpHandler = beginLoopHeader(node); 2125 JumpHandler jumpHandler = beginLoopHeader(node);
2099 HLoopInformation loopInfo = current.loopInformation; 2126 HLoopInformation loopInfo = current.loopInformation;
2100 HBasicBlock loopEntryBlock = current; 2127 HBasicBlock loopEntryBlock = current;
2101 HBasicBlock bodyEntryBlock = current; 2128 HBasicBlock bodyEntryBlock = current;
2102 TargetElement target = elements[node]; 2129 TargetElement target = elements[node];
2103 bool hasContinues = target != null && target.isContinueTarget; 2130 bool hasContinues = target != null && target.isContinueTarget;
2104 if (hasContinues) { 2131 if (hasContinues) {
2105 // Add extra block to hang labels on. 2132 // Add extra block to hang labels on.
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
2248 } 2275 }
2249 }); 2276 });
2250 2277
2251 HType type = new HType.nonNullExact( 2278 HType type = new HType.nonNullExact(
2252 compiler.functionClass.computeType(compiler), 2279 compiler.functionClass.computeType(compiler),
2253 compiler); 2280 compiler);
2254 push(new HForeignNew(closureClassElement, type, capturedVariables)); 2281 push(new HForeignNew(closureClassElement, type, capturedVariables));
2255 } 2282 }
2256 2283
2257 visitFunctionDeclaration(FunctionDeclaration node) { 2284 visitFunctionDeclaration(FunctionDeclaration node) {
2285 assert(isReachable);
2258 visit(node.function); 2286 visit(node.function);
2259 localsHandler.updateLocal(elements[node], pop()); 2287 localsHandler.updateLocal(elements[node], pop());
2260 } 2288 }
2261 2289
2262 visitIdentifier(Identifier node) { 2290 visitIdentifier(Identifier node) {
2263 if (node.isThis()) { 2291 if (node.isThis()) {
2264 stack.add(localsHandler.readThis()); 2292 stack.add(localsHandler.readThis());
2265 } else { 2293 } else {
2266 compiler.internalError("SsaBuilder.visitIdentifier on non-this", 2294 compiler.internalError("SsaBuilder.visitIdentifier on non-this",
2267 node: node); 2295 node: node);
2268 } 2296 }
2269 } 2297 }
2270 2298
2271 visitIf(If node) { 2299 visitIf(If node) {
2300 assert(isReachable);
2272 handleIf(node, 2301 handleIf(node,
2273 () => visit(node.condition), 2302 () => visit(node.condition),
2274 () => visit(node.thenPart), 2303 () => visit(node.thenPart),
2275 node.elsePart != null ? () => visit(node.elsePart) : null); 2304 node.elsePart != null ? () => visit(node.elsePart) : null);
2276 } 2305 }
2277 2306
2278 void handleIf(Node diagnosticNode, 2307 void handleIf(Node diagnosticNode,
2279 void visitCondition(), void visitThen(), void visitElse()) { 2308 void visitCondition(), void visitThen(), void visitElse()) {
2280 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); 2309 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode);
2281 branchBuilder.handleIf(visitCondition, visitThen, visitElse); 2310 branchBuilder.handleIf(visitCondition, visitThen, visitElse);
(...skipping 1585 matching lines...) Expand 10 before | Expand all | Expand 10 after
3867 open(newBlock); 3896 open(newBlock);
3868 } 3897 }
3869 3898
3870 visitReturn(Return node) { 3899 visitReturn(Return node) {
3871 if (identical(node.getBeginToken().stringValue, 'native')) { 3900 if (identical(node.getBeginToken().stringValue, 'native')) {
3872 native.handleSsaNative(this, node.expression); 3901 native.handleSsaNative(this, node.expression);
3873 return; 3902 return;
3874 } 3903 }
3875 assert(invariant(node, !node.isRedirectingFactoryBody)); 3904 assert(invariant(node, !node.isRedirectingFactoryBody));
3876 HInstruction value; 3905 HInstruction value;
3877 if (node.expression == null) { 3906 if (node.expression == null || !isReachable) {
ngeoffray 2013/04/11 09:31:08 I think you can remove the isReachable check.
3878 value = graph.addConstantNull(constantSystem); 3907 value = graph.addConstantNull(constantSystem);
3879 } else { 3908 } else {
3880 visit(node.expression); 3909 visit(node.expression);
3881 value = pop(); 3910 value = pop();
3882 value = potentiallyCheckType(value, returnType); 3911 value = potentiallyCheckType(value, returnType);
3883 } 3912 }
3884 3913
3885 handleInTryStatement(); 3914 handleInTryStatement();
3886 3915
3887 if (!inliningStack.isEmpty) { 3916 if (!inliningStack.isEmpty) {
3888 localsHandler.updateLocal(returnElement, value); 3917 localsHandler.updateLocal(returnElement, value);
3889 } else { 3918 } else {
3890 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); 3919 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit);
3891 } 3920 }
3892 } 3921 }
3893 3922
3894 visitThrow(Throw node) { 3923 visitThrow(Throw node) {
3895 if (node.expression == null) { 3924 if (node.expression == null) {
3896 HInstruction exception = rethrowableException; 3925 HInstruction exception = rethrowableException;
3897 if (exception == null) { 3926 if (exception == null) {
3898 exception = graph.addConstantNull(constantSystem); 3927 exception = graph.addConstantNull(constantSystem);
3899 compiler.internalError( 3928 compiler.internalError(
3900 'rethrowableException should not be null', node: node); 3929 'rethrowableException should not be null', node: node);
3901 } 3930 }
3902 close(new HThrow(exception, isRethrow: true)); 3931 close(new HThrow(exception, isRethrow: true));
3903 } else { 3932 } else {
3904 visit(node.expression); 3933 if (inliningStack.isEmpty) {
3905 close(new HThrow(pop())); 3934 visit(node.expression);
3935 close(new HThrow(pop()));
3936 } else if (isReachable) {
3937 // We don't close the block when we are inlining, because we could be
3938 // inside an expression, and it is rather complicated to close the
3939 // block at an arbitrary place in an expression.
3940 visit(node.expression);
3941 add(new HThrowExpression(pop()));
3942 isReachable = false;
3943 }
3906 } 3944 }
3907 } 3945 }
3908 3946
3909 visitTypeAnnotation(TypeAnnotation node) { 3947 visitTypeAnnotation(TypeAnnotation node) {
3910 compiler.internalError('visiting type annotation in SSA builder', 3948 compiler.internalError('visiting type annotation in SSA builder',
3911 node: node); 3949 node: node);
3912 } 3950 }
3913 3951
3914 visitVariableDefinitions(VariableDefinitions node) { 3952 visitVariableDefinitions(VariableDefinitions node) {
3953 assert(isReachable);
3915 for (Link<Node> link = node.definitions.nodes; 3954 for (Link<Node> link = node.definitions.nodes;
3916 !link.isEmpty; 3955 !link.isEmpty;
3917 link = link.tail) { 3956 link = link.tail) {
3918 Node definition = link.head; 3957 Node definition = link.head;
3919 if (definition is Identifier) { 3958 if (definition is Identifier) {
3920 HInstruction initialValue = graph.addConstantNull(constantSystem); 3959 HInstruction initialValue = graph.addConstantNull(constantSystem);
3921 localsHandler.updateLocal(elements[definition], initialValue); 3960 localsHandler.updateLocal(elements[definition], initialValue);
3922 } else { 3961 } else {
3923 assert(definition is SendSet); 3962 assert(definition is SendSet);
3924 visitSendSet(definition); 3963 visitSendSet(definition);
(...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after
4898 } 4937 }
4899 node.visitChildren(this); 4938 node.visitChildren(this);
4900 seenReturn = true; 4939 seenReturn = true;
4901 } 4940 }
4902 4941
4903 void visitTryStatement(Node node) { 4942 void visitTryStatement(Node node) {
4904 if (!registerNode()) return; 4943 if (!registerNode()) return;
4905 tooDifficult = true; 4944 tooDifficult = true;
4906 } 4945 }
4907 4946
4908 void visitThrow(Node node) { 4947 void visitThrow(Throw node) {
4909 if (!registerNode()) return; 4948 if (!registerNode()) return;
4910 tooDifficult = true; 4949 // We can't inline rethrows and we don't want to handle throw after a return
4950 // even if it is in an "if".
4951 if (seenReturn || node.expression == null) tooDifficult = true;
4911 } 4952 }
4912 } 4953 }
4913 4954
4914 class InliningState { 4955 class InliningState {
4915 /** 4956 /**
4916 * Documentation wanted -- johnniwinther 4957 * Documentation wanted -- johnniwinther
4917 * 4958 *
4918 * Invariant: [function] must be an implementation element. 4959 * Invariant: [function] must be an implementation element.
4919 */ 4960 */
4920 final PartialFunctionElement function; 4961 final PartialFunctionElement function;
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
5162 new HSubGraphBlockInformation(elseBranch.graph)); 5203 new HSubGraphBlockInformation(elseBranch.graph));
5163 5204
5164 HBasicBlock conditionStartBlock = conditionBranch.block; 5205 HBasicBlock conditionStartBlock = conditionBranch.block;
5165 conditionStartBlock.setBlockFlow(info, joinBlock); 5206 conditionStartBlock.setBlockFlow(info, joinBlock);
5166 SubGraph conditionGraph = conditionBranch.graph; 5207 SubGraph conditionGraph = conditionBranch.graph;
5167 HIf branch = conditionGraph.end.last; 5208 HIf branch = conditionGraph.end.last;
5168 assert(branch is HIf); 5209 assert(branch is HIf);
5169 branch.blockInformation = conditionStartBlock.blockFlow; 5210 branch.blockInformation = conditionStartBlock.blockFlow;
5170 } 5211 }
5171 } 5212 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698