// Copyright 2017 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.

#ifndef V8_COMPILER_ESCAPE_ANALYSIS_REDUCER_H_
#define V8_COMPILER_ESCAPE_ANALYSIS_REDUCER_H_

#include "src/base/compiler-specific.h"
#include "src/compiler/escape-analysis.h"
#include "src/compiler/graph-reducer.h"
#include "src/globals.h"

namespace v8 {
namespace internal {
namespace compiler {

class Deduplicator;
class JSGraph;

// Perform hash-consing when creating or mutating nodes. Used to avoid duplicate
// nodes when creating ObjectState, StateValues and FrameState nodes
class NodeHashCache {
 public:
  NodeHashCache(Graph* graph, Zone* zone)
      : graph_(graph), cache_(zone), temp_nodes_(zone) {}

  // Handle to a conceptually new mutable node. Tries to re-use existing nodes
  // and to recycle memory if possible.
  class Constructor {
   public:
    // Construct a new node as a clone of [from].
    Constructor(NodeHashCache* cache, Node* from)
        : node_cache_(cache), from_(from), tmp_(nullptr) {}
    // Construct a new node from scratch.
    Constructor(NodeHashCache* cache, const Operator* op, int input_count,
                Node** inputs, Type* type);

    // Modify the new node.
    void ReplaceValueInput(Node* input, int i) {
      if (!tmp_ && input == NodeProperties::GetValueInput(from_, i)) return;
      Node* node = MutableNode();
      NodeProperties::ReplaceValueInput(node, input, i);
    }
    void ReplaceInput(Node* input, int i) {
      if (!tmp_ && input == from_->InputAt(i)) return;
      Node* node = MutableNode();
      node->ReplaceInput(i, input);
    }

    // Obtain the mutated node or a cached copy. Invalidates the [Constructor].
    Node* Get();

   private:
    Node* MutableNode();

    NodeHashCache* node_cache_;
    // Original node, copied on write.
    Node* from_;
    // Temporary node used for mutations, can be recycled if cache is hit.
    Node* tmp_;
  };

 private:
  Node* Query(Node* node);
  void Insert(Node* node) { cache_.insert(node); }

  Graph* graph_;
  struct NodeEquals {
    bool operator()(Node* a, Node* b) const {
      return NodeProperties::Equals(a, b);
    }
  };
  struct NodeHashCode {
    size_t operator()(Node* n) const { return NodeProperties::HashCode(n); }
  };
  ZoneUnorderedSet<Node*, NodeHashCode, NodeEquals> cache_;
  // Unused nodes whose memory can be recycled.
  ZoneVector<Node*> temp_nodes_;
};

// Modify the graph according to the information computed in the previous phase.
class V8_EXPORT_PRIVATE EscapeAnalysisReducer final
    : public NON_EXPORTED_BASE(AdvancedReducer) {
 public:
  EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph,
                        EscapeAnalysisResult analysis_result, Zone* zone);

  Reduction Reduce(Node* node) override;
  const char* reducer_name() const override { return "EscapeAnalysisReducer"; }
  void Finalize() override;

  // Verifies that all virtual allocation nodes have been dealt with. Run it
  // after this reducer has been applied.
  void VerifyReplacement() const;

 private:
  void ReduceFrameStateInputs(Node* node);
  Node* ReduceDeoptState(Node* node, Node* effect, Deduplicator* deduplicator);
  Node* ObjectIdNode(const VirtualObject* vobject);
  Reduction ReplaceNode(Node* original, Node* replacement);

  JSGraph* jsgraph() const { return jsgraph_; }
  EscapeAnalysisResult analysis_result() const { return analysis_result_; }
  Zone* zone() const { return zone_; }

  JSGraph* const jsgraph_;
  EscapeAnalysisResult analysis_result_;
  ZoneVector<Node*> object_id_cache_;
  NodeHashCache node_cache_;
  ZoneSet<Node*> arguments_elements_;
  Zone* const zone_;

  DISALLOW_COPY_AND_ASSIGN(EscapeAnalysisReducer);
};

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_ESCAPE_ANALYSIS_REDUCER_H_
