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

Side by Side Diff: frog/leg/ssa/builder.dart

Issue 9632018: Switch-implementation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add missing handling of default in unparser. Created 8 years, 9 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 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 597 matching lines...) Expand 10 before | Expand all | Expand 10 after
608 } 608 }
609 609
610 610
611 // Represents a single break instruction. 611 // Represents a single break instruction.
612 class BreakHandlerEntry { 612 class BreakHandlerEntry {
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 {
ahe 2012/03/13 10:17:15 Do we really need an interface for this?
Lasse Reichstein Nielsen 2012/03/13 12:09:38 Maybe not, but I like making the NullBreakHandler
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();
ahe 2012/03/13 10:17:15 I like seeing a move from SourceString to Element.
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
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 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 } 995 }
999 996
1000 /** 997 /**
1001 * Creates a new loop-header block. The previous [current] block 998 * Creates a new loop-header block. The previous [current] block
1002 * is closed with an [HGoto] and replaced by the newly created block. 999 * is closed with an [HGoto] and replaced by the newly created block.
1003 * Also notifies the locals handler that we're entering a loop. 1000 * Also notifies the locals handler that we're entering a loop.
1004 */ 1001 */
1005 BreakHandler beginLoopHeader(Node node) { 1002 BreakHandler beginLoopHeader(Node node) {
1006 assert(!isAborted()); 1003 assert(!isAborted());
1007 HBasicBlock previousBlock = close(new HGoto()); 1004 HBasicBlock previousBlock = close(new HGoto());
1008 BreakHandler breakHandler = getLoopBreakHandler(node); 1005 BreakHandler breakHandler = getBreakHandler(node);
1009 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(breakHandler.labels()); 1006 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(breakHandler.labels());
1010 previousBlock.addSuccessor(loopEntry); 1007 previousBlock.addSuccessor(loopEntry);
1011 open(loopEntry); 1008 open(loopEntry);
1012 1009
1013 localsHandler.beginLoopHeader(node, loopEntry); 1010 localsHandler.beginLoopHeader(node, loopEntry);
1014 return breakHandler; 1011 return breakHandler;
1015 } 1012 }
1016 1013
1017 /** 1014 /**
1018 * Ends the loop: 1015 * Ends the loop:
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
1259 } else if (thenBlock !== null) { 1256 } else if (thenBlock !== null) {
1260 // The only predecessor is the then branch. 1257 // The only predecessor is the then branch.
1261 localsHandler = thenLocals; 1258 localsHandler = thenLocals;
1262 } 1259 }
1263 } 1260 }
1264 condition.blockInformation = 1261 condition.blockInformation =
1265 new HIfBlockInformation(condition, thenGraph, elseGraph, joinBlock); 1262 new HIfBlockInformation(condition, thenGraph, elseGraph, joinBlock);
1266 } 1263 }
1267 1264
1268 void visitLogicalAndOr(Send node, Operator op) { 1265 void visitLogicalAndOr(Send node, Operator op) {
1266 handleLogicalAndOr(() { visit(node.receiver); },
1267 () { visit(node.argumentsNode); },
1268 isAnd: (const SourceString("&&") == op.source));
1269 }
1270
1271
1272 void handleLogicalAndOr(void left(), void right(), [bool isAnd = true]) {
1269 // x && y is transformed into: 1273 // x && y is transformed into:
1270 // t0 = boolify(x); 1274 // t0 = boolify(x);
1271 // if (t0) t1 = boolify(y); 1275 // if (t0) t1 = boolify(y);
1272 // result = phi(t0, t1); 1276 // result = phi(t0, t1);
1273 // 1277 //
1274 // x || y is transformed into: 1278 // x || y is transformed into:
1275 // t0 = boolify(x); 1279 // t0 = boolify(x);
1276 // if (not(t0)) t1 = boolify(y); 1280 // if (not(t0)) t1 = boolify(y);
1277 // result = phi(t0, t1); 1281 // result = phi(t0, t1);
1278 bool isAnd = (const SourceString("&&") == op.source); 1282 left();
1279
1280 visit(node.receiver);
1281 HInstruction boolifiedLeft = popBoolified(); 1283 HInstruction boolifiedLeft = popBoolified();
1282 HInstruction condition; 1284 HInstruction condition;
1283 if (isAnd) { 1285 if (isAnd) {
1284 condition = boolifiedLeft; 1286 condition = boolifiedLeft;
1285 } else { 1287 } else {
1286 condition = new HNot(boolifiedLeft); 1288 condition = new HNot(boolifiedLeft);
1287 add(condition); 1289 add(condition);
1288 } 1290 }
1289 HIf branch = new HIf(condition, false); 1291 HIf branch = new HIf(condition, false);
1290 HBasicBlock leftBlock = close(branch); 1292 HBasicBlock leftBlock = close(branch);
1291 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 1293 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
1292 1294
1293 HBasicBlock rightBlock = addNewBlock(); 1295 HBasicBlock rightBlock = addNewBlock();
1294 leftBlock.addSuccessor(rightBlock); 1296 leftBlock.addSuccessor(rightBlock);
1295 open(rightBlock); 1297 open(rightBlock);
1296 visit(node.argumentsNode); 1298
1299 right();
1297 HInstruction boolifiedRight = popBoolified(); 1300 HInstruction boolifiedRight = popBoolified();
1298 SubGraph rightGraph = new SubGraph(rightBlock, current); 1301 SubGraph rightGraph = new SubGraph(rightBlock, current);
1299 rightBlock = close(new HGoto()); 1302 rightBlock = close(new HGoto());
1300 1303
1301 HBasicBlock joinBlock = addNewBlock(); 1304 HBasicBlock joinBlock = addNewBlock();
1302 leftBlock.addSuccessor(joinBlock); 1305 leftBlock.addSuccessor(joinBlock);
1303 rightBlock.addSuccessor(joinBlock); 1306 rightBlock.addSuccessor(joinBlock);
1304 open(joinBlock); 1307 open(joinBlock);
1305 1308
1306 branch.blockInformation = 1309 branch.blockInformation =
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
1641 SourceString name = selector.namedArguments[i]; 1644 SourceString name = selector.namedArguments[i];
1642 if (name == parameter.name) { 1645 if (name == parameter.name) {
1643 foundIndex = i; 1646 foundIndex = i;
1644 break; 1647 break;
1645 } 1648 }
1646 } 1649 }
1647 if (foundIndex != -1) { 1650 if (foundIndex != -1) {
1648 list.add(namedArguments[foundIndex]); 1651 list.add(namedArguments[foundIndex]);
1649 } else { 1652 } else {
1650 Constant constant = compiler.compileVariable(parameter); 1653 Constant constant = compiler.compileVariable(parameter);
1651 list.add(graph.addConstant(constant)); 1654 list.add(graph.addConstant(constant));
1652 } 1655 }
1653 } 1656 }
1654 } 1657 }
1655 } 1658 }
1656 1659
1657 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { 1660 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) {
1658 for (; !link.isEmpty(); link = link.tail) { 1661 for (; !link.isEmpty(); link = link.tail) {
1659 visit(link.head); 1662 visit(link.head);
1660 list.add(pop()); 1663 list.add(pop());
1661 } 1664 }
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
2113 visitBreakStatement(BreakStatement node) { 2116 visitBreakStatement(BreakStatement node) {
2114 work.allowSpeculativeOptimization = false; 2117 work.allowSpeculativeOptimization = false;
2115 assert(!isAborted()); 2118 assert(!isAborted());
2116 StatementElement target = elements[node]; 2119 StatementElement target = elements[node];
2117 assert(target !== null); 2120 assert(target !== null);
2118 BreakHandler handler = breakTargets[target]; 2121 BreakHandler handler = breakTargets[target];
2119 assert(handler !== null); 2122 assert(handler !== null);
2120 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 2123 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2121 HBreak breakInstruction; 2124 HBreak breakInstruction;
2122 if (node.target === null) { 2125 if (node.target === null) {
2123 breakInstruction = new HBreak(); 2126 breakInstruction = new HBreak(target);
2124 } else { 2127 } else {
2125 breakInstruction = new HBreak(node.target.source); 2128 LabelElement label = elements[node.target];
2129 breakInstruction = new HBreak(label);
2126 } 2130 }
2127 close(breakInstruction); 2131 close(breakInstruction);
2128 handler.addBreak(breakInstruction, savedLocals); 2132 handler.addBreak(breakInstruction, savedLocals);
2129 } 2133 }
2130 2134
2131 visitContinueStatement(ContinueStatement node) { 2135 visitContinueStatement(ContinueStatement node) {
2132 // TODO(lrn): Replace this with a real implementation of continue. 2136 // TODO(lrn): Replace this with a real implementation of continue.
2133 compiler.reportWarning(node, 'continue not implemented'); 2137 compiler.reportWarning(node, 'continue not implemented');
2134 generateUnimplemented('continue not implemented'); 2138 generateUnimplemented('continue not implemented');
2135 } 2139 }
2136 2140
2137 BreakHandler getLoopBreakHandler(Node node) { 2141 BreakHandler getBreakHandler(Node node) {
2138 StatementElement element = elements[node]; 2142 StatementElement element = elements[node];
2139 BreakHandler handler; 2143 if (element === null) return const NullBreakHandler();
2140 if (loopBreakHandler === null) { 2144 return new BreakHandler(this, element);
2141 if (element === null) return const NullBreakHandler();
2142 handler = new BreakHandler(this, element);
2143 } else {
2144 handler = loopBreakHandler;
2145 loopBreakHandler = null;
2146 if (element === null) return handler;
2147 }
2148 return handler;
2149 } 2145 }
2150 2146
2151 visitForInStatement(ForInStatement node) { 2147 visitForInStatement(ForInStatement node) {
2152 // Generate a structure equivalent to: 2148 // Generate a structure equivalent to:
2153 // Iterator<E> $iter = <iterable>.iterator() 2149 // Iterator<E> $iter = <iterable>.iterator()
2154 // while ($iter.hasNext()) { 2150 // while ($iter.hasNext()) {
2155 // E <declaredIdentifier> = $iter.next(); 2151 // E <declaredIdentifier> = $iter.next();
2156 // <body> 2152 // <body>
2157 // } 2153 // }
2158 localsHandler.startLoop(node); 2154 localsHandler.startLoop(node);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
2300 visit(node.value); 2296 visit(node.value);
2301 visit(node.key); 2297 visit(node.key);
2302 } 2298 }
2303 2299
2304 visitNamedArgument(NamedArgument node) { 2300 visitNamedArgument(NamedArgument node) {
2305 visit(node.expression); 2301 visit(node.expression);
2306 } 2302 }
2307 2303
2308 visitSwitchStatement(SwitchStatement node) { 2304 visitSwitchStatement(SwitchStatement node) {
2309 work.allowSpeculativeOptimization = false; 2305 work.allowSpeculativeOptimization = false;
2306 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2307 HBasicBlock startBlock = graph.addNewBlock();
2308 goto(current, startBlock);
2309 open(startBlock);
2310 visit(node.expression); 2310 visit(node.expression);
2311 HInstruction expression = pop(); 2311 HInstruction expression = pop();
2312 if (node.cases.isEmpty()) {
2313 return;
2314 }
2312 Link<Node> cases = node.cases.nodes; 2315 Link<Node> cases = node.cases.nodes;
2313 int count = 0; 2316
2314 handleThen() { 2317 BreakHandler breakHandler = getBreakHandler(node);
2315 if (cases.head.statements.nodes.isEmpty()) { 2318
2316 compiler.unimplemented('fall-through', node: cases.head); 2319 buildSwitchCases(cases, expression);
2320
2321 HBasicBlock lastBlock = lastOpenedBlock;
2322
2323 // Create merge block for break targets.
2324 HBasicBlock joinBlock = new HBasicBlock();
2325 List<LocalsHandler> caseLocals = <LocalsHandler>[];
2326 breakHandler.forEachBreak((HBreak instruction, LocalsHandler locals) {
2327 instruction.block.addSuccessor(joinBlock);
2328 caseLocals.add(locals);
2329 });
2330 if (!isAborted()) {
floitsch 2012/03/12 13:46:05 Please add comment when this happens: it's never a
Lasse Reichstein Nielsen 2012/03/13 12:09:38 Done.
2331 caseLocals.add(localsHandler);
2332 }
2333 if (caseLocals.length != 0) {
2334 graph.addBlock(joinBlock);
2335 if (!isAborted()) {
2336 goto(current, joinBlock);
2317 } 2337 }
2318 visit(cases.head.statements); 2338 open(joinBlock);
2319 cases = cases.tail; 2339 if (caseLocals.length == 1) {
2340 localsHandler = caseLocals[0];
2341 } else {
2342 localsHandler = savedLocals.mergeMultiple(caseLocals, joinBlock);
2343 }
2344 } else {
2345 // The joinblock is not used.
2346 joinBlock = null;
2320 } 2347 }
2321 handleElse() { 2348 startBlock.labeledBlockInformation = new HLabeledBlockInformation.implicit(
2322 if (cases.isEmpty()) return; 2349 new SubGraph(startBlock, lastBlock),
2323 if (cases.head.asDefaultCase() !== null) { 2350 joinBlock,
2324 stack.add(graph.addConstantBool(true)); 2351 elements[node]);
2325 if (!cases.tail.isEmpty()) { 2352 }
2326 compiler.unimplemented('default case not last', node: cases.head); 2353
2327 } 2354
2328 } else { 2355 // Recursively build an if/else structure to match the cases.
2329 SwitchCase switchCase = cases.head; 2356 buildSwitchCases(Link<Node> cases, HInstruction expression) {
2330 visit(switchCase.expression); 2357 SwitchCase node = cases.head;
2331 HInstruction caseExpression = pop(); 2358
2359 // Called for the statements on all but the last case block.
2360 // Ensures that a user expecting a fallthrough gets an error.
2361 void visitStatementsAndAbort() {
2362 visit(node.statements);
2363 if (!isAborted()) {
2364 compiler.reportWarning(node, 'Missing break at end of switch case');
floitsch 2012/03/12 13:46:05 Shouldn't that be caught earlier? If yes add at le
Lasse Reichstein Nielsen 2012/03/13 12:09:38 How? This is the first time we actually detect whe
2365 Element element =
2366 compiler.findHelper(const SourceString("getFallThroughError"));
2367 push(new HStatic(element));
2368 HInstruction error = new HInvokeStatic(
2369 Selector.INVOCATION_0, <HInstruction>[pop()]);
2370 add(error);
2371 close(new HThrow(error));
2372 }
2373 }
2374
2375 Link<Node> expressions = node.expressions.nodes;
2376 if (expressions.isEmpty()) {
2377 // Default case with no expressions.
2378 if (!node.isDefaultCase) {
2379 compiler.internalError("Case with no expression and not default");
ahe 2012/03/13 10:17:15 Please pass the node.
Lasse Reichstein Nielsen 2012/03/13 12:09:38 Done.
2380 }
2381 visit(node.statements);
2382 // This must be the final case (otherwise "default" would be invalid),
2383 // so we don't need to check for fallthrough.
2384 return;
2385 }
2386
2387 // Recursively build the test conditions. Leaves the result on the
2388 // expression stack.
2389 void buildTests(Link<Node> expressions) {
2390 // Build comparison for one case expression.
2391 void left() {
2332 Element equalsHelper = interceptors.getEqualsInterceptor(); 2392 Element equalsHelper = interceptors.getEqualsInterceptor();
2333 HInstruction target = new HStatic(equalsHelper); 2393 HInstruction target = new HStatic(equalsHelper);
2334 add(target); 2394 add(target);
2335 push(new HEquals(target, caseExpression, expression)); 2395 visit(expressions.head);
2396 push(new HEquals(target, pop(), expression));
2336 } 2397 }
2337 handleIf(handleThen, handleElse); 2398
2399 // If this is the last expression, just return it.
2400 if (expressions.tail.isEmpty()) {
2401 left();
2402 return;
2403 }
2404
2405 void right() {
2406 buildTests(expressions.tail);
2407 }
2408 handleLogicalAndOr(left, right, isAnd: false);
2338 } 2409 }
2339 2410
2340 localsHandler.startLoop(node); 2411 buildTests(expressions);
2341 BreakHandler breakHandler = beginLoopHeader(node); 2412 HInstruction result = popBoolified();
2342 HBasicBlock loopEntryBlock = current;
2343 localsHandler.enterLoopBody(node);
2344 2413
2345 handleElse(); 2414 if (node.isDefaultCase) {
2415 // Don't actually use the condition result.
2416 visitStatementsAndAbort();
2417 } else {
2418 stack.add(result);
2419 if (cases.tail.isEmpty()) {
2420 handleIf(() { visit(node.statements); }, null);
2421 } else {
2422 handleIf(() { visitStatementsAndAbort(); },
2423 () { buildSwitchCases(cases.tail, expression); });
2424 }
2425 }
2426 }
2346 2427
2347 if (isAborted()) { 2428 visitSwitchCase(SwitchCase node) {
2348 compiler.unimplemented("SsaBuilder for loop with aborting body", 2429 unreachable();
ahe 2012/03/13 10:17:15 Please make sure to pass in the node to unreachabl
Lasse Reichstein Nielsen 2012/03/13 12:09:38 I dont' think unreachable takes an argument (defin
2349 node: node);
2350 }
2351
2352 HBasicBlock bodyExitBlock = close(new HGoto());
2353 HBasicBlock conditionBlock = addNewBlock();
2354 bodyExitBlock.addSuccessor(conditionBlock);
2355 open(conditionBlock);
2356 stack.add(graph.addConstantBool(false));
2357
2358 conditionBlock = close(new HLoopBranch(popBoolified(),
2359 HLoopBranch.DO_WHILE_LOOP));
2360
2361 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge.
2362 loopEntryBlock.postProcessLoopHeader();
2363
2364 endLoop(loopEntryBlock, conditionBlock, breakHandler);
2365 } 2430 }
2366 2431
2367 visitTryStatement(TryStatement node) { 2432 visitTryStatement(TryStatement node) {
2368 work.allowSpeculativeOptimization = false; 2433 work.allowSpeculativeOptimization = false;
2369 assert(!work.isBailoutVersion()); 2434 assert(!work.isBailoutVersion());
2370 HBasicBlock enterBlock = graph.addNewBlock(); 2435 HBasicBlock enterBlock = graph.addNewBlock();
2371 close(new HGoto()).addSuccessor(enterBlock); 2436 close(new HGoto()).addSuccessor(enterBlock);
2372 open(enterBlock); 2437 open(enterBlock);
2373 HTry tryInstruction = new HTry(); 2438 HTry tryInstruction = new HTry();
2374 List<HBasicBlock> blocks = <HBasicBlock>[]; 2439 List<HBasicBlock> blocks = <HBasicBlock>[];
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
2486 // Normally, we would call [close] here. However, then we hit 2551 // Normally, we would call [close] here. However, then we hit
2487 // another unimplemented feature: aborting loop body. Simply 2552 // another unimplemented feature: aborting loop body. Simply
2488 // calling [add] does not work as it asserts that the instruction 2553 // calling [add] does not work as it asserts that the instruction
2489 // isn't a control flow instruction. So we inline parts of [add]. 2554 // isn't a control flow instruction. So we inline parts of [add].
2490 current.addAfter(current.last, new HThrow(message)); 2555 current.addAfter(current.last, new HThrow(message));
2491 if (isExpression) { 2556 if (isExpression) {
2492 stack.add(graph.addConstantNull()); 2557 stack.add(graph.addConstantNull());
2493 } 2558 }
2494 } 2559 }
2495 } 2560 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698