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 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 613 final HBreak breakInstruction; | 613 final HBreak breakInstruction; |
| 614 final LocalsHandler locals; | 614 final LocalsHandler locals; |
| 615 BreakHandlerEntry(this.breakInstruction, this.locals); | 615 BreakHandlerEntry(this.breakInstruction, this.locals); |
| 616 } | 616 } |
| 617 | 617 |
| 618 interface BreakHandler default BreakHandlerImpl { | 618 interface BreakHandler default BreakHandlerImpl { |
| 619 BreakHandler(SsaBuilder builder, StatementElement target); | 619 BreakHandler(SsaBuilder builder, StatementElement target); |
| 620 void addBreak(HBreak breakInstruction, LocalsHandler locals); | 620 void addBreak(HBreak breakInstruction, LocalsHandler locals); |
| 621 void forEachBreak(Function action); | 621 void forEachBreak(Function action); |
| 622 void close(); | 622 void close(); |
| 623 List<SourceString> labels(); | 623 List<LabelElement> labels(); |
| 624 } | 624 } |
| 625 | 625 |
| 626 // Inert break handler used to avoid null checks when a loop isn't | 626 // Inert break handler used to avoid null checks when a loop isn't |
| 627 // used as the target of a break, and therefore doesn't need a break | 627 // used as the target of a break, and therefore doesn't need a break |
| 628 // handler associated with it. | 628 // handler associated with it. |
| 629 class NullBreakHandler implements BreakHandler { | 629 class NullBreakHandler implements BreakHandler { |
| 630 const NullBreakHandler(); | 630 const NullBreakHandler(); |
| 631 void addBreak(HBreak breakInstruction, LocalsHandler locals) { | 631 void addBreak(HBreak breakInstruction, LocalsHandler locals) { |
| 632 unreachable(); | 632 unreachable(); |
| 633 } | 633 } |
| 634 void forEachBreak(Function ignored) { } | 634 void forEachBreak(Function ignored) { } |
| 635 void close() { } | 635 void close() { } |
| 636 List<SourceString> labels() => const <SourceString>[]; | 636 List<LabelElement> labels() => const <LabelElement>[]; |
| 637 } | 637 } |
| 638 | 638 |
| 639 // Records breaks until a target block is available. | 639 // Records breaks until a target block is available. |
| 640 // Breaks are always forward jumps. | 640 // Breaks are always forward jumps. |
| 641 class BreakHandlerImpl implements BreakHandler { | 641 class BreakHandlerImpl implements BreakHandler { |
| 642 final BreakHandler previous; | 642 final BreakHandler previous; |
| 643 final SsaBuilder builder; | 643 final SsaBuilder builder; |
| 644 final StatementElement target; | 644 final StatementElement target; |
| 645 final List<BreakHandlerEntry> breaks; | 645 final List<BreakHandlerEntry> breaks; |
| 646 BreakHandlerImpl(SsaBuilder builder, this.target) | 646 BreakHandlerImpl(SsaBuilder builder, this.target) |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 662 } | 662 } |
| 663 } | 663 } |
| 664 | 664 |
| 665 void close() { | 665 void close() { |
| 666 assert(builder.currentBreakHandler === this); | 666 assert(builder.currentBreakHandler === this); |
| 667 // The mapping from StatementElement to BreakHandler is no longer needed. | 667 // The mapping from StatementElement to BreakHandler is no longer needed. |
| 668 builder.breakTargets.remove(target); | 668 builder.breakTargets.remove(target); |
| 669 builder.currentBreakHandler = previous; | 669 builder.currentBreakHandler = previous; |
| 670 } | 670 } |
| 671 | 671 |
| 672 List<SourceString> labels() { | 672 List<LabelElement> labels() { |
| 673 List<SourceString> result = null; | 673 List<LabelElement> result = null; |
| 674 for (LabelElement element in target.labels) { | 674 for (LabelElement element in target.labels) { |
| 675 if (element.isBreakTarget) { | 675 if (element.isBreakTarget) { |
| 676 if (result === null) result = <SourceString>[]; | 676 if (result === null) result = <LabelElement>[]; |
| 677 result.add(element.label.source); | 677 result.add(element); |
| 678 } | 678 } |
| 679 } | 679 } |
| 680 return (result === null) ? const <SourceString>[] : result; | 680 return (result === null) ? const <LabelElement>[] : result; |
| 681 } | 681 } |
| 682 } | 682 } |
| 683 | 683 |
| 684 class SsaBuilder implements Visitor { | 684 class SsaBuilder implements Visitor { |
| 685 final Compiler compiler; | 685 final Compiler compiler; |
| 686 TreeElements elements; | 686 TreeElements elements; |
| 687 final Interceptors interceptors; | 687 final Interceptors interceptors; |
| 688 final WorkItem work; | 688 final WorkItem work; |
| 689 bool methodInterceptionEnabled; | 689 bool methodInterceptionEnabled; |
| 690 HGraph graph; | 690 HGraph graph; |
| 691 LocalsHandler localsHandler; | 691 LocalsHandler localsHandler; |
| 692 HInstruction rethrowableException; | 692 HInstruction rethrowableException; |
| 693 | 693 |
| 694 Map<StatementElement, BreakHandler> breakTargets; | 694 Map<StatementElement, BreakHandler> breakTargets; |
| 695 | 695 |
| 696 // We build the Ssa graph by simulating a stack machine. | 696 // We build the Ssa graph by simulating a stack machine. |
| 697 List<HInstruction> stack; | 697 List<HInstruction> stack; |
| 698 | 698 |
| 699 // The current block to add instructions to. Might be null, if we are | 699 // The current block to add instructions to. Might be null, if we are |
| 700 // visiting dead code. | 700 // visiting dead code. |
| 701 HBasicBlock current; | 701 HBasicBlock current; |
| 702 // The most recently opened block. Has the same value as [current] while | 702 // The most recently opened block. Has the same value as [current] while |
| 703 // the block is open, but unlike [current], it isn't cleared when the current | 703 // the block is open, but unlike [current], it isn't cleared when the current |
| 704 // block is closed. | 704 // block is closed. |
| 705 HBasicBlock lastOpenedBlock; | 705 HBasicBlock lastOpenedBlock; |
| 706 | 706 |
| 707 // Linked list of active break-handlers. Will be removed in the order | 707 // Linked list of active break-handlers. Will be removed in the order |
| 708 // they are added. | 708 // they are added. |
| 709 BreakHandler currentBreakHandler = const NullBreakHandler(); | 709 BreakHandler currentBreakHandler = const NullBreakHandler(); |
| 710 // The break handler to use for an upcoming loop statement (temporarily set | |
| 711 // if a labeled statement is labeling a loop). | |
| 712 BreakHandler loopBreakHandler = null; | |
| 713 | 710 |
| 714 SsaBuilder(Compiler compiler, WorkItem work) | 711 SsaBuilder(Compiler compiler, WorkItem work) |
| 715 : this.compiler = compiler, | 712 : this.compiler = compiler, |
| 716 this.work = work, | 713 this.work = work, |
| 717 interceptors = compiler.builder.interceptors, | 714 interceptors = compiler.builder.interceptors, |
| 718 methodInterceptionEnabled = true, | 715 methodInterceptionEnabled = true, |
| 719 elements = work.resolutionTree, | 716 elements = work.resolutionTree, |
| 720 graph = new HGraph(), | 717 graph = new HGraph(), |
| 721 stack = new List<HInstruction>(), | 718 stack = new List<HInstruction>(), |
| 722 breakTargets = new Map<StatementElement, BreakHandler>() { | 719 breakTargets = new Map<StatementElement, BreakHandler>() { |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1001 } | 998 } |
| 1002 | 999 |
| 1003 /** | 1000 /** |
| 1004 * Creates a new loop-header block. The previous [current] block | 1001 * Creates a new loop-header block. The previous [current] block |
| 1005 * is closed with an [HGoto] and replaced by the newly created block. | 1002 * is closed with an [HGoto] and replaced by the newly created block. |
| 1006 * Also notifies the locals handler that we're entering a loop. | 1003 * Also notifies the locals handler that we're entering a loop. |
| 1007 */ | 1004 */ |
| 1008 BreakHandler beginLoopHeader(Node node) { | 1005 BreakHandler beginLoopHeader(Node node) { |
| 1009 assert(!isAborted()); | 1006 assert(!isAborted()); |
| 1010 HBasicBlock previousBlock = close(new HGoto()); | 1007 HBasicBlock previousBlock = close(new HGoto()); |
| 1011 BreakHandler breakHandler = getLoopBreakHandler(node); | 1008 BreakHandler breakHandler = getBreakHandler(node); |
| 1012 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(breakHandler.labels()); | 1009 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(breakHandler.labels()); |
| 1013 previousBlock.addSuccessor(loopEntry); | 1010 previousBlock.addSuccessor(loopEntry); |
| 1014 open(loopEntry); | 1011 open(loopEntry); |
| 1015 | 1012 |
| 1016 localsHandler.beginLoopHeader(node, loopEntry); | 1013 localsHandler.beginLoopHeader(node, loopEntry); |
| 1017 return breakHandler; | 1014 return breakHandler; |
| 1018 } | 1015 } |
| 1019 | 1016 |
| 1020 /** | 1017 /** |
| 1021 * Ends the loop: | 1018 * Ends the loop: |
| (...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1644 SourceString name = selector.namedArguments[i]; | 1641 SourceString name = selector.namedArguments[i]; |
| 1645 if (name == parameter.name) { | 1642 if (name == parameter.name) { |
| 1646 foundIndex = i; | 1643 foundIndex = i; |
| 1647 break; | 1644 break; |
| 1648 } | 1645 } |
| 1649 } | 1646 } |
| 1650 if (foundIndex != -1) { | 1647 if (foundIndex != -1) { |
| 1651 list.add(namedArguments[foundIndex]); | 1648 list.add(namedArguments[foundIndex]); |
| 1652 } else { | 1649 } else { |
| 1653 Constant constant = compiler.compileVariable(parameter); | 1650 Constant constant = compiler.compileVariable(parameter); |
| 1654 list.add(graph.addConstant(constant)); | 1651 list.add(graph.addConstant(constant)); |
| 1655 } | 1652 } |
| 1656 } | 1653 } |
| 1657 } | 1654 } |
| 1658 } | 1655 } |
| 1659 | 1656 |
| 1660 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { | 1657 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| 1661 for (; !link.isEmpty(); link = link.tail) { | 1658 for (; !link.isEmpty(); link = link.tail) { |
| 1662 visit(link.head); | 1659 visit(link.head); |
| 1663 list.add(pop()); | 1660 list.add(pop()); |
| 1664 } | 1661 } |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2116 visitBreakStatement(BreakStatement node) { | 2113 visitBreakStatement(BreakStatement node) { |
| 2117 work.allowSpeculativeOptimization = false; | 2114 work.allowSpeculativeOptimization = false; |
| 2118 assert(!isAborted()); | 2115 assert(!isAborted()); |
| 2119 StatementElement target = elements[node]; | 2116 StatementElement target = elements[node]; |
| 2120 assert(target !== null); | 2117 assert(target !== null); |
| 2121 BreakHandler handler = breakTargets[target]; | 2118 BreakHandler handler = breakTargets[target]; |
| 2122 assert(handler !== null); | 2119 assert(handler !== null); |
| 2123 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 2120 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 2124 HBreak breakInstruction; | 2121 HBreak breakInstruction; |
| 2125 if (node.target === null) { | 2122 if (node.target === null) { |
| 2126 breakInstruction = new HBreak(); | 2123 breakInstruction = new HBreak(target); |
| 2127 } else { | 2124 } else { |
| 2128 breakInstruction = new HBreak(node.target.source); | 2125 LabelElement label = elements[node.target]; |
| 2126 breakInstruction = new HBreak(label); | |
| 2129 } | 2127 } |
| 2130 close(breakInstruction); | 2128 close(breakInstruction); |
| 2131 handler.addBreak(breakInstruction, savedLocals); | 2129 handler.addBreak(breakInstruction, savedLocals); |
| 2132 } | 2130 } |
| 2133 | 2131 |
| 2134 visitContinueStatement(ContinueStatement node) { | 2132 visitContinueStatement(ContinueStatement node) { |
| 2135 // TODO(lrn): Replace this with a real implementation of continue. | 2133 // TODO(lrn): Replace this with a real implementation of continue. |
| 2136 compiler.reportWarning(node, 'continue not implemented'); | 2134 compiler.reportWarning(node, 'continue not implemented'); |
| 2137 generateUnimplemented('continue not implemented'); | 2135 generateUnimplemented('continue not implemented'); |
| 2138 } | 2136 } |
| 2139 | 2137 |
| 2140 BreakHandler getLoopBreakHandler(Node node) { | 2138 BreakHandler getBreakHandler(Node node) { |
| 2141 StatementElement element = elements[node]; | 2139 StatementElement element = elements[node]; |
| 2142 BreakHandler handler; | 2140 if (element === null) return const NullBreakHandler(); |
| 2143 if (loopBreakHandler === null) { | 2141 return new BreakHandler(this, element); |
| 2144 if (element === null) return const NullBreakHandler(); | |
| 2145 handler = new BreakHandler(this, element); | |
| 2146 } else { | |
| 2147 handler = loopBreakHandler; | |
| 2148 loopBreakHandler = null; | |
| 2149 if (element === null) return handler; | |
| 2150 } | |
| 2151 return handler; | |
| 2152 } | 2142 } |
| 2153 | 2143 |
| 2154 visitForInStatement(ForInStatement node) { | 2144 visitForInStatement(ForInStatement node) { |
| 2155 // Generate a structure equivalent to: | 2145 // Generate a structure equivalent to: |
| 2156 // Iterator<E> $iter = <iterable>.iterator() | 2146 // Iterator<E> $iter = <iterable>.iterator() |
| 2157 // while ($iter.hasNext()) { | 2147 // while ($iter.hasNext()) { |
| 2158 // E <declaredIdentifier> = $iter.next(); | 2148 // E <declaredIdentifier> = $iter.next(); |
| 2159 // <body> | 2149 // <body> |
| 2160 // } | 2150 // } |
| 2161 localsHandler.startLoop(node); | 2151 localsHandler.startLoop(node); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2269 if (!isAborted()) { | 2259 if (!isAborted()) { |
| 2270 goto(current, joinBlock); | 2260 goto(current, joinBlock); |
| 2271 breakLocals.add(localsHandler); | 2261 breakLocals.add(localsHandler); |
| 2272 } | 2262 } |
| 2273 open(joinBlock); | 2263 open(joinBlock); |
| 2274 localsHandler = beforeLocals.mergeMultiple(breakLocals, joinBlock); | 2264 localsHandler = beforeLocals.mergeMultiple(breakLocals, joinBlock); |
| 2275 | 2265 |
| 2276 if (hasBreak) { | 2266 if (hasBreak) { |
| 2277 // There was at least one reachable break, so the label is needed. | 2267 // There was at least one reachable break, so the label is needed. |
| 2278 HLabeledBlockInformation blockInfo = | 2268 HLabeledBlockInformation blockInfo = |
| 2279 new HLabeledBlockInformation(bodyGraph, joinBlock, handler.labels()); | 2269 new HLabeledBlockInformation( |
|
floitsch
2012/03/09 16:52:15
keep on one line.
| |
| 2270 bodyGraph, joinBlock, handler.labels()); | |
| 2280 entryBlock.labeledBlockInformation = blockInfo; | 2271 entryBlock.labeledBlockInformation = blockInfo; |
| 2281 } | 2272 } |
| 2282 handler.close(); | 2273 handler.close(); |
| 2283 } | 2274 } |
| 2284 | 2275 |
| 2285 visitLiteralMap(LiteralMap node) { | 2276 visitLiteralMap(LiteralMap node) { |
| 2286 List<HInstruction> inputs = <HInstruction>[]; | 2277 List<HInstruction> inputs = <HInstruction>[]; |
| 2287 for (Link<Node> link = node.entries.nodes; | 2278 for (Link<Node> link = node.entries.nodes; |
| 2288 !link.isEmpty(); | 2279 !link.isEmpty(); |
| 2289 link = link.tail) { | 2280 link = link.tail) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2303 visit(node.value); | 2294 visit(node.value); |
| 2304 visit(node.key); | 2295 visit(node.key); |
| 2305 } | 2296 } |
| 2306 | 2297 |
| 2307 visitNamedArgument(NamedArgument node) { | 2298 visitNamedArgument(NamedArgument node) { |
| 2308 visit(node.expression); | 2299 visit(node.expression); |
| 2309 } | 2300 } |
| 2310 | 2301 |
| 2311 visitSwitchStatement(SwitchStatement node) { | 2302 visitSwitchStatement(SwitchStatement node) { |
| 2312 work.allowSpeculativeOptimization = false; | 2303 work.allowSpeculativeOptimization = false; |
| 2304 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | |
| 2305 HBasicBlock startBlock = graph.addNewBlock(); | |
| 2306 goto(current, startBlock); | |
| 2307 open(startBlock); | |
| 2313 visit(node.expression); | 2308 visit(node.expression); |
| 2314 HInstruction expression = pop(); | 2309 HInstruction expression = pop(); |
| 2310 if (node.cases.isEmpty()) { | |
| 2311 return; | |
| 2312 } | |
| 2315 Link<Node> cases = node.cases.nodes; | 2313 Link<Node> cases = node.cases.nodes; |
| 2316 int count = 0; | 2314 Element equalsHelper = interceptors.getEqualsInterceptor(); |
| 2317 handleThen() { | 2315 HInstruction target = new HStatic(equalsHelper); |
| 2318 if (cases.head.statements.nodes.isEmpty()) { | 2316 add(target); |
| 2319 compiler.unimplemented('fall-through', node: cases.head); | 2317 |
| 2318 BreakHandler breakHandler = getBreakHandler(node); | |
| 2319 | |
| 2320 void buildCompare(Expression caseExpression) { | |
|
floitsch
2012/03/09 16:52:15
Can't you move buildCompare and buildThrow into bu
Lasse Reichstein Nielsen
2012/03/12 13:05:23
I'll inline them.
| |
| 2321 visit(caseExpression); | |
| 2322 push(new HEquals(target, pop(), expression)); | |
| 2323 } | |
|
floitsch
2012/03/09 16:52:15
please add a newline after function declarations.
Lasse Reichstein Nielsen
2012/03/12 13:05:23
Done.
| |
| 2324 void buildThrow() { | |
| 2325 Element element = | |
| 2326 compiler.findHelper(const SourceString("getFallThroughError")); | |
| 2327 push(new HStatic(element)); | |
| 2328 HInstruction error = new HInvokeStatic( | |
| 2329 Selector.INVOCATION_0, <HInstruction>[pop()]); | |
| 2330 add(error); | |
| 2331 close(new HThrow(error)); | |
| 2332 } | |
| 2333 buildSwitchCases(cases, buildCompare, buildThrow); | |
| 2334 | |
| 2335 HBasicBlock lastBlock = lastOpenedBlock; | |
| 2336 | |
| 2337 // Create merge block for break targets. | |
| 2338 HBasicBlock joinBlock = new HBasicBlock(); | |
| 2339 List<LocalsHandler> caseLocals = <LocalsHandler>[]; | |
| 2340 breakHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { | |
| 2341 instruction.block.addSuccessor(joinBlock); | |
| 2342 caseLocals.add(locals); | |
| 2343 }); | |
| 2344 if (!isAborted()) { | |
| 2345 caseLocals.add(localsHandler); | |
| 2346 } | |
| 2347 if (caseLocals.length != 0) { | |
| 2348 graph.addBlock(joinBlock); | |
| 2349 if (!isAborted()) { | |
| 2350 goto(current, joinBlock); | |
| 2320 } | 2351 } |
| 2321 visit(cases.head.statements); | 2352 open(joinBlock); |
| 2322 cases = cases.tail; | 2353 if (caseLocals.length == 1) { |
| 2354 localsHandler = caseLocals[0]; | |
| 2355 } else { | |
| 2356 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock); | |
| 2357 } | |
| 2358 } else { | |
| 2359 // The joinblock is not used. | |
| 2360 joinBlock = null; | |
| 2323 } | 2361 } |
| 2324 handleElse() { | 2362 startBlock.labeledBlockInformation = new HLabeledBlockInformation.implicit( |
| 2325 if (cases.isEmpty()) return; | 2363 new SubGraph(startBlock, lastBlock), |
| 2326 if (cases.head.asDefaultCase() !== null) { | 2364 joinBlock, |
| 2327 stack.add(graph.addConstantBool(true)); | 2365 elements[node]); |
| 2328 if (!cases.tail.isEmpty()) { | 2366 } |
| 2329 compiler.unimplemented('default case not last', node: cases.head); | 2367 |
| 2330 } | 2368 |
| 2331 } else { | 2369 // Recursively build an if/else structure to match the cases. |
| 2332 SwitchCase switchCase = cases.head; | 2370 buildSwitchCases(Link<Node> cases, |
| 2333 visit(switchCase.expression); | 2371 Function buildCompare, |
| 2334 HInstruction caseExpression = pop(); | 2372 Function buildThrow) { |
| 2335 Element equalsHelper = interceptors.getEqualsInterceptor(); | 2373 SwitchCase node = cases.head; |
| 2336 HInstruction target = new HStatic(equalsHelper); | 2374 // TODO(lrn): Handle labels and continues. |
| 2337 add(target); | 2375 |
| 2338 push(new HEquals(target, caseExpression, expression)); | 2376 // Called for the statements on all but the last case block. |
| 2377 // Ensures that a user expecting a fallthrough gets an error. | |
| 2378 void visitStatementsAndAbort() { | |
| 2379 visit(node.statements); | |
| 2380 if (!isAborted()) { | |
| 2381 compiler.reportWarning(node, 'Missing break at end of switch case'); | |
| 2382 buildThrow(); | |
| 2339 } | 2383 } |
| 2340 handleIf(handleThen, handleElse); | |
| 2341 } | 2384 } |
| 2342 | 2385 |
| 2343 localsHandler.startLoop(node); | 2386 Link<Node> expressions = node.expressions.nodes; |
| 2344 BreakHandler breakHandler = beginLoopHeader(node); | 2387 if (expressions.isEmpty()) { |
| 2345 HBasicBlock loopEntryBlock = current; | 2388 // Default case with no expressions. |
| 2346 localsHandler.enterLoopBody(node); | 2389 if (!node.isDefaultCase) { |
| 2347 | 2390 compiler.internalError("Case with no expression and not default"); |
| 2348 handleElse(); | 2391 } |
| 2349 | 2392 visit(node.statements); |
| 2350 if (isAborted()) { | 2393 return; |
| 2351 compiler.unimplemented("SsaBuilder for loop with aborting body", | |
| 2352 node: node); | |
| 2353 } | 2394 } |
| 2354 | 2395 |
| 2355 HBasicBlock bodyExitBlock = close(new HGoto()); | 2396 // Recursively build the test conditions. |
| 2356 HBasicBlock conditionBlock = addNewBlock(); | 2397 HInstruction buildTests(Link<Node> expressions, HInstruction left) { |
|
floitsch
2012/03/09 16:52:15
This looks a lot like the visitLogicalAndOr. I vot
Lasse Reichstein Nielsen
2012/03/12 13:05:23
Good idea.
| |
| 2357 bodyExitBlock.addSuccessor(conditionBlock); | 2398 // previous is a boolean instruction. |
|
floitsch
2012/03/09 16:52:15
'previous' is still here.
Lasse Reichstein Nielsen
2012/03/12 13:05:23
Not any more. And good riddance.
| |
| 2358 open(conditionBlock); | 2399 if (expressions.isEmpty()) return left; |
| 2359 stack.add(graph.addConstantBool(false)); | 2400 push(new HNot(left)); |
| 2360 | 2401 |
| 2361 conditionBlock = close(new HLoopBranch(popBoolified(), | 2402 HIf branch = new HIf(pop(), false); |
| 2362 HLoopBranch.DO_WHILE_LOOP)); | 2403 HBasicBlock leftBlock = close(branch); |
| 2404 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | |
| 2363 | 2405 |
| 2364 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge. | 2406 HBasicBlock rightBlock = addNewBlock(); |
| 2365 loopEntryBlock.postProcessLoopHeader(); | 2407 leftBlock.addSuccessor(rightBlock); |
| 2408 open(rightBlock); | |
| 2366 | 2409 |
| 2367 endLoop(loopEntryBlock, conditionBlock, breakHandler); | 2410 buildCompare(expressions.head); |
| 2411 HInstruction right = buildTests(expressions.tail, popBoolified()); | |
| 2412 | |
| 2413 SubGraph rightGraph = new SubGraph(rightBlock, current); | |
| 2414 | |
| 2415 rightBlock = close(new HGoto()); | |
| 2416 HBasicBlock joinBlock = addNewBlock(); | |
| 2417 leftBlock.addSuccessor(joinBlock); | |
| 2418 rightBlock.addSuccessor(joinBlock); | |
| 2419 open(joinBlock); | |
| 2420 | |
| 2421 branch.blockInformation = | |
| 2422 new HIfBlockInformation(branch, rightGraph, null, joinBlock); | |
| 2423 | |
| 2424 localsHandler.mergeWith(savedLocals, joinBlock); | |
| 2425 HPhi result = new HPhi.manyInputs(null, [left, right]); | |
| 2426 joinBlock.addPhi(result); | |
| 2427 return result; | |
| 2428 } | |
| 2429 | |
| 2430 buildCompare(expressions.head); | |
| 2431 HInstruction result = buildTests(expressions.tail, popBoolified()); | |
| 2432 | |
| 2433 if (node.isDefaultCase) { | |
| 2434 // Don't actually use the condition result. | |
| 2435 visitStatementsAndAbort(); | |
| 2436 } else { | |
| 2437 stack.add(result); | |
| 2438 if (cases.tail.isEmpty()) { | |
| 2439 handleIf(() { visit(node.statements); }, null); | |
| 2440 } else { | |
| 2441 handleIf(() { visitStatementsAndAbort(); }, | |
| 2442 () { buildSwitchCases(cases.tail, | |
| 2443 buildCompare, buildThrow); }); | |
| 2444 } | |
| 2445 } | |
| 2446 } | |
| 2447 | |
| 2448 visitSwitchCase(SwitchCase node) { | |
| 2449 unreachable(); | |
| 2368 } | 2450 } |
| 2369 | 2451 |
| 2370 visitTryStatement(TryStatement node) { | 2452 visitTryStatement(TryStatement node) { |
| 2371 work.allowSpeculativeOptimization = false; | 2453 work.allowSpeculativeOptimization = false; |
| 2372 assert(!work.isBailoutVersion()); | 2454 assert(!work.isBailoutVersion()); |
| 2373 HBasicBlock enterBlock = graph.addNewBlock(); | 2455 HBasicBlock enterBlock = graph.addNewBlock(); |
| 2374 close(new HGoto()).addSuccessor(enterBlock); | 2456 close(new HGoto()).addSuccessor(enterBlock); |
| 2375 open(enterBlock); | 2457 open(enterBlock); |
| 2376 HTry tryInstruction = new HTry(); | 2458 HTry tryInstruction = new HTry(); |
| 2377 List<HBasicBlock> blocks = <HBasicBlock>[]; | 2459 List<HBasicBlock> blocks = <HBasicBlock>[]; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2489 // Normally, we would call [close] here. However, then we hit | 2571 // Normally, we would call [close] here. However, then we hit |
| 2490 // another unimplemented feature: aborting loop body. Simply | 2572 // another unimplemented feature: aborting loop body. Simply |
| 2491 // calling [add] does not work as it asserts that the instruction | 2573 // calling [add] does not work as it asserts that the instruction |
| 2492 // isn't a control flow instruction. So we inline parts of [add]. | 2574 // isn't a control flow instruction. So we inline parts of [add]. |
| 2493 current.addAfter(current.last, new HThrow(message)); | 2575 current.addAfter(current.last, new HThrow(message)); |
| 2494 if (isExpression) { | 2576 if (isExpression) { |
| 2495 stack.add(graph.addConstantNull()); | 2577 stack.add(graph.addConstantNull()); |
| 2496 } | 2578 } |
| 2497 } | 2579 } |
| 2498 } | 2580 } |
| OLD | NEW |