Index: src/hydrogen-removable-simulates.cc |
diff --git a/src/hydrogen-removable-simulates.cc b/src/hydrogen-removable-simulates.cc |
index 738c7358f519288b137b90d53342f8d289f8d563..9db53b7977e04365bc5b264bcc48f3a59894d1d1 100644 |
--- a/src/hydrogen-removable-simulates.cc |
+++ b/src/hydrogen-removable-simulates.cc |
@@ -16,8 +16,9 @@ class State : public ZoneObject { |
State* Process(HInstruction* instr, Zone* zone) { |
if (FLAG_trace_removable_simulates) { |
- PrintF("[State::Process %s #%d %s]\n", |
- mode_ == NORMAL ? "normal" : "collect", |
+ PrintF("[%s with state %p in B%d: #%d %s]\n", |
+ mode_ == NORMAL ? "processing" : "collecting", |
+ reinterpret_cast<void*>(this), instr->block()->block_id(), |
instr->id(), instr->Mnemonic()); |
} |
// Forward-merge "trains" of simulates after an instruction with observable |
@@ -80,18 +81,19 @@ class State : public ZoneObject { |
State* pred_state, |
HBasicBlock* pred_block, |
Zone* zone) { |
- if (FLAG_trace_removable_simulates) { |
- PrintF("[State::Merge predecessor block %d, successor block %d\n", |
- pred_block->block_id(), succ_block->block_id()); |
- } |
- return pred_state; |
+ return (succ_state == NULL) |
+ ? pred_state->Copy(succ_block, pred_block, zone) |
+ : succ_state->Merge(succ_block, pred_state, pred_block, zone); |
} |
static State* Finish(State* state, HBasicBlock* block, Zone* zone) { |
if (FLAG_trace_removable_simulates) { |
- PrintF("[State::Finish block %d]\n", block->block_id()); } |
- // Make sure the merge list is empty at the start of a block. |
- ASSERT(state->mergelist_.is_empty()); |
+ PrintF("[preparing state %p for B%d]\n", reinterpret_cast<void*>(state), |
+ block->block_id()); |
+ } |
+ // For our current local analysis, we should not remember simulates across |
+ // block boundaries. |
+ ASSERT(!state->HasRememberedSimulates()); |
// Nasty heuristic: Never remove the first simulate in a block. This |
// just so happens to have a beneficial effect on register allocation. |
state->first_ = true; |
@@ -99,24 +101,58 @@ class State : public ZoneObject { |
} |
private: |
+ explicit State(const State& other) |
+ : zone_(other.zone_), |
+ mergelist_(other.mergelist_, other.zone_), |
+ first_(other.first_), |
+ mode_(other.mode_) { } |
+ |
enum Mode { NORMAL, COLLECT_CONSECUTIVE_SIMULATES }; |
+ bool HasRememberedSimulates() const { return !mergelist_.is_empty(); } |
+ |
void Remember(HSimulate* sim) { |
mergelist_.Add(sim, zone_); |
} |
void FlushSimulates() { |
- if (!mergelist_.is_empty()) { |
+ if (HasRememberedSimulates()) { |
mergelist_.RemoveLast()->MergeWith(&mergelist_); |
} |
} |
void RemoveSimulates() { |
- while (!mergelist_.is_empty()) { |
+ while (HasRememberedSimulates()) { |
mergelist_.RemoveLast()->DeleteAndReplaceWith(NULL); |
} |
} |
+ State* Copy(HBasicBlock* succ_block, HBasicBlock* pred_block, Zone* zone) { |
+ State* copy = new(zone) State(*this); |
+ if (FLAG_trace_removable_simulates) { |
+ PrintF("[copy state %p from B%d to new state %p for B%d]\n", |
+ reinterpret_cast<void*>(this), pred_block->block_id(), |
+ reinterpret_cast<void*>(copy), succ_block->block_id()); |
+ } |
+ return copy; |
+ } |
+ |
+ State* Merge(HBasicBlock* succ_block, |
+ State* pred_state, |
+ HBasicBlock* pred_block, |
+ Zone* zone) { |
+ // For our current local analysis, we should not remember simulates across |
+ // block boundaries. |
+ ASSERT(!pred_state->HasRememberedSimulates()); |
+ ASSERT(!HasRememberedSimulates()); |
+ if (FLAG_trace_removable_simulates) { |
+ PrintF("[merge state %p from B%d into %p for B%d]\n", |
+ reinterpret_cast<void*>(pred_state), pred_block->block_id(), |
+ reinterpret_cast<void*>(this), succ_block->block_id()); |
+ } |
+ return this; |
+ } |
+ |
Zone* zone_; |
ZoneList<HSimulate*> mergelist_; |
bool first_; |