OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "hydrogen-flow-engine.h" | 5 #include "hydrogen-flow-engine.h" |
6 #include "hydrogen-instructions.h" | 6 #include "hydrogen-instructions.h" |
7 #include "hydrogen-removable-simulates.h" | 7 #include "hydrogen-removable-simulates.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
11 | 11 |
12 class State : public ZoneObject { | 12 class State : public ZoneObject { |
13 public: | 13 public: |
14 explicit State(Zone* zone) | 14 explicit State(Zone* zone) |
15 : zone_(zone), mergelist_(2, zone), first_(true), mode_(NORMAL) { } | 15 : zone_(zone), mergelist_(2, zone), first_(true), mode_(NORMAL) { } |
16 | 16 |
17 State* Process(HInstruction* instr, Zone* zone) { | 17 State* Process(HInstruction* instr, Zone* zone) { |
18 if (FLAG_trace_removable_simulates) { | 18 if (FLAG_trace_removable_simulates) { |
19 PrintF("[State::Process %s #%d %s]\n", | 19 PrintF("[%s with state %p in B%d: #%d %s]\n", |
20 mode_ == NORMAL ? "normal" : "collect", | 20 mode_ == NORMAL ? "processing" : "collecting", |
| 21 reinterpret_cast<void*>(this), instr->block()->block_id(), |
21 instr->id(), instr->Mnemonic()); | 22 instr->id(), instr->Mnemonic()); |
22 } | 23 } |
23 // Forward-merge "trains" of simulates after an instruction with observable | 24 // Forward-merge "trains" of simulates after an instruction with observable |
24 // side effects to keep live ranges short. | 25 // side effects to keep live ranges short. |
25 if (mode_ == COLLECT_CONSECUTIVE_SIMULATES) { | 26 if (mode_ == COLLECT_CONSECUTIVE_SIMULATES) { |
26 if (instr->IsSimulate()) { | 27 if (instr->IsSimulate()) { |
27 HSimulate* current_simulate = HSimulate::cast(instr); | 28 HSimulate* current_simulate = HSimulate::cast(instr); |
28 if (current_simulate->is_candidate_for_removal() && | 29 if (current_simulate->is_candidate_for_removal() && |
29 !current_simulate->ast_id().IsNone()) { | 30 !current_simulate->ast_id().IsNone()) { |
30 Remember(current_simulate); | 31 Remember(current_simulate); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 } | 74 } |
74 | 75 |
75 return this; | 76 return this; |
76 } | 77 } |
77 | 78 |
78 static State* Merge(State* succ_state, | 79 static State* Merge(State* succ_state, |
79 HBasicBlock* succ_block, | 80 HBasicBlock* succ_block, |
80 State* pred_state, | 81 State* pred_state, |
81 HBasicBlock* pred_block, | 82 HBasicBlock* pred_block, |
82 Zone* zone) { | 83 Zone* zone) { |
83 if (FLAG_trace_removable_simulates) { | 84 return (succ_state == NULL) |
84 PrintF("[State::Merge predecessor block %d, successor block %d\n", | 85 ? pred_state->Copy(succ_block, pred_block, zone) |
85 pred_block->block_id(), succ_block->block_id()); | 86 : succ_state->Merge(succ_block, pred_state, pred_block, zone); |
86 } | |
87 return pred_state; | |
88 } | 87 } |
89 | 88 |
90 static State* Finish(State* state, HBasicBlock* block, Zone* zone) { | 89 static State* Finish(State* state, HBasicBlock* block, Zone* zone) { |
91 if (FLAG_trace_removable_simulates) { | 90 if (FLAG_trace_removable_simulates) { |
92 PrintF("[State::Finish block %d]\n", block->block_id()); } | 91 PrintF("[preparing state %p for B%d]\n", reinterpret_cast<void*>(state), |
93 // Make sure the merge list is empty at the start of a block. | 92 block->block_id()); |
94 ASSERT(state->mergelist_.is_empty()); | 93 } |
| 94 // For our current local analysis, we should not remember simulates across |
| 95 // block boundaries. |
| 96 ASSERT(!state->HasRememberedSimulates()); |
95 // Nasty heuristic: Never remove the first simulate in a block. This | 97 // Nasty heuristic: Never remove the first simulate in a block. This |
96 // just so happens to have a beneficial effect on register allocation. | 98 // just so happens to have a beneficial effect on register allocation. |
97 state->first_ = true; | 99 state->first_ = true; |
98 return state; | 100 return state; |
99 } | 101 } |
100 | 102 |
101 private: | 103 private: |
| 104 explicit State(const State& other) |
| 105 : zone_(other.zone_), |
| 106 mergelist_(other.mergelist_, other.zone_), |
| 107 first_(other.first_), |
| 108 mode_(other.mode_) { } |
| 109 |
102 enum Mode { NORMAL, COLLECT_CONSECUTIVE_SIMULATES }; | 110 enum Mode { NORMAL, COLLECT_CONSECUTIVE_SIMULATES }; |
103 | 111 |
| 112 bool HasRememberedSimulates() const { return !mergelist_.is_empty(); } |
| 113 |
104 void Remember(HSimulate* sim) { | 114 void Remember(HSimulate* sim) { |
105 mergelist_.Add(sim, zone_); | 115 mergelist_.Add(sim, zone_); |
106 } | 116 } |
107 | 117 |
108 void FlushSimulates() { | 118 void FlushSimulates() { |
109 if (!mergelist_.is_empty()) { | 119 if (HasRememberedSimulates()) { |
110 mergelist_.RemoveLast()->MergeWith(&mergelist_); | 120 mergelist_.RemoveLast()->MergeWith(&mergelist_); |
111 } | 121 } |
112 } | 122 } |
113 | 123 |
114 void RemoveSimulates() { | 124 void RemoveSimulates() { |
115 while (!mergelist_.is_empty()) { | 125 while (HasRememberedSimulates()) { |
116 mergelist_.RemoveLast()->DeleteAndReplaceWith(NULL); | 126 mergelist_.RemoveLast()->DeleteAndReplaceWith(NULL); |
117 } | 127 } |
118 } | 128 } |
119 | 129 |
| 130 State* Copy(HBasicBlock* succ_block, HBasicBlock* pred_block, Zone* zone) { |
| 131 State* copy = new(zone) State(*this); |
| 132 if (FLAG_trace_removable_simulates) { |
| 133 PrintF("[copy state %p from B%d to new state %p for B%d]\n", |
| 134 reinterpret_cast<void*>(this), pred_block->block_id(), |
| 135 reinterpret_cast<void*>(copy), succ_block->block_id()); |
| 136 } |
| 137 return copy; |
| 138 } |
| 139 |
| 140 State* Merge(HBasicBlock* succ_block, |
| 141 State* pred_state, |
| 142 HBasicBlock* pred_block, |
| 143 Zone* zone) { |
| 144 // For our current local analysis, we should not remember simulates across |
| 145 // block boundaries. |
| 146 ASSERT(!pred_state->HasRememberedSimulates()); |
| 147 ASSERT(!HasRememberedSimulates()); |
| 148 if (FLAG_trace_removable_simulates) { |
| 149 PrintF("[merge state %p from B%d into %p for B%d]\n", |
| 150 reinterpret_cast<void*>(pred_state), pred_block->block_id(), |
| 151 reinterpret_cast<void*>(this), succ_block->block_id()); |
| 152 } |
| 153 return this; |
| 154 } |
| 155 |
120 Zone* zone_; | 156 Zone* zone_; |
121 ZoneList<HSimulate*> mergelist_; | 157 ZoneList<HSimulate*> mergelist_; |
122 bool first_; | 158 bool first_; |
123 Mode mode_; | 159 Mode mode_; |
124 }; | 160 }; |
125 | 161 |
126 | 162 |
127 // We don't use effects here. | 163 // We don't use effects here. |
128 class Effects : public ZoneObject { | 164 class Effects : public ZoneObject { |
129 public: | 165 public: |
130 explicit Effects(Zone* zone) { } | 166 explicit Effects(Zone* zone) { } |
131 bool Disabled() { return true; } | 167 bool Disabled() { return true; } |
132 void Process(HInstruction* instr, Zone* zone) { } | 168 void Process(HInstruction* instr, Zone* zone) { } |
133 void Apply(State* state) { } | 169 void Apply(State* state) { } |
134 void Union(Effects* that, Zone* zone) { } | 170 void Union(Effects* that, Zone* zone) { } |
135 }; | 171 }; |
136 | 172 |
137 | 173 |
138 void HMergeRemovableSimulatesPhase::Run() { | 174 void HMergeRemovableSimulatesPhase::Run() { |
139 HFlowEngine<State, Effects> engine(graph(), zone()); | 175 HFlowEngine<State, Effects> engine(graph(), zone()); |
140 State* state = new(zone()) State(zone()); | 176 State* state = new(zone()) State(zone()); |
141 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), state); | 177 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), state); |
142 } | 178 } |
143 | 179 |
144 } } // namespace v8::internal | 180 } } // namespace v8::internal |
OLD | NEW |