Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | List of all members
dart::VariableLivenessAnalysis Class Reference
Inheritance diagram for dart::VariableLivenessAnalysis:
dart::LivenessAnalysis dart::ValueObject

Public Member Functions

 VariableLivenessAnalysis (FlowGraph *flow_graph)
 
const GrowableArray< BitVector * > & ComputeAssignedVars ()
 
bool IsStoreAlive (BlockEntryInstr *block, StoreLocalInstr *store)
 
bool IsLastLoad (BlockEntryInstr *block, LoadLocalInstr *load)
 
- Public Member Functions inherited from dart::LivenessAnalysis
 LivenessAnalysis (intptr_t variable_count, const GrowableArray< BlockEntryInstr * > &postorder)
 
void Analyze ()
 
virtual ~LivenessAnalysis ()
 
BitVectorGetLiveInSetAt (intptr_t postorder_number) const
 
BitVectorGetLiveOutSetAt (intptr_t postorder_number) const
 
BitVectorGetLiveInSet (BlockEntryInstr *block) const
 
BitVectorGetKillSet (BlockEntryInstr *block) const
 
BitVectorGetLiveOutSet (BlockEntryInstr *block) const
 
void Dump ()
 
- Public Member Functions inherited from dart::ValueObject
 ValueObject ()
 
 ~ValueObject ()
 

Private Member Functions

virtual void ComputeInitialSets ()
 

Additional Inherited Members

- Protected Member Functions inherited from dart::LivenessAnalysis
bool UpdateLiveOut (const BlockEntryInstr &instr)
 
bool UpdateLiveIn (const BlockEntryInstr &instr)
 
void ComputeLiveInAndLiveOutSets ()
 
Zonezone () const
 
- Protected Attributes inherited from dart::LivenessAnalysis
Zonezone_
 
const intptr_t variable_count_
 
const GrowableArray< BlockEntryInstr * > & postorder_
 
GrowableArray< BitVector * > live_out_
 
GrowableArray< BitVector * > kill_
 
GrowableArray< BitVector * > live_in_
 

Detailed Description

Definition at line 774 of file flow_graph.cc.

Constructor & Destructor Documentation

◆ VariableLivenessAnalysis()

dart::VariableLivenessAnalysis::VariableLivenessAnalysis ( FlowGraph flow_graph)
inlineexplicit

Definition at line 776 of file flow_graph.cc.

777 : LivenessAnalysis(flow_graph->variable_count(), flow_graph->postorder()),
778 flow_graph_(flow_graph),
779 assigned_vars_() {}
LivenessAnalysis(intptr_t variable_count, const GrowableArray< BlockEntryInstr * > &postorder)

Member Function Documentation

◆ ComputeAssignedVars()

const GrowableArray< BitVector * > & dart::VariableLivenessAnalysis::ComputeAssignedVars ( )
inline

Definition at line 783 of file flow_graph.cc.

783 {
784 // We can't directly return kill_ because it uses postorder numbering while
785 // SSA construction uses preorder numbering internally.
786 // We have to permute postorder into preorder.
787 assigned_vars_.Clear();
788
789 const intptr_t block_count = flow_graph_->preorder().length();
790 for (intptr_t i = 0; i < block_count; i++) {
791 BlockEntryInstr* block = flow_graph_->preorder()[i];
792 // All locals are assigned inside a try{} block.
793 // This is a safe approximation and workaround to force insertion of
794 // phis for stores that appear non-live because of the way catch-blocks
795 // are connected to the graph: They normally are dominated by the
796 // try-entry, but are direct successors of the graph entry in our flow
797 // graph.
798 // TODO(fschneider): Improve this approximation by better modeling the
799 // actual data flow to reduce the number of redundant phis.
800 BitVector* kill = GetKillSet(block);
801 if (block->InsideTryBlock()) {
802 kill->SetAll();
803 } else {
804 kill->Intersect(GetLiveOutSet(block));
805 }
806 assigned_vars_.Add(kill);
807 }
808
809 return assigned_vars_;
810 }
static int block_count(const SkSBlockAllocator< N > &pool)
const GrowableArray< BlockEntryInstr * > & preorder() const
Definition flow_graph.h:203
BitVector * GetKillSet(BlockEntryInstr *block) const
Definition flow_graph.h:771
BitVector * GetLiveOutSet(BlockEntryInstr *block) const
Definition flow_graph.h:775

◆ ComputeInitialSets()

void dart::VariableLivenessAnalysis::ComputeInitialSets ( )
privatevirtual

Implements dart::LivenessAnalysis.

Definition at line 847 of file flow_graph.cc.

847 {
848 const intptr_t block_count = postorder_.length();
849
850 BitVector* last_loads = new (zone()) BitVector(zone(), variable_count_);
851 for (intptr_t i = 0; i < block_count; i++) {
852 BlockEntryInstr* block = postorder_[i];
853
854 BitVector* kill = kill_[i];
855 BitVector* live_in = live_in_[i];
856 last_loads->Clear();
857
858 // There is an implicit use (load-local) of every local variable at each
859 // call inside a try{} block and every call has an implicit control-flow
860 // to the catch entry. As an approximation we mark all locals as live
861 // inside try{}.
862 // TODO(fschneider): Improve this approximation, since not all local
863 // variable stores actually reach a call.
864 if (block->InsideTryBlock()) {
865 live_in->SetAll();
866 continue;
867 }
868
869 // Iterate backwards starting at the last instruction.
870 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
871 Instruction* current = it.Current();
872
873 LoadLocalInstr* load = current->AsLoadLocal();
874 if (load != nullptr) {
875 const intptr_t index = flow_graph_->EnvIndex(&load->local());
876 if (index >= live_in->length()) continue; // Skip tmp_locals.
877 live_in->Add(index);
878 if (!last_loads->Contains(index)) {
879 last_loads->Add(index);
880 load->mark_last();
881 }
882 continue;
883 }
884
885 StoreLocalInstr* store = current->AsStoreLocal();
886 if (store != nullptr) {
887 const intptr_t index = flow_graph_->EnvIndex(&store->local());
888 if (index >= live_in->length()) continue; // Skip tmp_locals.
889 if (kill->Contains(index)) {
890 if (!live_in->Contains(index)) {
891 store->mark_dead();
892 }
893 } else {
894 if (!live_in->Contains(index)) {
895 store->mark_last();
896 }
897 kill->Add(index);
898 }
899 live_in->Remove(index);
900 continue;
901 }
902 }
903
904 // For blocks with parameter or special parameter instructions we add them
905 // to the kill set.
906 const bool is_function_entry = block->IsFunctionEntry();
907 const bool is_osr_entry = block->IsOsrEntry();
908 const bool is_catch_block_entry = block->IsCatchBlockEntry();
909 if (is_function_entry || is_osr_entry || is_catch_block_entry) {
910 const intptr_t parameter_count =
911 (is_osr_entry || is_catch_block_entry)
912 ? flow_graph_->variable_count()
913 : flow_graph_->num_direct_parameters();
914 for (intptr_t i = 0; i < parameter_count; ++i) {
915 live_in->Remove(i);
916 kill->Add(i);
917 }
918 }
919 if (is_function_entry) {
920 if (flow_graph_->parsed_function().has_arg_desc_var()) {
921 const auto index = flow_graph_->ArgumentDescriptorEnvIndex();
922 live_in->Remove(index);
923 kill->Add(index);
924 }
925 }
926 }
927}
SI void store(P *ptr, const T &val)
SI T load(const P *ptr)
intptr_t ArgumentDescriptorEnvIndex() const
Definition flow_graph.h:185
const ParsedFunction & parsed_function() const
Definition flow_graph.h:129
intptr_t num_direct_parameters() const
Definition flow_graph.h:137
intptr_t variable_count() const
Definition flow_graph.h:143
intptr_t EnvIndex(const LocalVariable *variable) const
Definition flow_graph.h:189
const intptr_t variable_count_
Definition flow_graph.h:805
GrowableArray< BitVector * > kill_
Definition flow_graph.h:817
Zone * zone() const
Definition flow_graph.h:801
GrowableArray< BitVector * > live_in_
Definition flow_graph.h:821
const GrowableArray< BlockEntryInstr * > & postorder_
Definition flow_graph.h:807
bool has_arg_desc_var() const
Definition parser.h:130

◆ IsLastLoad()

bool dart::VariableLivenessAnalysis::IsLastLoad ( BlockEntryInstr block,
LoadLocalInstr load 
)
inline

Definition at line 832 of file flow_graph.cc.

832 {
833 if (load->local().Equals(*flow_graph_->CurrentContextVar())) {
834 return false;
835 }
836 const intptr_t index = flow_graph_->EnvIndex(&load->local());
837 return load->is_last() && !GetLiveOutSet(block)->Contains(index);
838 }
bool Contains(intptr_t i) const
Definition bit_vector.h:91
LocalVariable * CurrentContextVar() const
Definition flow_graph.h:173

◆ IsStoreAlive()

bool dart::VariableLivenessAnalysis::IsStoreAlive ( BlockEntryInstr block,
StoreLocalInstr store 
)
inline

Definition at line 814 of file flow_graph.cc.

814 {
815 if (store->local().Equals(*flow_graph_->CurrentContextVar())) {
816 return true;
817 }
818
819 if (store->is_dead()) {
820 return false;
821 }
822 if (store->is_last()) {
823 const intptr_t index = flow_graph_->EnvIndex(&store->local());
824 return GetLiveOutSet(block)->Contains(index);
825 }
826
827 return true;
828 }

The documentation for this class was generated from the following file: