// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/crankshaft/hydrogen-gvn.h"

#include "src/crankshaft/hydrogen.h"
#include "src/v8.h"

namespace v8 {
namespace internal {

class HInstructionMap final : public ZoneObject {
 public:
  HInstructionMap(Zone* zone, SideEffectsTracker* side_effects_tracker)
      : array_size_(0),
        lists_size_(0),
        count_(0),
        array_(NULL),
        lists_(NULL),
        free_list_head_(kNil),
        side_effects_tracker_(side_effects_tracker) {
    ResizeLists(kInitialSize, zone);
    Resize(kInitialSize, zone);
  }

  void Kill(SideEffects side_effects);

  void Add(HInstruction* instr, Zone* zone) {
    present_depends_on_.Add(side_effects_tracker_->ComputeDependsOn(instr));
    Insert(instr, zone);
  }

  HInstruction* Lookup(HInstruction* instr) const;

  HInstructionMap* Copy(Zone* zone) const {
    return new(zone) HInstructionMap(zone, this);
  }

  bool IsEmpty() const { return count_ == 0; }

 private:
  // A linked list of HInstruction* values.  Stored in arrays.
  struct HInstructionMapListElement {
    HInstruction* instr;
    int next;  // Index in the array of the next list element.
  };
  static const int kNil = -1;  // The end of a linked list

  // Must be a power of 2.
  static const int kInitialSize = 16;

  HInstructionMap(Zone* zone, const HInstructionMap* other);

  void Resize(int new_size, Zone* zone);
  void ResizeLists(int new_size, Zone* zone);
  void Insert(HInstruction* instr, Zone* zone);
  uint32_t Bound(uint32_t value) const { return value & (array_size_ - 1); }

  int array_size_;
  int lists_size_;
  int count_;  // The number of values stored in the HInstructionMap.
  SideEffects present_depends_on_;
  HInstructionMapListElement* array_;
  // Primary store - contains the first value
  // with a given hash.  Colliding elements are stored in linked lists.
  HInstructionMapListElement* lists_;
  // The linked lists containing hash collisions.
  int free_list_head_;  // Unused elements in lists_ are on the free list.
  SideEffectsTracker* side_effects_tracker_;
};


class HSideEffectMap final BASE_EMBEDDED {
 public:
  HSideEffectMap();
  explicit HSideEffectMap(HSideEffectMap* other);
  HSideEffectMap& operator= (const HSideEffectMap& other);

  void Kill(SideEffects side_effects);

  void Store(SideEffects side_effects, HInstruction* instr);

  bool IsEmpty() const { return count_ == 0; }

  inline HInstruction* operator[](int i) const {
    DCHECK(0 <= i);
    DCHECK(i < kNumberOfTrackedSideEffects);
    return data_[i];
  }
  inline HInstruction* at(int i) const { return operator[](i); }

 private:
  int count_;
  HInstruction* data_[kNumberOfTrackedSideEffects];
};


void TraceGVN(const char* msg, ...) {
  va_list arguments;
  va_start(arguments, msg);
  base::OS::VPrint(msg, arguments);
  va_end(arguments);
}


// Wrap TraceGVN in macros to avoid the expense of evaluating its arguments when
// --trace-gvn is off.
#define TRACE_GVN_1(msg, a1)                    \
  if (FLAG_trace_gvn) {                         \
    TraceGVN(msg, a1);                          \
  }

#define TRACE_GVN_2(msg, a1, a2)                \
  if (FLAG_trace_gvn) {                         \
    TraceGVN(msg, a1, a2);                      \
  }

#define TRACE_GVN_3(msg, a1, a2, a3)            \
  if (FLAG_trace_gvn) {                         \
    TraceGVN(msg, a1, a2, a3);                  \
  }

#define TRACE_GVN_4(msg, a1, a2, a3, a4)        \
  if (FLAG_trace_gvn) {                         \
    TraceGVN(msg, a1, a2, a3, a4);              \
  }

#define TRACE_GVN_5(msg, a1, a2, a3, a4, a5)    \
  if (FLAG_trace_gvn) {                         \
    TraceGVN(msg, a1, a2, a3, a4, a5);          \
  }


HInstructionMap::HInstructionMap(Zone* zone, const HInstructionMap* other)
    : array_size_(other->array_size_),
      lists_size_(other->lists_size_),
      count_(other->count_),
      present_depends_on_(other->present_depends_on_),
      array_(zone->NewArray<HInstructionMapListElement>(other->array_size_)),
      lists_(zone->NewArray<HInstructionMapListElement>(other->lists_size_)),
      free_list_head_(other->free_list_head_),
      side_effects_tracker_(other->side_effects_tracker_) {
  MemCopy(array_, other->array_,
          array_size_ * sizeof(HInstructionMapListElement));
  MemCopy(lists_, other->lists_,
          lists_size_ * sizeof(HInstructionMapListElement));
}


void HInstructionMap::Kill(SideEffects changes) {
  if (!present_depends_on_.ContainsAnyOf(changes)) return;
  present_depends_on_.RemoveAll();
  for (int i = 0; i < array_size_; ++i) {
    HInstruction* instr = array_[i].instr;
    if (instr != NULL) {
      // Clear list of collisions first, so we know if it becomes empty.
      int kept = kNil;  // List of kept elements.
      int next;
      for (int current = array_[i].next; current != kNil; current = next) {
        next = lists_[current].next;
        HInstruction* instr = lists_[current].instr;
        SideEffects depends_on = side_effects_tracker_->ComputeDependsOn(instr);
        if (depends_on.ContainsAnyOf(changes)) {
          // Drop it.
          count_--;
          lists_[current].next = free_list_head_;
          free_list_head_ = current;
        } else {
          // Keep it.
          lists_[current].next = kept;
          kept = current;
          present_depends_on_.Add(depends_on);
        }
      }
      array_[i].next = kept;

      // Now possibly drop directly indexed element.
      instr = array_[i].instr;
      SideEffects depends_on = side_effects_tracker_->ComputeDependsOn(instr);
      if (depends_on.ContainsAnyOf(changes)) {  // Drop it.
        count_--;
        int head = array_[i].next;
        if (head == kNil) {
          array_[i].instr = NULL;
        } else {
          array_[i].instr = lists_[head].instr;
          array_[i].next = lists_[head].next;
          lists_[head].next = free_list_head_;
          free_list_head_ = head;
        }
      } else {
        present_depends_on_.Add(depends_on);  // Keep it.
      }
    }
  }
}


HInstruction* HInstructionMap::Lookup(HInstruction* instr) const {
  uint32_t hash = static_cast<uint32_t>(instr->Hashcode());
  uint32_t pos = Bound(hash);
  if (array_[pos].instr != NULL) {
    if (array_[pos].instr->Equals(instr)) return array_[pos].instr;
    int next = array_[pos].next;
    while (next != kNil) {
      if (lists_[next].instr->Equals(instr)) return lists_[next].instr;
      next = lists_[next].next;
    }
  }
  return NULL;
}


void HInstructionMap::Resize(int new_size, Zone* zone) {
  DCHECK(new_size > count_);
  // Hashing the values into the new array has no more collisions than in the
  // old hash map, so we can use the existing lists_ array, if we are careful.

  // Make sure we have at least one free element.
  if (free_list_head_ == kNil) {
    ResizeLists(lists_size_ << 1, zone);
  }

  HInstructionMapListElement* new_array =
      zone->NewArray<HInstructionMapListElement>(new_size);
  memset(new_array, 0, sizeof(HInstructionMapListElement) * new_size);

  HInstructionMapListElement* old_array = array_;
  int old_size = array_size_;

  int old_count = count_;
  count_ = 0;
  // Do not modify present_depends_on_.  It is currently correct.
  array_size_ = new_size;
  array_ = new_array;

  if (old_array != NULL) {
    // Iterate over all the elements in lists, rehashing them.
    for (int i = 0; i < old_size; ++i) {
      if (old_array[i].instr != NULL) {
        int current = old_array[i].next;
        while (current != kNil) {
          Insert(lists_[current].instr, zone);
          int next = lists_[current].next;
          lists_[current].next = free_list_head_;
          free_list_head_ = current;
          current = next;
        }
        // Rehash the directly stored instruction.
        Insert(old_array[i].instr, zone);
      }
    }
  }
  USE(old_count);
  DCHECK(count_ == old_count);
}


void HInstructionMap::ResizeLists(int new_size, Zone* zone) {
  DCHECK(new_size > lists_size_);

  HInstructionMapListElement* new_lists =
      zone->NewArray<HInstructionMapListElement>(new_size);
  memset(new_lists, 0, sizeof(HInstructionMapListElement) * new_size);

  HInstructionMapListElement* old_lists = lists_;
  int old_size = lists_size_;

  lists_size_ = new_size;
  lists_ = new_lists;

  if (old_lists != NULL) {
    MemCopy(lists_, old_lists, old_size * sizeof(HInstructionMapListElement));
  }
  for (int i = old_size; i < lists_size_; ++i) {
    lists_[i].next = free_list_head_;
    free_list_head_ = i;
  }
}


void HInstructionMap::Insert(HInstruction* instr, Zone* zone) {
  DCHECK(instr != NULL);
  // Resizing when half of the hashtable is filled up.
  if (count_ >= array_size_ >> 1) Resize(array_size_ << 1, zone);
  DCHECK(count_ < array_size_);
  count_++;
  uint32_t pos = Bound(static_cast<uint32_t>(instr->Hashcode()));
  if (array_[pos].instr == NULL) {
    array_[pos].instr = instr;
    array_[pos].next = kNil;
  } else {
    if (free_list_head_ == kNil) {
      ResizeLists(lists_size_ << 1, zone);
    }
    int new_element_pos = free_list_head_;
    DCHECK(new_element_pos != kNil);
    free_list_head_ = lists_[free_list_head_].next;
    lists_[new_element_pos].instr = instr;
    lists_[new_element_pos].next = array_[pos].next;
    DCHECK(array_[pos].next == kNil || lists_[array_[pos].next].instr != NULL);
    array_[pos].next = new_element_pos;
  }
}


HSideEffectMap::HSideEffectMap() : count_(0) {
  memset(data_, 0, kNumberOfTrackedSideEffects * kPointerSize);
}


HSideEffectMap::HSideEffectMap(HSideEffectMap* other) : count_(other->count_) {
  *this = *other;  // Calls operator=.
}


HSideEffectMap& HSideEffectMap::operator=(const HSideEffectMap& other) {
  if (this != &other) {
    MemCopy(data_, other.data_, kNumberOfTrackedSideEffects * kPointerSize);
  }
  return *this;
}


void HSideEffectMap::Kill(SideEffects side_effects) {
  for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
    if (side_effects.ContainsFlag(GVNFlagFromInt(i))) {
      if (data_[i] != NULL) count_--;
      data_[i] = NULL;
    }
  }
}


void HSideEffectMap::Store(SideEffects side_effects, HInstruction* instr) {
  for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
    if (side_effects.ContainsFlag(GVNFlagFromInt(i))) {
      if (data_[i] == NULL) count_++;
      data_[i] = instr;
    }
  }
}


SideEffects SideEffectsTracker::ComputeChanges(HInstruction* instr) {
  int index;
  SideEffects result(instr->ChangesFlags());
  if (result.ContainsFlag(kGlobalVars)) {
    if (instr->IsStoreNamedField()) {
      HStoreNamedField* store = HStoreNamedField::cast(instr);
      HConstant* target = HConstant::cast(store->object());
      if (ComputeGlobalVar(Unique<PropertyCell>::cast(target->GetUnique()),
                           &index)) {
        result.RemoveFlag(kGlobalVars);
        result.AddSpecial(GlobalVar(index));
        return result;
      }
    }
    for (index = 0; index < kNumberOfGlobalVars; ++index) {
      result.AddSpecial(GlobalVar(index));
    }
  } else if (result.ContainsFlag(kInobjectFields)) {
    if (instr->IsStoreNamedField() &&
        ComputeInobjectField(HStoreNamedField::cast(instr)->access(), &index)) {
      result.RemoveFlag(kInobjectFields);
      result.AddSpecial(InobjectField(index));
    } else {
      for (index = 0; index < kNumberOfInobjectFields; ++index) {
        result.AddSpecial(InobjectField(index));
      }
    }
  }
  return result;
}


SideEffects SideEffectsTracker::ComputeDependsOn(HInstruction* instr) {
  int index;
  SideEffects result(instr->DependsOnFlags());
  if (result.ContainsFlag(kGlobalVars)) {
    if (instr->IsLoadNamedField()) {
      HLoadNamedField* load = HLoadNamedField::cast(instr);
      HConstant* target = HConstant::cast(load->object());
      if (ComputeGlobalVar(Unique<PropertyCell>::cast(target->GetUnique()),
                           &index)) {
        result.RemoveFlag(kGlobalVars);
        result.AddSpecial(GlobalVar(index));
        return result;
      }
    }
    for (index = 0; index < kNumberOfGlobalVars; ++index) {
      result.AddSpecial(GlobalVar(index));
    }
  } else if (result.ContainsFlag(kInobjectFields)) {
    if (instr->IsLoadNamedField() &&
        ComputeInobjectField(HLoadNamedField::cast(instr)->access(), &index)) {
      result.RemoveFlag(kInobjectFields);
      result.AddSpecial(InobjectField(index));
    } else {
      for (index = 0; index < kNumberOfInobjectFields; ++index) {
        result.AddSpecial(InobjectField(index));
      }
    }
  }
  return result;
}


std::ostream& operator<<(std::ostream& os, const TrackedEffects& te) {
  SideEffectsTracker* t = te.tracker;
  const char* separator = "";
  os << "[";
  for (int bit = 0; bit < kNumberOfFlags; ++bit) {
    GVNFlag flag = GVNFlagFromInt(bit);
    if (te.effects.ContainsFlag(flag)) {
      os << separator;
      separator = ", ";
      switch (flag) {
#define DECLARE_FLAG(Type) \
  case k##Type:            \
    os << #Type;           \
    break;
GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
#undef DECLARE_FLAG
        default:
            break;
      }
    }
  }
  for (int index = 0; index < t->num_global_vars_; ++index) {
    if (te.effects.ContainsSpecial(t->GlobalVar(index))) {
      os << separator << "[" << *t->global_vars_[index].handle() << "]";
      separator = ", ";
    }
  }
  for (int index = 0; index < t->num_inobject_fields_; ++index) {
    if (te.effects.ContainsSpecial(t->InobjectField(index))) {
      os << separator << t->inobject_fields_[index];
      separator = ", ";
    }
  }
  os << "]";
  return os;
}


bool SideEffectsTracker::ComputeGlobalVar(Unique<PropertyCell> cell,
                                          int* index) {
  for (int i = 0; i < num_global_vars_; ++i) {
    if (cell == global_vars_[i]) {
      *index = i;
      return true;
    }
  }
  if (num_global_vars_ < kNumberOfGlobalVars) {
    if (FLAG_trace_gvn) {
      OFStream os(stdout);
      os << "Tracking global var [" << *cell.handle() << "] "
         << "(mapped to index " << num_global_vars_ << ")" << std::endl;
    }
    *index = num_global_vars_;
    global_vars_[num_global_vars_++] = cell;
    return true;
  }
  return false;
}


bool SideEffectsTracker::ComputeInobjectField(HObjectAccess access,
                                              int* index) {
  for (int i = 0; i < num_inobject_fields_; ++i) {
    if (access.Equals(inobject_fields_[i])) {
      *index = i;
      return true;
    }
  }
  if (num_inobject_fields_ < kNumberOfInobjectFields) {
    if (FLAG_trace_gvn) {
      OFStream os(stdout);
      os << "Tracking inobject field access " << access << " (mapped to index "
         << num_inobject_fields_ << ")" << std::endl;
    }
    *index = num_inobject_fields_;
    inobject_fields_[num_inobject_fields_++] = access;
    return true;
  }
  return false;
}


HGlobalValueNumberingPhase::HGlobalValueNumberingPhase(HGraph* graph)
    : HPhase("H_Global value numbering", graph),
      removed_side_effects_(false),
      block_side_effects_(graph->blocks()->length(), zone()),
      loop_side_effects_(graph->blocks()->length(), zone()),
      visited_on_paths_(graph->blocks()->length(), zone()) {
  DCHECK(!AllowHandleAllocation::IsAllowed());
  block_side_effects_.AddBlock(
      SideEffects(), graph->blocks()->length(), zone());
  loop_side_effects_.AddBlock(
      SideEffects(), graph->blocks()->length(), zone());
}


void HGlobalValueNumberingPhase::Run() {
  DCHECK(!removed_side_effects_);
  for (int i = FLAG_gvn_iterations; i > 0; --i) {
    // Compute the side effects.
    ComputeBlockSideEffects();

    // Perform loop invariant code motion if requested.
    if (FLAG_loop_invariant_code_motion) LoopInvariantCodeMotion();

    // Perform the actual value numbering.
    AnalyzeGraph();

    // Continue GVN if we removed any side effects.
    if (!removed_side_effects_) break;
    removed_side_effects_ = false;

    // Clear all side effects.
    DCHECK_EQ(block_side_effects_.length(), graph()->blocks()->length());
    DCHECK_EQ(loop_side_effects_.length(), graph()->blocks()->length());
    for (int i = 0; i < graph()->blocks()->length(); ++i) {
      block_side_effects_[i].RemoveAll();
      loop_side_effects_[i].RemoveAll();
    }
    visited_on_paths_.Clear();
  }
}


void HGlobalValueNumberingPhase::ComputeBlockSideEffects() {
  for (int i = graph()->blocks()->length() - 1; i >= 0; --i) {
    // Compute side effects for the block.
    HBasicBlock* block = graph()->blocks()->at(i);
    SideEffects side_effects;
    if (block->IsReachable() && !block->IsDeoptimizing()) {
      int id = block->block_id();
      for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
        HInstruction* instr = it.Current();
        side_effects.Add(side_effects_tracker_.ComputeChanges(instr));
      }
      block_side_effects_[id].Add(side_effects);

      // Loop headers are part of their loop.
      if (block->IsLoopHeader()) {
        loop_side_effects_[id].Add(side_effects);
      }

      // Propagate loop side effects upwards.
      if (block->HasParentLoopHeader()) {
        HBasicBlock* with_parent = block;
        if (block->IsLoopHeader()) side_effects = loop_side_effects_[id];
        do {
          HBasicBlock* parent_block = with_parent->parent_loop_header();
          loop_side_effects_[parent_block->block_id()].Add(side_effects);
          with_parent = parent_block;
        } while (with_parent->HasParentLoopHeader());
      }
    }
  }
}


void HGlobalValueNumberingPhase::LoopInvariantCodeMotion() {
  TRACE_GVN_1("Using optimistic loop invariant code motion: %s\n",
              graph()->use_optimistic_licm() ? "yes" : "no");
  for (int i = graph()->blocks()->length() - 1; i >= 0; --i) {
    HBasicBlock* block = graph()->blocks()->at(i);
    if (block->IsLoopHeader()) {
      SideEffects side_effects = loop_side_effects_[block->block_id()];
      if (FLAG_trace_gvn) {
        OFStream os(stdout);
        os << "Try loop invariant motion for " << *block << " changes "
           << Print(side_effects) << std::endl;
      }
      HBasicBlock* last = block->loop_information()->GetLastBackEdge();
      for (int j = block->block_id(); j <= last->block_id(); ++j) {
        ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects);
      }
    }
  }
}


void HGlobalValueNumberingPhase::ProcessLoopBlock(
    HBasicBlock* block,
    HBasicBlock* loop_header,
    SideEffects loop_kills) {
  HBasicBlock* pre_header = loop_header->predecessors()->at(0);
  if (FLAG_trace_gvn) {
    OFStream os(stdout);
    os << "Loop invariant code motion for " << *block << " depends on "
       << Print(loop_kills) << std::endl;
  }
  HInstruction* instr = block->first();
  while (instr != NULL) {
    HInstruction* next = instr->next();
    if (instr->CheckFlag(HValue::kUseGVN)) {
      SideEffects changes = side_effects_tracker_.ComputeChanges(instr);
      SideEffects depends_on = side_effects_tracker_.ComputeDependsOn(instr);
      if (FLAG_trace_gvn) {
        OFStream os(stdout);
        os << "Checking instruction i" << instr->id() << " ("
           << instr->Mnemonic() << ") changes " << Print(changes)
           << ", depends on " << Print(depends_on) << ". Loop changes "
           << Print(loop_kills) << std::endl;
      }
      bool can_hoist = !depends_on.ContainsAnyOf(loop_kills);
      if (can_hoist && !graph()->use_optimistic_licm()) {
        can_hoist = block->IsLoopSuccessorDominator();
      }

      if (can_hoist) {
        bool inputs_loop_invariant = true;
        for (int i = 0; i < instr->OperandCount(); ++i) {
          if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
            inputs_loop_invariant = false;
          }
        }

        if (inputs_loop_invariant && ShouldMove(instr, loop_header)) {
          TRACE_GVN_2("Hoisting loop invariant instruction i%d to block B%d\n",
                      instr->id(), pre_header->block_id());
          // Move the instruction out of the loop.
          instr->Unlink();
          instr->InsertBefore(pre_header->end());
          if (instr->HasSideEffects()) removed_side_effects_ = true;
        }
      }
    }
    instr = next;
  }
}


bool HGlobalValueNumberingPhase::AllowCodeMotion() {
  return info()->IsStub() || info()->opt_count() + 1 < FLAG_max_opt_count;
}


bool HGlobalValueNumberingPhase::ShouldMove(HInstruction* instr,
                                            HBasicBlock* loop_header) {
  // If we've disabled code motion or we're in a block that unconditionally
  // deoptimizes, don't move any instructions.
  return AllowCodeMotion() && !instr->block()->IsDeoptimizing() &&
      instr->block()->IsReachable();
}


SideEffects
HGlobalValueNumberingPhase::CollectSideEffectsOnPathsToDominatedBlock(
    HBasicBlock* dominator, HBasicBlock* dominated) {
  SideEffects side_effects;
  for (int i = 0; i < dominated->predecessors()->length(); ++i) {
    HBasicBlock* block = dominated->predecessors()->at(i);
    if (dominator->block_id() < block->block_id() &&
        block->block_id() < dominated->block_id() &&
        !visited_on_paths_.Contains(block->block_id())) {
      visited_on_paths_.Add(block->block_id());
      side_effects.Add(block_side_effects_[block->block_id()]);
      if (block->IsLoopHeader()) {
        side_effects.Add(loop_side_effects_[block->block_id()]);
      }
      side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock(
          dominator, block));
    }
  }
  return side_effects;
}


// Each instance of this class is like a "stack frame" for the recursive
// traversal of the dominator tree done during GVN (the stack is handled
// as a double linked list).
// We reuse frames when possible so the list length is limited by the depth
// of the dominator tree but this forces us to initialize each frame calling
// an explicit "Initialize" method instead of a using constructor.
class GvnBasicBlockState: public ZoneObject {
 public:
  static GvnBasicBlockState* CreateEntry(Zone* zone,
                                         HBasicBlock* entry_block,
                                         HInstructionMap* entry_map) {
    return new(zone)
        GvnBasicBlockState(NULL, entry_block, entry_map, NULL, zone);
  }

  HBasicBlock* block() { return block_; }
  HInstructionMap* map() { return map_; }
  HSideEffectMap* dominators() { return &dominators_; }

  GvnBasicBlockState* next_in_dominator_tree_traversal(
      Zone* zone,
      HBasicBlock** dominator) {
    // This assignment needs to happen before calling next_dominated() because
    // that call can reuse "this" if we are at the last dominated block.
    *dominator = block();
    GvnBasicBlockState* result = next_dominated(zone);
    if (result == NULL) {
      GvnBasicBlockState* dominator_state = pop();
      if (dominator_state != NULL) {
        // This branch is guaranteed not to return NULL because pop() never
        // returns a state where "is_done() == true".
        *dominator = dominator_state->block();
        result = dominator_state->next_dominated(zone);
      } else {
        // Unnecessary (we are returning NULL) but done for cleanness.
        *dominator = NULL;
      }
    }
    return result;
  }

 private:
  void Initialize(HBasicBlock* block,
                  HInstructionMap* map,
                  HSideEffectMap* dominators,
                  bool copy_map,
                  Zone* zone) {
    block_ = block;
    map_ = copy_map ? map->Copy(zone) : map;
    dominated_index_ = -1;
    length_ = block->dominated_blocks()->length();
    if (dominators != NULL) {
      dominators_ = *dominators;
    }
  }
  bool is_done() { return dominated_index_ >= length_; }

  GvnBasicBlockState(GvnBasicBlockState* previous,
                     HBasicBlock* block,
                     HInstructionMap* map,
                     HSideEffectMap* dominators,
                     Zone* zone)
      : previous_(previous), next_(NULL) {
    Initialize(block, map, dominators, true, zone);
  }

  GvnBasicBlockState* next_dominated(Zone* zone) {
    dominated_index_++;
    if (dominated_index_ == length_ - 1) {
      // No need to copy the map for the last child in the dominator tree.
      Initialize(block_->dominated_blocks()->at(dominated_index_),
                 map(),
                 dominators(),
                 false,
                 zone);
      return this;
    } else if (dominated_index_ < length_) {
      return push(zone, block_->dominated_blocks()->at(dominated_index_));
    } else {
      return NULL;
    }
  }

  GvnBasicBlockState* push(Zone* zone, HBasicBlock* block) {
    if (next_ == NULL) {
      next_ =
          new(zone) GvnBasicBlockState(this, block, map(), dominators(), zone);
    } else {
      next_->Initialize(block, map(), dominators(), true, zone);
    }
    return next_;
  }
  GvnBasicBlockState* pop() {
    GvnBasicBlockState* result = previous_;
    while (result != NULL && result->is_done()) {
      TRACE_GVN_2("Backtracking from block B%d to block b%d\n",
                  block()->block_id(),
                  previous_->block()->block_id())
      result = result->previous_;
    }
    return result;
  }

  GvnBasicBlockState* previous_;
  GvnBasicBlockState* next_;
  HBasicBlock* block_;
  HInstructionMap* map_;
  HSideEffectMap dominators_;
  int dominated_index_;
  int length_;
};


// This is a recursive traversal of the dominator tree but it has been turned
// into a loop to avoid stack overflows.
// The logical "stack frames" of the recursion are kept in a list of
// GvnBasicBlockState instances.
void HGlobalValueNumberingPhase::AnalyzeGraph() {
  HBasicBlock* entry_block = graph()->entry_block();
  HInstructionMap* entry_map =
      new(zone()) HInstructionMap(zone(), &side_effects_tracker_);
  GvnBasicBlockState* current =
      GvnBasicBlockState::CreateEntry(zone(), entry_block, entry_map);

  while (current != NULL) {
    HBasicBlock* block = current->block();
    HInstructionMap* map = current->map();
    HSideEffectMap* dominators = current->dominators();

    TRACE_GVN_2("Analyzing block B%d%s\n",
                block->block_id(),
                block->IsLoopHeader() ? " (loop header)" : "");

    // If this is a loop header kill everything killed by the loop.
    if (block->IsLoopHeader()) {
      map->Kill(loop_side_effects_[block->block_id()]);
      dominators->Kill(loop_side_effects_[block->block_id()]);
    }

    // Go through all instructions of the current block.
    for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
      HInstruction* instr = it.Current();
      if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) {
        for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
          HValue* other = dominators->at(i);
          GVNFlag flag = GVNFlagFromInt(i);
          if (instr->DependsOnFlags().Contains(flag) && other != NULL) {
            TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n",
                        i,
                        instr->id(),
                        instr->Mnemonic(),
                        other->id(),
                        other->Mnemonic());
            if (instr->HandleSideEffectDominator(flag, other)) {
              removed_side_effects_ = true;
            }
          }
        }
      }
      // Instruction was unlinked during graph traversal.
      if (!instr->IsLinked()) continue;

      SideEffects changes = side_effects_tracker_.ComputeChanges(instr);
      if (!changes.IsEmpty()) {
        // Clear all instructions in the map that are affected by side effects.
        // Store instruction as the dominating one for tracked side effects.
        map->Kill(changes);
        dominators->Store(changes, instr);
        if (FLAG_trace_gvn) {
          OFStream os(stdout);
          os << "Instruction i" << instr->id() << " changes " << Print(changes)
             << std::endl;
        }
      }
      if (instr->CheckFlag(HValue::kUseGVN) &&
          !instr->CheckFlag(HValue::kCantBeReplaced)) {
        DCHECK(!instr->HasObservableSideEffects());
        HInstruction* other = map->Lookup(instr);
        if (other != NULL) {
          DCHECK(instr->Equals(other) && other->Equals(instr));
          TRACE_GVN_4("Replacing instruction i%d (%s) with i%d (%s)\n",
                      instr->id(),
                      instr->Mnemonic(),
                      other->id(),
                      other->Mnemonic());
          if (instr->HasSideEffects()) removed_side_effects_ = true;
          instr->DeleteAndReplaceWith(other);
        } else {
          map->Add(instr, zone());
        }
      }
    }

    HBasicBlock* dominator_block;
    GvnBasicBlockState* next =
        current->next_in_dominator_tree_traversal(zone(),
                                                  &dominator_block);

    if (next != NULL) {
      HBasicBlock* dominated = next->block();
      HInstructionMap* successor_map = next->map();
      HSideEffectMap* successor_dominators = next->dominators();

      // Kill everything killed on any path between this block and the
      // dominated block.  We don't have to traverse these paths if the
      // value map and the dominators list is already empty.  If the range
      // of block ids (block_id, dominated_id) is empty there are no such
      // paths.
      if ((!successor_map->IsEmpty() || !successor_dominators->IsEmpty()) &&
          dominator_block->block_id() + 1 < dominated->block_id()) {
        visited_on_paths_.Clear();
        SideEffects side_effects_on_all_paths =
            CollectSideEffectsOnPathsToDominatedBlock(dominator_block,
                                                      dominated);
        successor_map->Kill(side_effects_on_all_paths);
        successor_dominators->Kill(side_effects_on_all_paths);
      }
    }
    current = next;
  }
}

}  // namespace internal
}  // namespace v8
