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

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: 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 that the current block is dead (because it has a throw or a
814 * return further up. If this is true, then [_current] may be null. If it
ngeoffray 2013/04/10 12:06:39 Missing ending paren after 'further up'.
erikcorry 2013/04/10 12:52:32 Done.
815 * is dead then it may also be aborted, but for simplicity we only abort on
816 * statement boundaries, not in the middle of expressions. See isAborted.
817 */
818 bool isReachable = true;
karlklose 2013/04/09 11:58:46 The comment does not really match the name of the
erikcorry 2013/04/10 12:52:32 Done.
819
805 final List<Element> sourceElementStack; 820 final List<Element> sourceElementStack;
806 821
807 Element get currentElement => sourceElementStack.last.declaration; 822 Element get currentElement => sourceElementStack.last.declaration;
808 Compiler get compiler => builder.compiler; 823 Compiler get compiler => builder.compiler;
809 CodeEmitterTask get emitter => builder.emitter; 824 CodeEmitterTask get emitter => builder.emitter;
810 825
811 SsaBuilder(this.constantSystem, SsaBuilderTask builder, CodegenWorkItem work) 826 SsaBuilder(this.constantSystem, SsaBuilderTask builder, CodegenWorkItem work)
812 : this.builder = builder, 827 : this.builder = builder,
813 this.backend = builder.backend, 828 this.backend = builder.backend,
814 this.work = work, 829 this.work = work,
815 graph = new HGraph(), 830 graph = new HGraph(),
816 stack = new List<HInstruction>(), 831 stack = new List<HInstruction>(),
817 activationVariables = new Map<Element, HLocalValue>(), 832 activationVariables = new Map<Element, HLocalValue>(),
818 jumpTargets = new Map<TargetElement, JumpHandler>(), 833 jumpTargets = new Map<TargetElement, JumpHandler>(),
819 parameters = new Map<Element, HInstruction>(), 834 parameters = new Map<Element, HInstruction>(),
820 sourceElementStack = <Element>[work.element], 835 sourceElementStack = <Element>[work.element],
821 inliningStack = <InliningState>[], 836 inliningStack = <InliningState>[],
822 rti = builder.backend.rti, 837 rti = builder.backend.rti,
823 super(work.resolutionTree) { 838 super(work.resolutionTree) {
824 localsHandler = new LocalsHandler(this); 839 localsHandler = new LocalsHandler(this);
825 } 840 }
826 841
827 static const MAX_INLINING_DEPTH = 3; 842 static const MAX_INLINING_DEPTH = 3;
828 static const MAX_INLINING_NODES = 46; 843 static const MAX_INLINING_NODES = 46;
829 List<InliningState> inliningStack; 844 List<InliningState> inliningStack;
830 Element returnElement; 845 Element returnElement;
831 DartType returnType; 846 DartType returnType;
832 bool inTryStatement = false; 847 bool inTryStatement = false;
833 848
849 HBasicBlock get current => _current;
850 void set current(c) {
851 isReachable = c != null;
852 _current = c;
853 }
854
834 /** 855 /**
835 * Compiles compile-time constants. Never returns [:null:]. If the 856 * Compiles compile-time constants. Never returns [:null:]. If the
836 * initial value is not a compile-time constants, it reports an 857 * initial value is not a compile-time constants, it reports an
837 * internal error. 858 * internal error.
838 */ 859 */
839 Constant compileConstant(VariableElement element) { 860 Constant compileConstant(VariableElement element) {
840 return compiler.constantHandler.compileConstant(element); 861 return compiler.constantHandler.compileConstant(element);
841 } 862 }
842 863
843 Constant compileVariable(VariableElement element) { 864 Constant compileVariable(VariableElement element) {
(...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after
1747 1768
1748 void visit(Node node) { 1769 void visit(Node node) {
1749 if (node != null) node.accept(this); 1770 if (node != null) node.accept(this);
1750 } 1771 }
1751 1772
1752 visitBlock(Block node) { 1773 visitBlock(Block node) {
1753 for (Link<Node> link = node.statements.nodes; 1774 for (Link<Node> link = node.statements.nodes;
1754 !link.isEmpty; 1775 !link.isEmpty;
1755 link = link.tail) { 1776 link = link.tail) {
1756 visit(link.head); 1777 visit(link.head);
1757 if (isAborted()) { 1778 if (!isReachable) {
1758 // The block has been aborted by a return or a throw. 1779 // The block has been aborted by a return or a throw.
1759 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack'); 1780 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack');
1760 return; 1781 return;
1761 } 1782 }
1762 } 1783 }
1763 assert(!current.isClosed()); 1784 assert(!current.isClosed());
1764 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack'); 1785 if (!stack.isEmpty) compiler.cancel('non-empty instruction stack');
1765 } 1786 }
1766 1787
1767 visitClassNode(ClassNode node) { 1788 visitClassNode(ClassNode node) {
1768 compiler.internalError('visitClassNode should not be called', node: node); 1789 compiler.internalError('visitClassNode should not be called', node: node);
1769 } 1790 }
1770 1791
1771 visitExpressionStatement(ExpressionStatement node) { 1792 visitExpressionStatement(ExpressionStatement node) {
1772 visit(node.expression); 1793 if (isReachable) {
ngeoffray 2013/04/10 12:06:39 It looks weird to check this here while the code l
erikcorry 2013/04/10 12:52:32 I replaced all these checks with asserts and it tu
ngeoffray 2013/04/10 13:02:58 Isn't that a bug if that assert is hit? Do you kno
erikcorry 2013/04/11 09:09:35 It's the inlined throw test that I just introduced
1773 pop(); 1794 visit(node.expression);
1795 pop();
1796 }
1774 } 1797 }
1775 1798
1776 /** 1799 /**
1777 * Creates a new loop-header block. The previous [current] block 1800 * Creates a new loop-header block. The previous [current] block
1778 * is closed with an [HGoto] and replaced by the newly created block. 1801 * is closed with an [HGoto] and replaced by the newly created block.
1779 * Also notifies the locals handler that we're entering a loop. 1802 * Also notifies the locals handler that we're entering a loop.
1780 */ 1803 */
1781 JumpHandler beginLoopHeader(Node node) { 1804 JumpHandler beginLoopHeader(Node node) {
1782 assert(!isAborted()); 1805 assert(!isAborted());
1783 HBasicBlock previousBlock = close(new HGoto()); 1806 HBasicBlock previousBlock = close(new HGoto());
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
2040 HBasicBlock block = breakInstruction.block; 2063 HBasicBlock block = breakInstruction.block;
2041 block.addAtExit(new HBreak.toLabel(label)); 2064 block.addAtExit(new HBreak.toLabel(label));
2042 block.remove(breakInstruction); 2065 block.remove(breakInstruction);
2043 }); 2066 });
2044 } 2067 }
2045 } 2068 }
2046 jumpHandler.close(); 2069 jumpHandler.close();
2047 } 2070 }
2048 2071
2049 visitFor(For node) { 2072 visitFor(For node) {
2073 if (!isReachable) return;
karlklose 2013/04/09 11:58:46 Would it be enough to abort in visitBlock instead
erikcorry 2013/04/10 12:52:32 I tried replacing this if with an assert and it wa
2050 assert(node.body != null); 2074 assert(node.body != null);
2051 void buildInitializer() { 2075 void buildInitializer() {
2052 if (node.initializer == null) return; 2076 if (node.initializer == null) return;
2053 Node initializer = node.initializer; 2077 Node initializer = node.initializer;
2054 if (initializer != null) { 2078 if (initializer != null) {
2055 visit(initializer); 2079 visit(initializer);
2056 if (initializer.asExpression() != null) { 2080 if (initializer.asExpression() != null) {
2057 pop(); 2081 pop();
2058 } 2082 }
2059 } 2083 }
(...skipping 14 matching lines...) Expand all
2074 HInstruction updateInstruction = pop(); 2098 HInstruction updateInstruction = pop();
2075 } 2099 }
2076 } 2100 }
2077 void buildBody() { 2101 void buildBody() {
2078 visit(node.body); 2102 visit(node.body);
2079 } 2103 }
2080 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody); 2104 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody);
2081 } 2105 }
2082 2106
2083 visitWhile(While node) { 2107 visitWhile(While node) {
2108 if (!isReachable) return;
2084 HInstruction buildCondition() { 2109 HInstruction buildCondition() {
2085 visit(node.condition); 2110 visit(node.condition);
2086 return popBoolified(); 2111 return popBoolified();
2087 } 2112 }
2088 handleLoop(node, 2113 handleLoop(node,
2089 () {}, 2114 () {},
2090 buildCondition, 2115 buildCondition,
2091 () {}, 2116 () {},
2092 () { visit(node.body); }); 2117 () { visit(node.body); });
2093 } 2118 }
2094 2119
2095 visitDoWhile(DoWhile node) { 2120 visitDoWhile(DoWhile node) {
2121 if (!isReachable) return;
2096 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 2122 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2097 localsHandler.startLoop(node); 2123 localsHandler.startLoop(node);
2098 JumpHandler jumpHandler = beginLoopHeader(node); 2124 JumpHandler jumpHandler = beginLoopHeader(node);
2099 HLoopInformation loopInfo = current.loopInformation; 2125 HLoopInformation loopInfo = current.loopInformation;
2100 HBasicBlock loopEntryBlock = current; 2126 HBasicBlock loopEntryBlock = current;
2101 HBasicBlock bodyEntryBlock = current; 2127 HBasicBlock bodyEntryBlock = current;
2102 TargetElement target = elements[node]; 2128 TargetElement target = elements[node];
2103 bool hasContinues = target != null && target.isContinueTarget; 2129 bool hasContinues = target != null && target.isContinueTarget;
2104 if (hasContinues) { 2130 if (hasContinues) {
2105 // Add extra block to hang labels on. 2131 // Add extra block to hang labels on.
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
2248 } 2274 }
2249 }); 2275 });
2250 2276
2251 HType type = new HType.nonNullExact( 2277 HType type = new HType.nonNullExact(
2252 compiler.functionClass.computeType(compiler), 2278 compiler.functionClass.computeType(compiler),
2253 compiler); 2279 compiler);
2254 push(new HForeignNew(closureClassElement, type, capturedVariables)); 2280 push(new HForeignNew(closureClassElement, type, capturedVariables));
2255 } 2281 }
2256 2282
2257 visitFunctionDeclaration(FunctionDeclaration node) { 2283 visitFunctionDeclaration(FunctionDeclaration node) {
2284 if (!isReachable) return;
2258 visit(node.function); 2285 visit(node.function);
2259 localsHandler.updateLocal(elements[node], pop()); 2286 localsHandler.updateLocal(elements[node], pop());
2260 } 2287 }
2261 2288
2262 visitIdentifier(Identifier node) { 2289 visitIdentifier(Identifier node) {
2263 if (node.isThis()) { 2290 if (node.isThis()) {
2264 stack.add(localsHandler.readThis()); 2291 stack.add(localsHandler.readThis());
2265 } else { 2292 } else {
2266 compiler.internalError("SsaBuilder.visitIdentifier on non-this", 2293 compiler.internalError("SsaBuilder.visitIdentifier on non-this",
2267 node: node); 2294 node: node);
2268 } 2295 }
2269 } 2296 }
2270 2297
2271 visitIf(If node) { 2298 visitIf(If node) {
2299 if (!isReachable) return;
2272 handleIf(node, 2300 handleIf(node,
2273 () => visit(node.condition), 2301 () => visit(node.condition),
2274 () => visit(node.thenPart), 2302 () => visit(node.thenPart),
2275 node.elsePart != null ? () => visit(node.elsePart) : null); 2303 node.elsePart != null ? () => visit(node.elsePart) : null);
2276 } 2304 }
2277 2305
2278 void handleIf(Node diagnosticNode, 2306 void handleIf(Node diagnosticNode,
2279 void visitCondition(), void visitThen(), void visitElse()) { 2307 void visitCondition(), void visitThen(), void visitElse()) {
2280 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode); 2308 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, diagnosticNode);
2281 branchBuilder.handleIf(visitCondition, visitThen, visitElse); 2309 branchBuilder.handleIf(visitCondition, visitThen, visitElse);
(...skipping 1585 matching lines...) Expand 10 before | Expand all | Expand 10 after
3867 open(newBlock); 3895 open(newBlock);
3868 } 3896 }
3869 3897
3870 visitReturn(Return node) { 3898 visitReturn(Return node) {
3871 if (identical(node.getBeginToken().stringValue, 'native')) { 3899 if (identical(node.getBeginToken().stringValue, 'native')) {
3872 native.handleSsaNative(this, node.expression); 3900 native.handleSsaNative(this, node.expression);
3873 return; 3901 return;
3874 } 3902 }
3875 assert(invariant(node, !node.isRedirectingFactoryBody)); 3903 assert(invariant(node, !node.isRedirectingFactoryBody));
3876 HInstruction value; 3904 HInstruction value;
3877 if (node.expression == null) { 3905 if (node.expression == null || !isReachable) {
3878 value = graph.addConstantNull(constantSystem); 3906 value = graph.addConstantNull(constantSystem);
3879 } else { 3907 } else {
3880 visit(node.expression); 3908 visit(node.expression);
3881 value = pop(); 3909 value = pop();
3882 value = potentiallyCheckType(value, returnType); 3910 value = potentiallyCheckType(value, returnType);
3883 } 3911 }
3884 3912
3885 handleInTryStatement(); 3913 handleInTryStatement();
3886 3914
3887 if (!inliningStack.isEmpty) { 3915 if (!inliningStack.isEmpty) {
3888 localsHandler.updateLocal(returnElement, value); 3916 localsHandler.updateLocal(returnElement, value);
3889 } else { 3917 } else {
3890 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); 3918 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit);
3891 } 3919 }
3892 } 3920 }
3893 3921
3894 visitThrow(Throw node) { 3922 visitThrow(Throw node) {
3895 if (node.expression == null) { 3923 if (node.expression == null) {
3896 HInstruction exception = rethrowableException; 3924 HInstruction exception = rethrowableException;
3897 if (exception == null) { 3925 if (exception == null) {
3898 exception = graph.addConstantNull(constantSystem); 3926 exception = graph.addConstantNull(constantSystem);
3899 compiler.internalError( 3927 compiler.internalError(
3900 'rethrowableException should not be null', node: node); 3928 'rethrowableException should not be null', node: node);
3901 } 3929 }
3902 close(new HThrow(exception, isRethrow: true)); 3930 close(new HThrow(exception, isRethrow: true));
3903 } else { 3931 } else {
3904 visit(node.expression); 3932 if (inliningStack.isEmpty) {
3905 close(new HThrow(pop())); 3933 if (isReachable) {
ngeoffray 2013/04/10 12:06:39 I can't see why this can happen.
erikcorry 2013/04/10 12:52:32 Perhaps if there is more than one throw in an inli
ngeoffray 2013/04/10 13:02:58 But the first throw would abort visiting the block
erikcorry 2013/04/11 09:09:35 I couldn't make this trigger so I removed it.
3934 visit(node.expression);
3935 } else {
3936 stack.add(graph.addConstantNull(constantSystem));
3937 }
3938 close(new HThrow(pop()));
3939 } else if (isReachable) {
3940 // We don't close the block when we are inlining, because we could be
3941 // inside an expression, and it is rather complicated to close the
3942 // block at an arbitrary place in an expression.
3943 visit(node.expression);
3944 add(new HThrowExpression(pop()));
3945 isReachable = false;
3946 }
3906 } 3947 }
3907 } 3948 }
3908 3949
3909 visitTypeAnnotation(TypeAnnotation node) { 3950 visitTypeAnnotation(TypeAnnotation node) {
3910 compiler.internalError('visiting type annotation in SSA builder', 3951 compiler.internalError('visiting type annotation in SSA builder',
3911 node: node); 3952 node: node);
3912 } 3953 }
3913 3954
3914 visitVariableDefinitions(VariableDefinitions node) { 3955 visitVariableDefinitions(VariableDefinitions node) {
3956 if (!isReachable) return;
3915 for (Link<Node> link = node.definitions.nodes; 3957 for (Link<Node> link = node.definitions.nodes;
3916 !link.isEmpty; 3958 !link.isEmpty;
3917 link = link.tail) { 3959 link = link.tail) {
3918 Node definition = link.head; 3960 Node definition = link.head;
3919 if (definition is Identifier) { 3961 if (definition is Identifier) {
3920 HInstruction initialValue = graph.addConstantNull(constantSystem); 3962 HInstruction initialValue = graph.addConstantNull(constantSystem);
3921 localsHandler.updateLocal(elements[definition], initialValue); 3963 localsHandler.updateLocal(elements[definition], initialValue);
3922 } else { 3964 } else {
3923 assert(definition is SendSet); 3965 assert(definition is SendSet);
3924 visitSendSet(definition); 3966 visitSendSet(definition);
(...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after
4898 } 4940 }
4899 node.visitChildren(this); 4941 node.visitChildren(this);
4900 seenReturn = true; 4942 seenReturn = true;
4901 } 4943 }
4902 4944
4903 void visitTryStatement(Node node) { 4945 void visitTryStatement(Node node) {
4904 if (!registerNode()) return; 4946 if (!registerNode()) return;
4905 tooDifficult = true; 4947 tooDifficult = true;
4906 } 4948 }
4907 4949
4908 void visitThrow(Node node) { 4950 void visitThrow(Throw node) {
4909 if (!registerNode()) return; 4951 if (!registerNode()) return;
4910 tooDifficult = true; 4952 // We can't inline rethrows and we don't want to handle throw after a return
4953 // even if it is in an "if".
4954 if (seenReturn || node.expression == null) tooDifficult = true;
4911 } 4955 }
4912 } 4956 }
4913 4957
4914 class InliningState { 4958 class InliningState {
4915 /** 4959 /**
4916 * Documentation wanted -- johnniwinther 4960 * Documentation wanted -- johnniwinther
4917 * 4961 *
4918 * Invariant: [function] must be an implementation element. 4962 * Invariant: [function] must be an implementation element.
4919 */ 4963 */
4920 final PartialFunctionElement function; 4964 final PartialFunctionElement function;
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
5162 new HSubGraphBlockInformation(elseBranch.graph)); 5206 new HSubGraphBlockInformation(elseBranch.graph));
5163 5207
5164 HBasicBlock conditionStartBlock = conditionBranch.block; 5208 HBasicBlock conditionStartBlock = conditionBranch.block;
5165 conditionStartBlock.setBlockFlow(info, joinBlock); 5209 conditionStartBlock.setBlockFlow(info, joinBlock);
5166 SubGraph conditionGraph = conditionBranch.graph; 5210 SubGraph conditionGraph = conditionBranch.graph;
5167 HIf branch = conditionGraph.end.last; 5211 HIf branch = conditionGraph.end.last;
5168 assert(branch is HIf); 5212 assert(branch is HIf);
5169 branch.blockInformation = conditionStartBlock.blockFlow; 5213 branch.blockInformation = conditionStartBlock.blockFlow;
5170 } 5214 }
5171 } 5215 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698