1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_COMPILER_LIVENESS_ANAYZER_H_ 6 #define V8_COMPILER_LIVENESS_ANAYZER_H_ 7 8 #include "src/bit-vector.h" 9 #include "src/compiler/node.h" 10 #include "src/globals.h" 11 #include "src/zone/zone-containers.h" 12 13 namespace v8 { 14 namespace internal { 15 namespace compiler { 16 17 class LivenessAnalyzerBlock; 18 class Node; 19 class StateValuesCache; 20 21 class NonLiveFrameStateSlotReplacer { 22 public: 23 void ClearNonLiveFrameStateSlots(Node* frame_state, BitVector* liveness); 24 NonLiveFrameStateSlotReplacer(StateValuesCache* state_values_cache, 25 Node* replacement, size_t local_count, 26 bool has_accumulator, Zone* local_zone) 27 : replacement_node_(replacement), 28 state_values_cache_(state_values_cache), 29 local_zone_(local_zone), 30 permanently_live_( 31 static_cast<int>(local_count) + (has_accumulator ? 1 : 0), 32 local_zone), 33 inputs_buffer_(local_zone), 34 has_accumulator_(has_accumulator) {} 35 36 // TODO(leszeks): Not used by bytecode, remove once AST graph builder is gone. 37 void MarkPermanentlyLive(int var) { permanently_live_.Add(var); } 38 39 private: 40 Node* ClearNonLiveStateValues(Node* frame_state, BitVector* liveness); 41 42 StateValuesCache* state_values_cache() { return state_values_cache_; } 43 Zone* local_zone() { return local_zone_; } 44 45 // Node that replaces dead values. 46 Node* replacement_node_; 47 // Reference to state values cache so that we can create state values 48 // nodes. 49 StateValuesCache* state_values_cache_; 50 51 Zone* local_zone_; 52 BitVector permanently_live_; 53 NodeVector inputs_buffer_; 54 55 bool has_accumulator_; 56 }; 57 58 class V8_EXPORT_PRIVATE LivenessAnalyzer { 59 public: 60 LivenessAnalyzer(size_t local_count, bool has_accumulator, Zone* zone); 61 62 LivenessAnalyzerBlock* NewBlock(); 63 LivenessAnalyzerBlock* NewBlock(LivenessAnalyzerBlock* predecessor); 64 65 void Run(NonLiveFrameStateSlotReplacer* relaxer); 66 67 Zone* zone() { return zone_; } 68 69 void Print(std::ostream& os); 70 71 size_t local_count() { return local_count_; } 72 73 private: 74 void Queue(LivenessAnalyzerBlock* block); 75 76 Zone* zone_; 77 ZoneDeque<LivenessAnalyzerBlock*> blocks_; 78 size_t local_count_; 79 80 // TODO(leszeks): Always true for bytecode, remove once AST graph builder is 81 // gone. 82 bool has_accumulator_; 83 84 ZoneQueue<LivenessAnalyzerBlock*> queue_; 85 }; 86 87 88 class LivenessAnalyzerBlock { 89 public: 90 friend class LivenessAnalyzer; 91 92 void Lookup(int var) { entries_.push_back(Entry(Entry::kLookup, var)); } 93 void Bind(int var) { entries_.push_back(Entry(Entry::kBind, var)); } 94 void LookupAccumulator() { 95 DCHECK(has_accumulator_); 96 // The last entry is the accumulator entry. 97 entries_.push_back(Entry(Entry::kLookup, live_.length() - 1)); 98 } 99 void BindAccumulator() { 100 DCHECK(has_accumulator_); 101 // The last entry is the accumulator entry. 102 entries_.push_back(Entry(Entry::kBind, live_.length() - 1)); 103 } 104 105 void Checkpoint(Node* node) { entries_.push_back(Entry(node)); } 106 void AddPredecessor(LivenessAnalyzerBlock* b) { predecessors_.push_back(b); } 107 LivenessAnalyzerBlock* GetPredecessor() { 108 DCHECK(predecessors_.size() == 1); 109 return predecessors_[0]; 110 } 111 112 private: 113 class Entry { 114 public: 115 enum Kind { kBind, kLookup, kCheckpoint }; 116 117 Kind kind() const { return kind_; } 118 Node* node() const { 119 DCHECK(kind() == kCheckpoint); 120 return node_; 121 } 122 int var() const { 123 DCHECK(kind() != kCheckpoint); 124 return var_; 125 } 126 127 explicit Entry(Node* node) : kind_(kCheckpoint), var_(-1), node_(node) {} 128 Entry(Kind kind, int var) : kind_(kind), var_(var), node_(nullptr) { 129 DCHECK(kind != kCheckpoint); 130 } 131 132 private: 133 Kind kind_; 134 int var_; 135 Node* node_; 136 }; 137 138 LivenessAnalyzerBlock(size_t id, size_t local_count, bool has_accumulator, 139 Zone* zone); 140 void Process(BitVector* result, NonLiveFrameStateSlotReplacer* relaxer); 141 bool UpdateLive(BitVector* working_area); 142 143 void SetQueued() { queued_ = true; } 144 bool IsQueued() { return queued_; } 145 146 ZoneDeque<LivenessAnalyzerBlock*>::const_iterator pred_begin() { 147 return predecessors_.begin(); 148 } 149 ZoneDeque<LivenessAnalyzerBlock*>::const_iterator pred_end() { 150 return predecessors_.end(); 151 } 152 153 size_t id() { return id_; } 154 void Print(std::ostream& os); 155 156 ZoneDeque<Entry> entries_; 157 ZoneDeque<LivenessAnalyzerBlock*> predecessors_; 158 159 BitVector live_; 160 bool queued_; 161 bool has_accumulator_; 162 163 size_t id_; 164 }; 165 166 167 } // namespace compiler 168 } // namespace internal 169 } // namespace v8 170 171 #endif // V8_COMPILER_AST_GRAPH_BUILDER_H_ 172