// 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-removable-simulates.h"

#include "src/crankshaft/hydrogen-flow-engine.h"
#include "src/crankshaft/hydrogen-instructions.h"

namespace v8 {
namespace internal {

class State : public ZoneObject {
 public:
  explicit State(Zone* zone)
      : zone_(zone), mergelist_(2, zone), first_(true), mode_(NORMAL) { }

  State* Process(HInstruction* instr, Zone* zone) {
    if (FLAG_trace_removable_simulates) {
      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
    // side effects to keep live ranges short.
    if (mode_ == COLLECT_CONSECUTIVE_SIMULATES) {
      if (instr->IsSimulate()) {
        HSimulate* current_simulate = HSimulate::cast(instr);
        if (current_simulate->is_candidate_for_removal() &&
            !current_simulate->ast_id().IsNone()) {
          Remember(current_simulate);
          return this;
        }
      }
      FlushSimulates();
      mode_ = NORMAL;
    }
    // Ensure there's a non-foldable HSimulate before an HEnterInlined to avoid
    // folding across HEnterInlined.
    DCHECK(!(instr->IsEnterInlined() &&
             HSimulate::cast(instr->previous())->is_candidate_for_removal()));
    if (instr->IsLeaveInlined() || instr->IsReturn()) {
      // Never fold simulates from inlined environments into simulates in the
      // outer environment. Simply remove all accumulated simulates without
      // merging. This is safe because simulates after instructions with side
      // effects are never added to the merge list. The same reasoning holds for
      // return instructions.
      RemoveSimulates();
      return this;
    }
    if (instr->IsControlInstruction()) {
      // Merge the accumulated simulates at the end of the block.
      FlushSimulates();
      return this;
    }
    if (instr->IsCapturedObject()) {
      // Do not merge simulates across captured objects - captured objects
      // change environments during environment replay, and such changes
      // would not be reflected in the simulate.
      FlushSimulates();
      return this;
    }
    // Skip the non-simulates and the first simulate.
    if (!instr->IsSimulate()) return this;
    if (first_) {
      first_ = false;
      return this;
    }
    HSimulate* current_simulate = HSimulate::cast(instr);
    if (!current_simulate->is_candidate_for_removal()) {
      Remember(current_simulate);
      FlushSimulates();
    } else if (current_simulate->ast_id().IsNone()) {
      DCHECK(current_simulate->next()->IsEnterInlined());
      FlushSimulates();
    } else if (current_simulate->previous()->HasObservableSideEffects()) {
      Remember(current_simulate);
      mode_ = COLLECT_CONSECUTIVE_SIMULATES;
    } else {
      Remember(current_simulate);
    }

    return this;
  }

  static State* Merge(State* succ_state,
                      HBasicBlock* succ_block,
                      State* pred_state,
                      HBasicBlock* pred_block,
                      Zone* zone) {
    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("[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.
    DCHECK(!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;
    return state;
  }

 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 (HasRememberedSimulates()) {
      mergelist_.RemoveLast()->MergeWith(&mergelist_);
    }
  }

  void RemoveSimulates() {
    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.
    DCHECK(!pred_state->HasRememberedSimulates());
    DCHECK(!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_;
  Mode mode_;
};


// We don't use effects here.
class Effects : public ZoneObject {
 public:
  explicit Effects(Zone* zone) { }
  bool Disabled() { return true; }
  void Process(HInstruction* instr, Zone* zone) { }
  void Apply(State* state) { }
  void Union(Effects* that, Zone* zone) { }
};


void HMergeRemovableSimulatesPhase::Run() {
  HFlowEngine<State, Effects> engine(graph(), zone());
  State* state = new(zone()) State(zone());
  engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), state);
}

}  // namespace internal
}  // namespace v8
