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 #include "vm/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
| 6 | 6 |
| 7 #include "vm/ast_printer.h" | 7 #include "vm/ast_printer.h" |
| 8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| (...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 741 body_exit->SetSuccessor(target_entry); | 741 body_exit->SetSuccessor(target_entry); |
| 742 } | 742 } |
| 743 | 743 |
| 744 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); | 744 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); |
| 745 *for_test.true_successor_address() = back_target_entry; | 745 *for_test.true_successor_address() = back_target_entry; |
| 746 back_target_entry->SetSuccessor(join); | 746 back_target_entry->SetSuccessor(join); |
| 747 exit_ = *for_test.false_successor_address() = new TargetEntryInstr(); | 747 exit_ = *for_test.false_successor_address() = new TargetEntryInstr(); |
| 748 } | 748 } |
| 749 | 749 |
| 750 | 750 |
| 751 // A ForNode can contain break and continue jumps. 'break' joins to | |
| 752 // ForNode exit, 'continue' joins at iteration entry. | |
| 751 void EffectGraphVisitor::VisitForNode(ForNode* node) { | 753 void EffectGraphVisitor::VisitForNode(ForNode* node) { |
| 752 EffectGraphVisitor for_initializer(owner(), temp_index()); | 754 EffectGraphVisitor for_initializer(owner(), temp_index()); |
| 753 node->initializer()->Visit(&for_initializer); | 755 node->initializer()->Visit(&for_initializer); |
| 754 Append(for_initializer); | 756 Append(for_initializer); |
| 755 ASSERT(is_open()); | 757 ASSERT(is_open()); |
| 756 | 758 |
| 759 JoinEntryInstr* for_break_join = NULL; | |
| 760 if (node->label()->is_break_jump_target()) { | |
|
Kevin Millikin (Google)
2012/03/29 11:38:31
You could do this lazily in VisitJumpNode:
if ((n
| |
| 761 for_break_join = new JoinEntryInstr(); | |
| 762 // Must be set-up before body is traversed. | |
| 763 node->label()->set_join_for_break(for_break_join); | |
| 764 } | |
| 765 | |
| 766 // Increment entry is either target or join. | |
| 767 BlockEntryInstr* increment_entry = NULL; | |
|
Kevin Millikin (Google)
2012/03/29 11:38:31
You could also do this lazily in VisitJumpNode.
| |
| 768 if (node->label()->is_continue_jump_target()) { | |
| 769 JoinEntryInstr* join = new JoinEntryInstr(); | |
| 770 // Must be set-up before body is traversed. | |
| 771 node->label()->set_join_for_continue(join); | |
| 772 increment_entry = join; | |
| 773 } else { | |
| 774 increment_entry = new TargetEntryInstr(); | |
| 775 } | |
| 776 | |
| 777 EffectGraphVisitor for_increment(owner(), temp_index()); | |
|
Kevin Millikin (Google)
2012/03/29 11:38:31
Then you can:
1. Visit the body first. After vis
| |
| 778 for_increment.AddInstruction(increment_entry); | |
| 779 node->increment()->Visit(&for_increment); | |
| 780 | |
| 757 EffectGraphVisitor for_body(owner(), temp_index()); | 781 EffectGraphVisitor for_body(owner(), temp_index()); |
| 782 TargetEntryInstr* body_entry = new TargetEntryInstr(); | |
| 783 for_body.AddInstruction(body_entry); | |
| 758 node->body()->Visit(&for_body); | 784 node->body()->Visit(&for_body); |
| 785 | |
| 759 if (for_body.is_open()) { | 786 if (for_body.is_open()) { |
| 760 EffectGraphVisitor for_increment(owner(), temp_index()); | 787 ASSERT(!for_body.is_empty()); |
| 761 node->increment()->Visit(&for_increment); | 788 for_body.exit()->SetSuccessor(increment_entry); |
| 762 for_body.Append(for_increment); | |
| 763 } | 789 } |
| 764 | 790 |
| 765 if (node->condition() != NULL) { | 791 if (node->condition() != NULL) { |
| 792 JoinEntryInstr* test_entry = new JoinEntryInstr(); | |
| 793 AddInstruction(test_entry); | |
| 766 TestGraphVisitor for_test(owner(), temp_index()); | 794 TestGraphVisitor for_test(owner(), temp_index()); |
| 767 node->condition()->Visit(&for_test); | 795 node->condition()->Visit(&for_test); |
| 768 TieLoop(for_test, for_body); | 796 Append(for_test); |
| 769 return; | 797 *for_test.true_successor_address() = body_entry; |
| 798 for_increment.exit()->SetSuccessor(test_entry); | |
| 799 | |
| 800 TargetEntryInstr* target_entry = new TargetEntryInstr(); | |
| 801 *for_test.false_successor_address() = target_entry; | |
| 802 if (for_break_join == NULL) { | |
| 803 exit_ = target_entry; | |
| 804 } else { | |
| 805 target_entry->SetSuccessor(for_break_join); | |
| 806 exit_ = for_break_join; | |
| 807 } | |
| 808 } else { | |
| 809 // Endless loop | |
| 810 JoinEntryInstr* loop_start = new JoinEntryInstr(); | |
| 811 AddInstruction(loop_start); | |
| 812 Append(for_body); | |
| 813 for_increment.exit()->SetSuccessor(loop_start); | |
| 814 if (node->label()->is_break_jump_target()) { | |
| 815 exit_ = for_break_join; | |
| 816 } else { | |
| 817 CloseFragment(); | |
| 818 } | |
| 819 } | |
| 820 } | |
| 821 | |
| 822 | |
| 823 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { | |
| 824 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | |
| 825 EffectGraphVisitor for_effect(owner(), temp_index()); | |
| 826 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); | |
| 827 Append(for_effect); | |
| 828 if (!is_open()) return; | |
| 770 } | 829 } |
| 771 | 830 |
| 772 // Degenerate cases. An absent condition is implicitly true. No | 831 // Unchain the context(s) up to the outer context level of the scope which |
| 773 // normal exit from loop => no back edge. | 832 // contains the destination label. |
| 774 if (!for_body.is_open()) { | 833 SourceLabel* label = node->label(); |
| 775 Append(for_body); | 834 ASSERT(label->owner() != NULL); |
| 776 return; | 835 int target_context_level = 0; |
| 836 LocalScope* target_scope = label->owner(); | |
| 837 if (target_scope->num_context_variables() > 0) { | |
| 838 // The scope of the target label allocates a context, therefore its outer | |
| 839 // scope is at a lower context level. | |
| 840 target_context_level = target_scope->context_level() - 1; | |
| 841 } else { | |
| 842 // The scope of the target label does not allocate a context, so its outer | |
| 843 // scope is at the same context level. Find it. | |
| 844 while ((target_scope != NULL) && | |
| 845 (target_scope->num_context_variables() == 0)) { | |
| 846 target_scope = target_scope->parent(); | |
| 847 } | |
| 848 if (target_scope != NULL) { | |
| 849 target_context_level = target_scope->context_level(); | |
| 850 } | |
| 777 } | 851 } |
| 778 JoinEntryInstr* join = new JoinEntryInstr(); | 852 ASSERT(target_context_level >= 0); |
| 779 AddInstruction(join); | 853 intptr_t current_context_level = owner()->context_level(); |
| 780 if (for_body.is_empty()) { | 854 ASSERT(current_context_level >= target_context_level); |
| 781 join->SetSuccessor(join); | 855 while (current_context_level-- > target_context_level) { |
| 856 UnchainContext(); | |
| 857 } | |
| 858 | |
| 859 if (node->kind() == Token::kBREAK) { | |
| 860 ASSERT(node->label()->is_break_jump_target()); | |
| 861 if (node->label()->join_for_break() == NULL) { | |
| 862 Bailout("Join for JUMP BREAK not implemented"); | |
| 863 } | |
| 864 entry_ = exit_ = node->label()->join_for_break(); | |
|
Kevin Millikin (Google)
2012/03/29 11:38:31
Hmm. We don't need to set exit_, because CloseFra
| |
| 782 } else { | 865 } else { |
| 783 join->SetSuccessor(for_body.entry()); | 866 ASSERT(node->label()->is_continue_jump_target()); |
| 784 for_body.exit()->SetSuccessor(join); | 867 if (node->label()->join_for_continue() == NULL) { |
| 868 Bailout("Join for JUMP CONTINUE not implemented"); | |
| 869 } | |
| 870 entry_ = exit_ = node->label()->join_for_continue(); | |
| 785 } | 871 } |
| 786 CloseFragment(); | 872 CloseFragment(); |
| 787 } | 873 } |
| 788 | 874 |
| 789 | 875 |
| 790 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { | |
| 791 Bailout("EffectGraphVisitor::VisitJumpNode"); | |
| 792 } | |
| 793 | |
| 794 | |
| 795 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { | 876 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { |
| 796 UNREACHABLE(); | 877 UNREACHABLE(); |
| 797 } | 878 } |
| 798 | 879 |
| 799 | 880 |
| 800 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { | 881 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { |
| 801 // Translate the array elements and collect their values. | 882 // Translate the array elements and collect their values. |
| 802 ZoneGrowableArray<Value*>* values = | 883 ZoneGrowableArray<Value*>* values = |
| 803 new ZoneGrowableArray<Value*>(node->length()); | 884 new ZoneGrowableArray<Value*>(node->length()); |
| 804 int index = temp_index(); | 885 int index = temp_index(); |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1406 if (FLAG_enable_type_checks && | 1487 if (FLAG_enable_type_checks && |
| 1407 (node == owner()->parsed_function().node_sequence())) { | 1488 (node == owner()->parsed_function().node_sequence())) { |
| 1408 Bailout("VisitSequenceNode GenerateArgumentTypeChecks()"); | 1489 Bailout("VisitSequenceNode GenerateArgumentTypeChecks()"); |
| 1409 } | 1490 } |
| 1410 | 1491 |
| 1411 intptr_t i = 0; | 1492 intptr_t i = 0; |
| 1412 while (is_open() && (i < node->length())) { | 1493 while (is_open() && (i < node->length())) { |
| 1413 EffectGraphVisitor for_effect(owner(), temp_index()); | 1494 EffectGraphVisitor for_effect(owner(), temp_index()); |
| 1414 node->NodeAt(i++)->Visit(&for_effect); | 1495 node->NodeAt(i++)->Visit(&for_effect); |
| 1415 Append(for_effect); | 1496 Append(for_effect); |
| 1497 if (!is_open()) { | |
| 1498 // E.g., because of a JumpNode. | |
| 1499 break; | |
| 1500 } | |
| 1416 } | 1501 } |
| 1417 | 1502 |
| 1418 if (is_open()) { | 1503 if (is_open()) { |
| 1419 if (MustSaveRestoreContext(node)) { | 1504 if (MustSaveRestoreContext(node)) { |
| 1420 ASSERT(num_context_variables > 0); | 1505 ASSERT(num_context_variables > 0); |
| 1421 LoadLocalComp* load_comp = | 1506 LoadLocalComp* load_comp = |
| 1422 new LoadLocalComp(*owner()->parsed_function().saved_context_var(), 0); | 1507 new LoadLocalComp(*owner()->parsed_function().saved_context_var(), 0); |
| 1423 AddInstruction(new BindInstr(temp_index(), load_comp)); | 1508 AddInstruction(new BindInstr(temp_index(), load_comp)); |
| 1424 TempVal* local_value = new TempVal(temp_index()); | 1509 TempVal* local_value = new TempVal(temp_index()); |
| 1425 StoreContextComp* store_context = new StoreContextComp(local_value); | 1510 StoreContextComp* store_context = new StoreContextComp(local_value); |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1960 char* chars = reinterpret_cast<char*>( | 2045 char* chars = reinterpret_cast<char*>( |
| 1961 Isolate::Current()->current_zone()->Allocate(len)); | 2046 Isolate::Current()->current_zone()->Allocate(len)); |
| 1962 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2047 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 1963 const Error& error = Error::Handle( | 2048 const Error& error = Error::Handle( |
| 1964 LanguageError::New(String::Handle(String::New(chars)))); | 2049 LanguageError::New(String::Handle(String::New(chars)))); |
| 1965 Isolate::Current()->long_jump_base()->Jump(1, error); | 2050 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 1966 } | 2051 } |
| 1967 | 2052 |
| 1968 | 2053 |
| 1969 } // namespace dart | 2054 } // namespace dart |
| OLD | NEW |