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); | 620 void addBreak(HBreak breakInstruction); |
| 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) { unreachable(); } | 631 void addBreak(HBreak breakInstruction) { unreachable(); } |
| 632 void forEachBreak(Function ignored) { } | 632 void forEachBreak(Function ignored) { } |
| 633 void close() { } | 633 void close() { } |
| 634 List<SourceString> labels() => const <SourceString>[]; | 634 List<LabelElement> labels() => const <LabelElement>[]; |
| 635 } | 635 } |
| 636 | 636 |
| 637 // Records breaks until a target block is available. | 637 // Records breaks until a target block is available. |
| 638 // Breaks are always forward jumps. | 638 // Breaks are always forward jumps. |
| 639 class BreakHandlerImpl implements BreakHandler { | 639 class BreakHandlerImpl implements BreakHandler { |
| 640 final BreakHandler previous; | 640 final BreakHandler previous; |
| 641 final SsaBuilder builder; | 641 final SsaBuilder builder; |
| 642 final StatementElement target; | 642 final StatementElement target; |
| 643 final List<BreakHandlerEntry> breaks; | 643 final List<BreakHandlerEntry> breaks; |
| 644 BreakHandlerImpl(SsaBuilder builder, this.target) | 644 BreakHandlerImpl(SsaBuilder builder, this.target) |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 661 } | 661 } |
| 662 } | 662 } |
| 663 | 663 |
| 664 void close() { | 664 void close() { |
| 665 assert(builder.currentBreakHandler === this); | 665 assert(builder.currentBreakHandler === this); |
| 666 // The mapping from StatementElement to BreakHandler is no longer needed. | 666 // The mapping from StatementElement to BreakHandler is no longer needed. |
| 667 builder.breakTargets.remove(target); | 667 builder.breakTargets.remove(target); |
| 668 builder.currentBreakHandler = previous; | 668 builder.currentBreakHandler = previous; |
| 669 } | 669 } |
| 670 | 670 |
| 671 List<SourceString> labels() { | 671 List<LabelElement> labels() { |
| 672 List<SourceString> result = null; | 672 List<LabelElement> result = null; |
| 673 for (LabelElement element in target.labels) { | 673 for (LabelElement element in target.labels) { |
| 674 if (element.isBreakTarget) { | 674 if (element.isBreakTarget) { |
| 675 if (result === null) result = <SourceString>[]; | 675 if (result === null) result = <LabelElement>[]; |
| 676 result.add(element.label.source); | 676 result.add(element); |
| 677 } | 677 } |
| 678 } | 678 } |
| 679 return (result === null) ? const <SourceString>[] : result; | 679 return (result === null) ? const <LabelElement>[] : result; |
| 680 } | 680 } |
| 681 } | 681 } |
| 682 | 682 |
| 683 class SsaBuilder implements Visitor { | 683 class SsaBuilder implements Visitor { |
| 684 final Compiler compiler; | 684 final Compiler compiler; |
| 685 TreeElements elements; | 685 TreeElements elements; |
| 686 final Interceptors interceptors; | 686 final Interceptors interceptors; |
| 687 final WorkItem work; | 687 final WorkItem work; |
| 688 bool methodInterceptionEnabled; | 688 bool methodInterceptionEnabled; |
| 689 HGraph graph; | 689 HGraph graph; |
| 690 LocalsHandler localsHandler; | 690 LocalsHandler localsHandler; |
| 691 HInstruction rethrowableException; | 691 HInstruction rethrowableException; |
| 692 | 692 |
| 693 Map<StatementElement, BreakHandler> breakTargets; | 693 Map<StatementElement, BreakHandler> breakTargets; |
| 694 | 694 |
| 695 // We build the Ssa graph by simulating a stack machine. | 695 // We build the Ssa graph by simulating a stack machine. |
| 696 List<HInstruction> stack; | 696 List<HInstruction> stack; |
| 697 | 697 |
| 698 // The current block to add instructions to. Might be null, if we are | 698 // The current block to add instructions to. Might be null, if we are |
| 699 // visiting dead code. | 699 // visiting dead code. |
| 700 HBasicBlock current; | 700 HBasicBlock current; |
| 701 // The most recently opened block. Has the same value as [current] while | 701 // The most recently opened block. Has the same value as [current] while |
| 702 // the block is open, but unlike [current], it isn't cleared when the current | 702 // the block is open, but unlike [current], it isn't cleared when the current |
| 703 // block is closed. | 703 // block is closed. |
| 704 HBasicBlock lastOpenedBlock; | 704 HBasicBlock lastOpenedBlock; |
| 705 | 705 |
| 706 // Linked list of active break-handlers. Will be removed in the order | 706 // Linked list of active break-handlers. Will be removed in the order |
| 707 // they are added. | 707 // they are added. |
| 708 BreakHandler currentBreakHandler = const NullBreakHandler(); | 708 BreakHandler currentBreakHandler = const NullBreakHandler(); |
| 709 // The break handler to use for an upcoming loop statement (temporarily set | |
| 710 // if a labeled statement is labeling a loop). | |
| 711 BreakHandler loopBreakHandler = null; | |
| 712 | 709 |
| 713 SsaBuilder(Compiler compiler, WorkItem work) | 710 SsaBuilder(Compiler compiler, WorkItem work) |
| 714 : this.compiler = compiler, | 711 : this.compiler = compiler, |
| 715 this.work = work, | 712 this.work = work, |
| 716 interceptors = compiler.builder.interceptors, | 713 interceptors = compiler.builder.interceptors, |
| 717 methodInterceptionEnabled = true, | 714 methodInterceptionEnabled = true, |
| 718 elements = work.resolutionTree, | 715 elements = work.resolutionTree, |
| 719 graph = new HGraph(), | 716 graph = new HGraph(), |
| 720 stack = new List<HInstruction>(), | 717 stack = new List<HInstruction>(), |
| 721 breakTargets = new Map<StatementElement, BreakHandler>() { | 718 breakTargets = new Map<StatementElement, BreakHandler>() { |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1000 } | 997 } |
| 1001 | 998 |
| 1002 /** | 999 /** |
| 1003 * Creates a new loop-header block. The previous [current] block | 1000 * Creates a new loop-header block. The previous [current] block |
| 1004 * is closed with an [HGoto] and replaced by the newly created block. | 1001 * is closed with an [HGoto] and replaced by the newly created block. |
| 1005 * Also notifies the locals handler that we're entering a loop. | 1002 * Also notifies the locals handler that we're entering a loop. |
| 1006 */ | 1003 */ |
| 1007 BreakHandler beginLoopHeader(Node node) { | 1004 BreakHandler beginLoopHeader(Node node) { |
| 1008 assert(!isAborted()); | 1005 assert(!isAborted()); |
| 1009 HBasicBlock previousBlock = close(new HGoto()); | 1006 HBasicBlock previousBlock = close(new HGoto()); |
| 1010 BreakHandler breakHandler = getLoopBreakHandler(node); | 1007 BreakHandler breakHandler = getBreakHandler(node); |
| 1011 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(breakHandler.labels()); | 1008 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(breakHandler.labels()); |
| 1012 previousBlock.addSuccessor(loopEntry); | 1009 previousBlock.addSuccessor(loopEntry); |
| 1013 open(loopEntry); | 1010 open(loopEntry); |
| 1014 | 1011 |
| 1015 localsHandler.beginLoopHeader(node, loopEntry); | 1012 localsHandler.beginLoopHeader(node, loopEntry); |
| 1016 return breakHandler; | 1013 return breakHandler; |
| 1017 } | 1014 } |
| 1018 | 1015 |
| 1019 /** | 1016 /** |
| 1020 * Ends the loop: | 1017 * Ends the loop: |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1322 assert(op.token.kind !== PLUS_TOKEN); | 1319 assert(op.token.kind !== PLUS_TOKEN); |
| 1323 HInstruction operand = pop(); | 1320 HInstruction operand = pop(); |
| 1324 // See if we can constant-fold right away. This avoids rewrites later on. | 1321 // See if we can constant-fold right away. This avoids rewrites later on. |
| 1325 if (operand is HConstant) { | 1322 if (operand is HConstant) { |
| 1326 HConstant typedOperand = operand; | 1323 HConstant typedOperand = operand; |
| 1327 Constant constant = typedOperand.constant; | 1324 Constant constant = typedOperand.constant; |
| 1328 Constant folded = constant.unaryFold(op.source.stringValue); | 1325 Constant folded = constant.unaryFold(op.source.stringValue); |
| 1329 if (folded !== null) { | 1326 if (folded !== null) { |
| 1330 stack.add(graph.addConstant(folded)); | 1327 stack.add(graph.addConstant(folded)); |
| 1331 return; | 1328 return; |
| 1332 } | 1329 } |
| 1333 } | 1330 } |
| 1334 HInstruction target = | 1331 HInstruction target = |
| 1335 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); | 1332 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); |
| 1336 add(target); | 1333 add(target); |
| 1337 switch (op.source.stringValue) { | 1334 switch (op.source.stringValue) { |
| 1338 case "-": push(new HNegate(target, operand)); break; | 1335 case "-": push(new HNegate(target, operand)); break; |
| 1339 case "~": push(new HBitNot(target, operand)); break; | 1336 case "~": push(new HBitNot(target, operand)); break; |
| 1340 default: unreachable(); | 1337 default: unreachable(); |
| 1341 } | 1338 } |
| 1342 } | 1339 } |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1637 SourceString name = selector.namedArguments[i]; | 1634 SourceString name = selector.namedArguments[i]; |
| 1638 if (name == parameter.name) { | 1635 if (name == parameter.name) { |
| 1639 foundIndex = i; | 1636 foundIndex = i; |
| 1640 break; | 1637 break; |
| 1641 } | 1638 } |
| 1642 } | 1639 } |
| 1643 if (foundIndex != -1) { | 1640 if (foundIndex != -1) { |
| 1644 list.add(namedArguments[foundIndex]); | 1641 list.add(namedArguments[foundIndex]); |
| 1645 } else { | 1642 } else { |
| 1646 Constant constant = compiler.compileVariable(parameter); | 1643 Constant constant = compiler.compileVariable(parameter); |
| 1647 list.add(graph.addConstant(constant)); | 1644 list.add(graph.addConstant(constant)); |
| 1648 } | 1645 } |
| 1649 } | 1646 } |
| 1650 } | 1647 } |
| 1651 } | 1648 } |
| 1652 | 1649 |
| 1653 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { | 1650 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| 1654 for (; !link.isEmpty(); link = link.tail) { | 1651 for (; !link.isEmpty(); link = link.tail) { |
| 1655 visit(link.head); | 1652 visit(link.head); |
| 1656 list.add(pop()); | 1653 list.add(pop()); |
| 1657 } | 1654 } |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2104 work.allowSpeculativeOptimization = false; | 2101 work.allowSpeculativeOptimization = false; |
| 2105 assert(!isAborted()); | 2102 assert(!isAborted()); |
| 2106 StatementElement target = elements[node]; | 2103 StatementElement target = elements[node]; |
| 2107 assert(target !== null); | 2104 assert(target !== null); |
| 2108 BreakHandler handler = breakTargets[target]; | 2105 BreakHandler handler = breakTargets[target]; |
| 2109 assert(handler !== null); | 2106 assert(handler !== null); |
| 2110 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 2107 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 2111 HBreak breakInstruction; | 2108 HBreak breakInstruction; |
| 2112 if (node.target === null) { | 2109 if (node.target === null) { |
| 2113 breakInstruction = new HBreak(); | 2110 breakInstruction = new HBreak(); |
| 2114 } else { | 2111 } else { |
| 2115 breakInstruction = new HBreak(node.target.source); | 2112 LabelElement label = elements[node.target]; |
| 2113 breakInstruction = new HBreak(label); | |
| 2116 } | 2114 } |
| 2117 close(breakInstruction); | 2115 close(breakInstruction); |
| 2118 handler.addBreak(breakInstruction, savedLocals); | 2116 handler.addBreak(breakInstruction, savedLocals); |
| 2119 } | 2117 } |
| 2120 | 2118 |
| 2121 visitContinueStatement(ContinueStatement node) { | 2119 visitContinueStatement(ContinueStatement node) { |
| 2122 // TODO(lrn): Replace this with a real implementation of continue. | 2120 // TODO(lrn): Replace this with a real implementation of continue. |
| 2123 compiler.reportWarning(node, 'continue not implemented'); | 2121 compiler.reportWarning(node, 'continue not implemented'); |
| 2124 generateUnimplemented('continue not implemented'); | 2122 generateUnimplemented('continue not implemented'); |
| 2125 } | 2123 } |
| 2126 | 2124 |
| 2127 BreakHandler getLoopBreakHandler(Node node) { | 2125 BreakHandler getBreakHandler(Node node) { |
| 2128 StatementElement element = elements[node]; | 2126 StatementElement element = elements[node]; |
| 2129 BreakHandler handler; | 2127 if (element === null) return const NullBreakHandler(); |
| 2130 if (loopBreakHandler === null) { | 2128 return new BreakHandler(this, element); |
| 2131 if (element === null) return const NullBreakHandler(); | |
| 2132 handler = new BreakHandler(this, element); | |
| 2133 } else { | |
| 2134 handler = loopBreakHandler; | |
| 2135 loopBreakHandler = null; | |
| 2136 if (element === null) return handler; | |
| 2137 } | |
| 2138 return handler; | |
| 2139 } | 2129 } |
| 2140 | 2130 |
| 2141 visitForInStatement(ForInStatement node) { | 2131 visitForInStatement(ForInStatement node) { |
| 2142 // Generate a structure equivalent to: | 2132 // Generate a structure equivalent to: |
| 2143 // Iterator<E> $iter = <iterable>.iterator() | 2133 // Iterator<E> $iter = <iterable>.iterator() |
| 2144 // while ($iter.hasNext()) { | 2134 // while ($iter.hasNext()) { |
| 2145 // E <declaredIdentifier> = $iter.next(); | 2135 // E <declaredIdentifier> = $iter.next(); |
| 2146 // <body> | 2136 // <body> |
| 2147 // } | 2137 // } |
| 2148 localsHandler.startLoop(node); | 2138 localsHandler.startLoop(node); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2290 visit(node.value); | 2280 visit(node.value); |
| 2291 visit(node.key); | 2281 visit(node.key); |
| 2292 } | 2282 } |
| 2293 | 2283 |
| 2294 visitNamedArgument(NamedArgument node) { | 2284 visitNamedArgument(NamedArgument node) { |
| 2295 visit(node.expression); | 2285 visit(node.expression); |
| 2296 } | 2286 } |
| 2297 | 2287 |
| 2298 visitSwitchStatement(SwitchStatement node) { | 2288 visitSwitchStatement(SwitchStatement node) { |
| 2299 work.allowSpeculativeOptimization = false; | 2289 work.allowSpeculativeOptimization = false; |
| 2290 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | |
| 2300 visit(node.expression); | 2291 visit(node.expression); |
| 2301 HInstruction expression = pop(); | 2292 HInstruction expression = pop(); |
| 2293 if (node.cases.isEmpty()) { | |
| 2294 return; | |
| 2295 } | |
| 2302 Link<Node> cases = node.cases.nodes; | 2296 Link<Node> cases = node.cases.nodes; |
| 2303 int count = 0; | 2297 Element equalsHelper = interceptors.getEqualsInterceptor(); |
| 2304 handleThen() { | 2298 HInstruction target = new HStatic(equalsHelper); |
| 2305 if (cases.head.statements.nodes.isEmpty()) { | 2299 add(target); |
| 2306 compiler.unimplemented('fall-through', node: cases.head); | 2300 |
| 2301 BreakHandler breakHandler = getBreakHandler(node); | |
| 2302 | |
| 2303 void buildCompare(Expression caseExpression) { | |
| 2304 visit(caseExpression); | |
| 2305 push(new HEquals(target, pop(), expression)); | |
| 2306 } | |
| 2307 buildSwitchCases(cases, buildCompare); | |
| 2308 | |
| 2309 // Create merge block for break targets. | |
| 2310 HBasicBlock joinBlock = new HBasicBlock(); | |
| 2311 List<LocalsHandler> caseLocals = <LocalsHandler>[]; | |
| 2312 breakHandler.forEachBreak((HBreak instruction, LocalsHandler locals) { | |
| 2313 instruction.block.addSuccessor(joinBlock); | |
| 2314 caseLocals.add(locals); | |
| 2315 }); | |
| 2316 if (caseLocals.length == 0) return; | |
| 2317 if (!isAborted()) { | |
| 2318 caseLocals.add(localsHandler); | |
| 2319 goto(current, joinBlock); | |
| 2320 } | |
| 2321 graph.addBlock(joinBlock); | |
| 2322 open(joinBlock); | |
| 2323 if (caseLocals.length == 1) { | |
| 2324 localsHandler = caseLocals[0]; | |
| 2325 } else { | |
| 2326 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock); | |
| 2327 } | |
| 2328 } | |
| 2329 | |
| 2330 | |
| 2331 // Recursively build an if/else structure to match the cases. | |
| 2332 buildSwitchCases(Link<Node> cases, Function buildCompare) { | |
| 2333 SwitchCase node = cases.head; | |
| 2334 // TODO(lrn): Handle labels and continues. | |
| 2335 | |
| 2336 void visitStatementsAndAbort() { | |
| 2337 visit(node.statements); | |
| 2338 if (!isAborted()) { | |
| 2339 compiler.cancel('Missing break at end of switch case', node: node); | |
| 2340 HBreak breakInstruction = new HBreak(); | |
| 2341 close(breakInstruction); | |
| 2342 currentBreakHandler.addBreak(breakInstruction, localsHandler); | |
| 2307 } | 2343 } |
| 2308 visit(cases.head.statements); | |
| 2309 cases = cases.tail; | |
| 2310 } | |
| 2311 handleElse() { | |
| 2312 if (cases.isEmpty()) return; | |
| 2313 if (cases.head.asDefaultCase() !== null) { | |
| 2314 stack.add(graph.addConstantBool(true)); | |
| 2315 if (!cases.tail.isEmpty()) { | |
| 2316 compiler.unimplemented('default case not last', node: cases.head); | |
| 2317 } | |
| 2318 } else { | |
| 2319 SwitchCase switchCase = cases.head; | |
| 2320 visit(switchCase.expression); | |
| 2321 HInstruction caseExpression = pop(); | |
| 2322 Element equalsHelper = interceptors.getEqualsInterceptor(); | |
| 2323 HInstruction target = new HStatic(equalsHelper); | |
| 2324 add(target); | |
| 2325 push(new HEquals(target, caseExpression, expression)); | |
| 2326 } | |
| 2327 handleIf(handleThen, handleElse); | |
| 2328 } | 2344 } |
| 2329 | 2345 |
| 2330 localsHandler.startLoop(node); | 2346 Link<Node> expressions = node.expressions.nodes; |
| 2331 BreakHandler breakHandler = beginLoopHeader(node); | 2347 if (expressions.isEmpty()) { |
| 2332 HBasicBlock loopEntryBlock = current; | 2348 // Default case with no expressions. |
| 2333 localsHandler.enterLoopBody(node); | 2349 if (!node.isDefaultCase) { |
| 2334 | 2350 compiler.internalError("Case with no expression and not default"); |
| 2335 handleElse(); | 2351 } |
| 2336 | 2352 visitStatementsAndAbort(); |
| 2337 if (isAborted()) { | 2353 return; |
| 2338 compiler.unimplemented("SsaBuilder for loop with aborting body", | |
| 2339 node: node); | |
| 2340 } | 2354 } |
| 2341 | 2355 |
| 2342 HBasicBlock bodyExitBlock = close(new HGoto()); | 2356 // Recursively build the test conditions. |
| 2343 HBasicBlock conditionBlock = addNewBlock(); | 2357 HInstruction buildTests(Link<Node> expressions, HInstruction left) { |
| 2344 bodyExitBlock.addSuccessor(conditionBlock); | 2358 // previous is a boolean instruction. |
|
floitsch
2012/03/08 16:35:14
P
Lasse Reichstein Nielsen
2012/03/08 18:35:40
Whoops, 'previous'->'left'.
| |
| 2345 open(conditionBlock); | 2359 if (expressions.isEmpty()) return left; |
| 2346 stack.add(graph.addConstantBool(false)); | 2360 push(new HNot(left)); |
| 2347 | 2361 |
| 2348 conditionBlock = close(new HLoopBranch(popBoolified(), | 2362 HIf branch = new HIf(pop(), false); |
| 2349 HLoopBranch.DO_WHILE_LOOP)); | 2363 HBasicBlock leftBlock = close(branch); |
| 2364 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | |
| 2350 | 2365 |
| 2351 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge. | 2366 HBasicBlock rightBlock = addNewBlock(); |
| 2352 loopEntryBlock.postProcessLoopHeader(); | 2367 leftBlock.addSuccessor(rightBlock); |
| 2368 open(rightBlock); | |
| 2353 | 2369 |
| 2354 endLoop(loopEntryBlock, conditionBlock, breakHandler); | 2370 buildCompare(expressions.head); |
| 2371 HInstruction right = buildTests(expressions.tail, popBoolified()); | |
| 2372 | |
| 2373 SubGraph rightGraph = new SubGraph(rightBlock, current); | |
| 2374 | |
| 2375 rightBlock = close(new HGoto()); | |
| 2376 HBasicBlock joinBlock = addNewBlock(); | |
| 2377 leftBlock.addSuccessor(joinBlock); | |
| 2378 rightBlock.addSuccessor(joinBlock); | |
| 2379 open(joinBlock); | |
| 2380 | |
| 2381 branch.blockInformation = | |
| 2382 new HIfBlockInformation(branch, rightGraph, null, joinBlock); | |
| 2383 | |
| 2384 localsHandler.mergeWith(savedLocals, joinBlock); | |
| 2385 HPhi result = new HPhi.manyInputs(null, [left, right]); | |
| 2386 joinBlock.addPhi(result); | |
| 2387 return result; | |
| 2388 } | |
| 2389 | |
| 2390 buildCompare(expressions.head); | |
| 2391 HInstruction result = buildTests(expressions.tail, popBoolified()); | |
| 2392 | |
| 2393 if (node.isDefaultCase) { | |
| 2394 // Don't actually use the condition result. | |
| 2395 visitStatementsAndAbort(); | |
| 2396 } else { | |
| 2397 stack.add(result); | |
| 2398 handleIf(() { visitStatementsAndAbort(); }, | |
| 2399 cases.tail.isEmpty() ? | |
| 2400 null : | |
| 2401 () { buildSwitchCases(cases.tail, buildCompare); }); | |
| 2402 } | |
| 2403 } | |
| 2404 | |
| 2405 visitSwitchCase(SwitchCase node) { | |
| 2406 unreachable(); | |
| 2355 } | 2407 } |
| 2356 | 2408 |
| 2357 visitTryStatement(TryStatement node) { | 2409 visitTryStatement(TryStatement node) { |
| 2358 work.allowSpeculativeOptimization = false; | 2410 work.allowSpeculativeOptimization = false; |
| 2359 assert(!work.isBailoutVersion()); | 2411 assert(!work.isBailoutVersion()); |
| 2360 HBasicBlock enterBlock = graph.addNewBlock(); | 2412 HBasicBlock enterBlock = graph.addNewBlock(); |
| 2361 close(new HGoto()).addSuccessor(enterBlock); | 2413 close(new HGoto()).addSuccessor(enterBlock); |
| 2362 open(enterBlock); | 2414 open(enterBlock); |
| 2363 HTry tryInstruction = new HTry(); | 2415 HTry tryInstruction = new HTry(); |
| 2364 List<HBasicBlock> blocks = <HBasicBlock>[]; | 2416 List<HBasicBlock> blocks = <HBasicBlock>[]; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2476 // Normally, we would call [close] here. However, then we hit | 2528 // Normally, we would call [close] here. However, then we hit |
| 2477 // another unimplemented feature: aborting loop body. Simply | 2529 // another unimplemented feature: aborting loop body. Simply |
| 2478 // calling [add] does not work as it asserts that the instruction | 2530 // calling [add] does not work as it asserts that the instruction |
| 2479 // isn't a control flow instruction. So we inline parts of [add]. | 2531 // isn't a control flow instruction. So we inline parts of [add]. |
| 2480 current.addAfter(current.last, new HThrow(message)); | 2532 current.addAfter(current.last, new HThrow(message)); |
| 2481 if (isExpression) { | 2533 if (isExpression) { |
| 2482 stack.add(graph.addConstantNull()); | 2534 stack.add(graph.addConstantNull()); |
| 2483 } | 2535 } |
| 2484 } | 2536 } |
| 2485 } | 2537 } |
| OLD | NEW |