Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library inferrer_visitor; | 5 library inferrer_visitor; |
| 6 | 6 |
| 7 import 'dart:collection' show | 7 import 'dart:collection' show |
| 8 IterableMixin; | 8 IterableMixin; |
| 9 | 9 |
| 10 import '../common.dart'; | 10 import '../common.dart'; |
| (...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 599 * ... | 599 * ... |
| 600 * } | 600 * } |
| 601 * :] | 601 * :] |
| 602 * | 602 * |
| 603 * where [:this:] is the [LocalsHandler] for the paths through the | 603 * where [:this:] is the [LocalsHandler] for the paths through the |
| 604 * labeled statement that do not break out. | 604 * labeled statement that do not break out. |
| 605 */ | 605 */ |
| 606 void mergeAfterBreaks(List<LocalsHandler<T>> handlers, | 606 void mergeAfterBreaks(List<LocalsHandler<T>> handlers, |
| 607 {bool keepOwnLocals: true}) { | 607 {bool keepOwnLocals: true}) { |
| 608 Node level = locals.block; | 608 Node level = locals.block; |
| 609 // Use a separate locals handler to perform the merge in, so that Phi | |
| 610 // creation does not invalidate previous type knowledge while we might | |
| 611 // still look it up. | |
| 612 LocalsHandler merged = new LocalsHandler.from(this, level); | |
| 609 Set<Local> seenLocals = new Setlet<Local>(); | 613 Set<Local> seenLocals = new Setlet<Local>(); |
| 610 // If we want to keep the locals, we first merge [this] into itself to | 614 bool allBranchesAbort = true; |
|
Kevin Millikin (Google)
2015/11/11 12:14:52
An extra space has crept in.
herhut
2015/12/10 10:09:11
Done.
| |
| 611 // create the required Phi nodes. | |
| 612 if (keepOwnLocals && !seenReturnOrThrow) { | |
| 613 mergeHandler(this, seenLocals); | |
| 614 } | |
| 615 bool allBranchesAbort = true; | |
| 616 // Merge all other handlers. | 615 // Merge all other handlers. |
| 617 for (LocalsHandler handler in handlers) { | 616 for (LocalsHandler handler in handlers) { |
| 618 allBranchesAbort = allBranchesAbort && handler.seenReturnOrThrow; | 617 allBranchesAbort = allBranchesAbort && handler.seenReturnOrThrow; |
| 619 mergeHandler(handler, seenLocals); | 618 merged.mergeHandler(handler, seenLocals); |
| 620 } | 619 } |
| 621 // Clean up Phi nodes with single input. | 620 // If we want to keep own locals, we merge [seenLocals] from [this] into |
| 622 locals.forEachLocal((Local variable, T type) { | 621 // [merged] to update the Phi nodes with original values. |
| 623 if (!seenLocals.contains(variable)) return; | 622 if (keepOwnLocals && !seenReturnOrThrow) { |
| 624 T newType = types.simplifyPhi(level, variable, type); | 623 for (Local variable in seenLocals) { |
| 625 if (newType != type) { | 624 T originalType = locals[variable]; |
| 626 locals[variable] = newType; | 625 if (originalType != null) { |
| 626 merged.locals[variable] = types.addPhiInput(variable, | |
| 627 merged.locals[variable], | |
| 628 originalType); | |
| 629 } | |
| 627 } | 630 } |
| 631 } | |
| 632 // Clean up Phi nodes with single input and store back result into | |
| 633 // actual locals handler. | |
| 634 merged.locals.forEachOwnLocal((Local variable, T type) { | |
| 635 locals[variable] = types.simplifyPhi(level, variable, type); | |
| 628 }); | 636 }); |
| 629 seenReturnOrThrow = allBranchesAbort && | 637 seenReturnOrThrow = allBranchesAbort && |
| 630 (!keepOwnLocals || seenReturnOrThrow); | 638 (!keepOwnLocals || seenReturnOrThrow); |
| 631 } | 639 } |
| 632 | 640 |
| 633 /** | 641 /** |
| 634 * Merge [other] into this handler. Returns whether a local in this | 642 * Merge [other] into this handler. Returns whether a local in this |
| 635 * has changed. If [seen] is not null, we allocate new Phi nodes | 643 * has changed. If [seen] is not null, we allocate new Phi nodes |
| 636 * unless the local is already present in the set [seen]. This effectively | 644 * unless the local is already present in the set [seen]. This effectively |
| 637 * overwrites the current type knowledge in this handler. | 645 * overwrites the current type knowledge in this handler. |
| (...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1538 return type; | 1546 return type; |
| 1539 } | 1547 } |
| 1540 | 1548 |
| 1541 T visitCascade(Cascade node) { | 1549 T visitCascade(Cascade node) { |
| 1542 // Ignore the result of the cascade send and return the type of the cascade | 1550 // Ignore the result of the cascade send and return the type of the cascade |
| 1543 // receiver. | 1551 // receiver. |
| 1544 visit(node.expression); | 1552 visit(node.expression); |
| 1545 return cascadeReceiverStack.removeLast(); | 1553 return cascadeReceiverStack.removeLast(); |
| 1546 } | 1554 } |
| 1547 } | 1555 } |
| OLD | NEW |