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

Side by Side Diff: runtime/vm/flow_graph.cc

Issue 678763004: Make CTX allocatable by the register allocator. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 1 month 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 #include "vm/flow_graph.h" 5 #include "vm/flow_graph.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/flow_graph_builder.h" 8 #include "vm/flow_graph_builder.h"
9 #include "vm/intermediate_language.h" 9 #include "vm/intermediate_language.h"
10 #include "vm/growable_array.h" 10 #include "vm/growable_array.h"
11 #include "vm/object_store.h"
11 #include "vm/report.h" 12 #include "vm/report.h"
12 13
13 namespace dart { 14 namespace dart {
14 15
15 DECLARE_FLAG(bool, reorder_basic_blocks); 16 DECLARE_FLAG(bool, reorder_basic_blocks);
16 DECLARE_FLAG(bool, trace_optimization); 17 DECLARE_FLAG(bool, trace_optimization);
17 DECLARE_FLAG(bool, verify_compiler); 18 DECLARE_FLAG(bool, verify_compiler);
18 19
19 20
20 FlowGraph::FlowGraph(const FlowGraphBuilder& builder, 21 FlowGraph::FlowGraph(const FlowGraphBuilder& builder,
21 GraphEntryInstr* graph_entry, 22 GraphEntryInstr* graph_entry,
22 intptr_t max_block_id) 23 intptr_t max_block_id)
23 : isolate_(Isolate::Current()), 24 : isolate_(Isolate::Current()),
24 parent_(), 25 parent_(),
25 current_ssa_temp_index_(0), 26 current_ssa_temp_index_(0),
26 max_block_id_(max_block_id), 27 max_block_id_(max_block_id),
27 builder_(builder), 28 builder_(builder),
28 parsed_function_(*builder.parsed_function()), 29 parsed_function_(*builder.parsed_function()),
29 num_copied_params_(builder.num_copied_params()), 30 num_copied_params_(builder.num_copied_params()),
30 num_non_copied_params_(builder.num_non_copied_params()), 31 num_non_copied_params_(builder.num_non_copied_params()),
31 num_stack_locals_(builder.num_stack_locals()), 32 num_stack_locals_(builder.num_stack_locals()),
32 graph_entry_(graph_entry), 33 graph_entry_(graph_entry),
33 preorder_(), 34 preorder_(),
34 postorder_(), 35 postorder_(),
35 reverse_postorder_(), 36 reverse_postorder_(),
36 optimized_block_order_(), 37 optimized_block_order_(),
37 constant_null_(NULL), 38 constant_null_(NULL),
38 constant_dead_(NULL), 39 constant_dead_(NULL),
40 constant_empty_context_(NULL),
41 current_context_(NULL),
39 block_effects_(NULL), 42 block_effects_(NULL),
40 licm_allowed_(true), 43 licm_allowed_(true),
41 loop_headers_(NULL), 44 loop_headers_(NULL),
42 loop_invariant_loads_(NULL), 45 loop_invariant_loads_(NULL),
43 guarded_fields_(builder.guarded_fields()), 46 guarded_fields_(builder.guarded_fields()),
44 deferred_prefixes_(builder.deferred_prefixes()), 47 deferred_prefixes_(builder.deferred_prefixes()),
45 captured_parameters_( 48 captured_parameters_(
46 new(isolate_) BitVector(isolate_, variable_count())) { 49 new(isolate_) BitVector(isolate_, variable_count())) {
47 DiscoverBlocks(); 50 DiscoverBlocks();
48 } 51 }
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
458 } 461 }
459 assigned_vars_.Add(kill); 462 assigned_vars_.Add(kill);
460 } 463 }
461 464
462 return assigned_vars_; 465 return assigned_vars_;
463 } 466 }
464 467
465 // Returns true if the value set by the given store reaches any load from the 468 // Returns true if the value set by the given store reaches any load from the
466 // same local variable. 469 // same local variable.
467 bool IsStoreAlive(BlockEntryInstr* block, StoreLocalInstr* store) { 470 bool IsStoreAlive(BlockEntryInstr* block, StoreLocalInstr* store) {
471 if (store->local().index() == flow_graph_->CurrentContextVar()->index()) {
Vyacheslav Egorov (Google) 2014/10/28 13:44:57 is it possible just to do store->local().Equals(f
Florian Schneider 2014/10/28 19:04:31 Done.
472 return true;
473 }
474
468 if (store->is_dead()) { 475 if (store->is_dead()) {
469 return false; 476 return false;
470 } 477 }
471
472 if (store->is_last()) { 478 if (store->is_last()) {
473 const intptr_t index = store->local().BitIndexIn(num_non_copied_params_); 479 const intptr_t index = store->local().BitIndexIn(num_non_copied_params_);
474 return GetLiveOutSet(block)->Contains(index); 480 return GetLiveOutSet(block)->Contains(index);
475 } 481 }
476 482
477 return true; 483 return true;
478 } 484 }
479 485
480 // Returns true if the given load is the last for the local and the value 486 // Returns true if the given load is the last for the local and the value
481 // of the local will not flow into another one. 487 // of the local will not flow into another one.
482 bool IsLastLoad(BlockEntryInstr* block, LoadLocalInstr* load) { 488 bool IsLastLoad(BlockEntryInstr* block, LoadLocalInstr* load) {
489 if (load->local().index() == flow_graph_->CurrentContextVar()->index()) {
Vyacheslav Egorov (Google) 2014/10/28 13:44:57 ditto
Florian Schneider 2014/10/28 19:04:30 Done.
490 return false;
491 }
483 const intptr_t index = load->local().BitIndexIn(num_non_copied_params_); 492 const intptr_t index = load->local().BitIndexIn(num_non_copied_params_);
484 return load->is_last() && !GetLiveOutSet(block)->Contains(index); 493 return load->is_last() && !GetLiveOutSet(block)->Contains(index);
485 } 494 }
486 495
487 private: 496 private:
488 virtual void ComputeInitialSets(); 497 virtual void ComputeInitialSets();
489 498
490 const FlowGraph* flow_graph_; 499 const FlowGraph* flow_graph_;
491 const intptr_t num_non_copied_params_; 500 const intptr_t num_non_copied_params_;
492 GrowableArray<BitVector*> assigned_vars_; 501 GrowableArray<BitVector*> assigned_vars_;
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 724
716 // Initialize has_already and work. 725 // Initialize has_already and work.
717 for (intptr_t block_index = 0; block_index < block_count; ++block_index) { 726 for (intptr_t block_index = 0; block_index < block_count; ++block_index) {
718 has_already.Add(-1); 727 has_already.Add(-1);
719 work.Add(-1); 728 work.Add(-1);
720 } 729 }
721 730
722 // Insert phis for each variable in turn. 731 // Insert phis for each variable in turn.
723 GrowableArray<BlockEntryInstr*> worklist; 732 GrowableArray<BlockEntryInstr*> worklist;
724 for (intptr_t var_index = 0; var_index < variable_count(); ++var_index) { 733 for (intptr_t var_index = 0; var_index < variable_count(); ++var_index) {
734 bool always_live = var_index == CurrentContextEnvIndex();
Vyacheslav Egorov (Google) 2014/10/28 13:44:57 const bool is_always_alive
Florian Schneider 2014/10/28 19:04:30 Done.
725 // Add to the worklist each block containing an assignment. 735 // Add to the worklist each block containing an assignment.
726 for (intptr_t block_index = 0; block_index < block_count; ++block_index) { 736 for (intptr_t block_index = 0; block_index < block_count; ++block_index) {
727 if (assigned_vars[block_index]->Contains(var_index)) { 737 if (assigned_vars[block_index]->Contains(var_index)) {
728 work[block_index] = var_index; 738 work[block_index] = var_index;
729 worklist.Add(preorder[block_index]); 739 worklist.Add(preorder[block_index]);
730 } 740 }
731 } 741 }
732 742
733 while (!worklist.is_empty()) { 743 while (!worklist.is_empty()) {
734 BlockEntryInstr* current = worklist.RemoveLast(); 744 BlockEntryInstr* current = worklist.RemoveLast();
735 // Ensure a phi for each block in the dominance frontier of current. 745 // Ensure a phi for each block in the dominance frontier of current.
736 for (BitVector::Iterator it(dom_frontier[current->preorder_number()]); 746 for (BitVector::Iterator it(dom_frontier[current->preorder_number()]);
737 !it.Done(); 747 !it.Done();
738 it.Advance()) { 748 it.Advance()) {
739 int index = it.Current(); 749 int index = it.Current();
740 if (has_already[index] < var_index) { 750 if (has_already[index] < var_index) {
741 BlockEntryInstr* block = preorder[index]; 751 BlockEntryInstr* block = preorder[index];
742 ASSERT(block->IsJoinEntry()); 752 ASSERT(block->IsJoinEntry());
743 block->AsJoinEntry()->InsertPhi(var_index, variable_count()); 753 block->AsJoinEntry()->InsertPhi(var_index,
Vyacheslav Egorov (Google) 2014/10/28 13:44:57 You can also make InsertPhi return the phi it crea
Florian Schneider 2014/10/28 19:04:31 Done.
754 variable_count(),
755 always_live);
744 has_already[index] = var_index; 756 has_already[index] = var_index;
745 if (work[index] < var_index) { 757 if (work[index] < var_index) {
746 work[index] = var_index; 758 work[index] = var_index;
747 worklist.Add(block); 759 worklist.Add(block);
748 } 760 }
749 } 761 }
750 } 762 }
751 } 763 }
752 } 764 }
753 } 765 }
754 766
755 767
756 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, 768 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis,
757 VariableLivenessAnalysis* variable_liveness, 769 VariableLivenessAnalysis* variable_liveness,
758 ZoneGrowableArray<Definition*>* inlining_parameters) { 770 ZoneGrowableArray<Definition*>* inlining_parameters) {
759 GraphEntryInstr* entry = graph_entry(); 771 GraphEntryInstr* entry = graph_entry();
760 772
761 // Initial renaming environment. 773 // Initial renaming environment.
762 GrowableArray<Definition*> env(variable_count()); 774 GrowableArray<Definition*> env(variable_count());
763 775
764 // Add global constants to the initial definitions. 776 // Add global constants to the initial definitions.
765 constant_null_ = GetConstant(Object::ZoneHandle()); 777 constant_null_ = GetConstant(Object::ZoneHandle());
766 constant_dead_ = GetConstant(Symbols::OptimizedOut()); 778 constant_dead_ = GetConstant(Symbols::OptimizedOut());
779 constant_empty_context_ = GetConstant(Context::Handle(
780 isolate()->object_store()->empty_context()));
767 781
768 // Add parameters to the initial definitions and renaming environment. 782 // Add parameters to the initial definitions and renaming environment.
769 if (inlining_parameters != NULL) { 783 if (inlining_parameters != NULL) {
770 // Use known parameters. 784 // Use known parameters.
771 ASSERT(parameter_count() == inlining_parameters->length()); 785 ASSERT(parameter_count() == inlining_parameters->length());
772 for (intptr_t i = 0; i < parameter_count(); ++i) { 786 for (intptr_t i = 0; i < parameter_count(); ++i) {
773 Definition* defn = (*inlining_parameters)[i]; 787 Definition* defn = (*inlining_parameters)[i];
774 AllocateSSAIndexes(defn); 788 AllocateSSAIndexes(defn);
775 AddToInitialDefinitions(defn); 789 AddToInitialDefinitions(defn);
776 env.Add(defn); 790 env.Add(defn);
777 } 791 }
778 } else { 792 } else {
779 // Create new parameters. For functions compiled for OSR, the locals 793 // Create new parameters. For functions compiled for OSR, the locals
780 // are unknown and so treated like parameters. 794 // are unknown and so treated like parameters.
781 intptr_t count = IsCompiledForOsr() ? variable_count() : parameter_count(); 795 intptr_t count = IsCompiledForOsr() ? variable_count() : parameter_count();
782 for (intptr_t i = 0; i < count; ++i) { 796 for (intptr_t i = 0; i < count; ++i) {
783 ParameterInstr* param = new(isolate()) ParameterInstr(i, entry); 797 ParameterInstr* param = new(isolate()) ParameterInstr(i, entry);
784 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 798 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
785 AddToInitialDefinitions(param); 799 AddToInitialDefinitions(param);
786 env.Add(param); 800 env.Add(param);
787 } 801 }
788 } 802 }
789 803
790 // Initialize all locals with #null in the renaming environment. For OSR, 804 // Initialize all locals with #null in the renaming environment. For OSR,
Vyacheslav Egorov (Google) 2014/10/28 13:44:57 Comment is out of date.
Florian Schneider 2014/10/28 19:04:31 Done.
791 // the locals have already been handled as parameters. 805 // the locals have already been handled as parameters.
792 if (!IsCompiledForOsr()) { 806 if (!IsCompiledForOsr()) {
793 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { 807 for (intptr_t i = parameter_count(); i < variable_count(); ++i) {
794 env.Add(constant_null()); 808 if (i == CurrentContextEnvIndex()) {
809 if (parsed_function().function().IsClosureFunction()) {
810 CurrentContextInstr* context = new CurrentContextInstr();
811 context->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
812 AddToInitialDefinitions(context);
813 env.Add(context);
814 } else {
815 env.Add(constant_empty_context());
816 }
817 } else {
818 env.Add(constant_null());
819 }
795 } 820 }
796 } 821 }
797 822
798 if (entry->SuccessorCount() > 1) { 823 if (entry->SuccessorCount() > 1) {
799 // Functions with try-catch have a fixed area of stack slots reserved 824 // Functions with try-catch have a fixed area of stack slots reserved
800 // so that all local variables are stored at a known location when 825 // so that all local variables are stored at a known location when
801 // on entry to the catch. 826 // on entry to the catch.
802 entry->set_fixed_slot_count(num_stack_locals() + num_copied_params()); 827 entry->set_fixed_slot_count(num_stack_locals() + num_copied_params());
803 } 828 }
804 RenameRecursive(entry, &env, live_phis, variable_liveness); 829 RenameRecursive(entry, &env, live_phis, variable_liveness);
805 } 830 }
806 831
807 832
808 void FlowGraph::AttachEnvironment(Instruction* instr, 833 void FlowGraph::AttachEnvironment(Instruction* instr,
809 GrowableArray<Definition*>* env) { 834 GrowableArray<Definition*>* env) {
810 Environment* deopt_env = 835 Environment* deopt_env =
811 Environment::From(isolate(), 836 Environment::From(isolate(),
812 *env, 837 *env,
813 num_non_copied_params_, 838 num_non_copied_params_,
814 &parsed_function_); 839 &parsed_function_);
815 // TODO(fschneider): Add predicates CanEagerlyDeoptimize and
816 // CanLazilyDeoptimize to instructions to generally deal with instructions
817 // that have pushed arguments and input operands.
818 // Right now, closure calls are the only instructions that have both. They
819 // also don't have an eager deoptimziation point, so the environment attached
820 // here is only used for after the call.
821 if (instr->IsClosureCall()) { 840 if (instr->IsClosureCall()) {
822 deopt_env = deopt_env->DeepCopy(isolate(), 841 deopt_env = deopt_env->DeepCopy(isolate(),
823 deopt_env->Length() - instr->InputCount()); 842 deopt_env->Length() - instr->InputCount());
824 } 843 }
825 instr->SetEnvironment(deopt_env); 844 instr->SetEnvironment(deopt_env);
826 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) { 845 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
827 Value* use = it.CurrentValue(); 846 Value* use = it.CurrentValue();
828 use->definition()->AddEnvUse(use); 847 use->definition()->AddEnvUse(use);
829 } 848 }
830 if (instr->CanDeoptimize()) { 849 if (instr->CanDeoptimize()) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 884 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
866 (*env)[i] = param; 885 (*env)[i] = param;
867 block_entry->AsCatchBlockEntry()->initial_definitions()->Add(param); 886 block_entry->AsCatchBlockEntry()->initial_definitions()->Add(param);
868 } 887 }
869 } 888 }
870 889
871 // Prune non-live variables at block entry by replacing their environment 890 // Prune non-live variables at block entry by replacing their environment
872 // slots with null. 891 // slots with null.
873 BitVector* live_in = variable_liveness->GetLiveInSet(block_entry); 892 BitVector* live_in = variable_liveness->GetLiveInSet(block_entry);
874 for (intptr_t i = 0; i < variable_count(); i++) { 893 for (intptr_t i = 0; i < variable_count(); i++) {
875 if (!live_in->Contains(i)) { 894 if (!live_in->Contains(i) && (i != CurrentContextEnvIndex())) {
Vyacheslav Egorov (Google) 2014/10/28 13:44:57 Should not we instead ensure that live_in->Contain
Florian Schneider 2014/10/28 19:04:31 Yes, I can change the VariableLiveness accordingly
876 (*env)[i] = constant_dead(); 895 (*env)[i] = constant_dead();
877 } 896 }
878 } 897 }
879 898
880 // Attach environment to the block entry. 899 // Attach environment to the block entry.
881 AttachEnvironment(block_entry, env); 900 AttachEnvironment(block_entry, env);
882 901
883 // 2. Process normal instructions. 902 // 2. Process normal instructions.
884 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { 903 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
885 Instruction* current = it.Current(); 904 Instruction* current = it.Current();
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
1308 } 1327 }
1309 1328
1310 1329
1311 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from, 1330 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from,
1312 BlockEntryInstr* to) const { 1331 BlockEntryInstr* to) const {
1313 return available_at_[to->postorder_number()]->Contains( 1332 return available_at_[to->postorder_number()]->Contains(
1314 from->postorder_number()); 1333 from->postorder_number());
1315 } 1334 }
1316 1335
1317 } // namespace dart 1336 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698