// Copyright 2015 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_STATE_VALUES_UTILS_H_
#define V8_COMPILER_STATE_VALUES_UTILS_H_

#include <array>
#include "src/common/globals.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/js-graph.h"

namespace v8 {
namespace internal {

class BitVector;

namespace compiler {

class Graph;

class V8_EXPORT_PRIVATE StateValuesCache {
 public:
  explicit StateValuesCache(JSGraph* js_graph);

  Node* GetNodeForValues(Node** values, size_t count,
                         const BitVector* liveness = nullptr,
                         int liveness_offset = 0);

 private:
  static const size_t kMaxInputCount = 8;
  using WorkingBuffer = std::array<Node*, kMaxInputCount>;

  struct NodeKey {
    Node* node;

    explicit NodeKey(Node* node) : node(node) {}
  };

  struct StateValuesKey : public NodeKey {
    // ValueArray - array of nodes ({node} has to be nullptr).
    size_t count;
    SparseInputMask mask;
    Node** values;

    StateValuesKey(size_t count, SparseInputMask mask, Node** values)
        : NodeKey(nullptr), count(count), mask(mask), values(values) {}
  };

  static bool AreKeysEqual(void* key1, void* key2);
  static bool IsKeysEqualToNode(StateValuesKey* key, Node* node);
  static bool AreValueKeysEqual(StateValuesKey* key1, StateValuesKey* key2);

  // Fills {node_buffer}, starting from {node_count}, with {values}, starting
  // at {values_idx}, sparsely encoding according to {liveness}. {node_count} is
  // updated with the new number of inputs in {node_buffer}, and a bitmask of
  // the sparse encoding is returned.
  SparseInputMask::BitMaskType FillBufferWithValues(WorkingBuffer* node_buffer,
                                                    size_t* node_count,
                                                    size_t* values_idx,
                                                    Node** values, size_t count,
                                                    const BitVector* liveness,
                                                    int liveness_offset);

  Node* BuildTree(size_t* values_idx, Node** values, size_t count,
                  const BitVector* liveness, int liveness_offset, size_t level);

  WorkingBuffer* GetWorkingSpace(size_t level);
  Node* GetEmptyStateValues();
  Node* GetValuesNodeFromCache(Node** nodes, size_t count,
                               SparseInputMask mask);

  Graph* graph() { return js_graph_->graph(); }
  CommonOperatorBuilder* common() { return js_graph_->common(); }

  Zone* zone() { return graph()->zone(); }

  JSGraph* js_graph_;
  CustomMatcherZoneHashMap hash_map_;
  ZoneVector<WorkingBuffer> working_space_;  // One working space per level.
  Node* empty_state_values_;
};

class V8_EXPORT_PRIVATE StateValuesAccess {
 public:
  struct TypedNode {
    Node* node;
    MachineType type;
    TypedNode(Node* node, MachineType type) : node(node), type(type) {}
  };

  class V8_EXPORT_PRIVATE iterator {
   public:
    // Bare minimum of operators needed for range iteration.
    bool operator!=(iterator const& other);
    iterator& operator++();
    TypedNode operator*();

   private:
    friend class StateValuesAccess;

    iterator() : current_depth_(-1) {}
    explicit iterator(Node* node);

    Node* node();
    MachineType type();
    bool done() const;
    void Advance();
    void EnsureValid();

    SparseInputMask::InputIterator* Top();
    void Push(Node* node);
    void Pop();

    static const int kMaxInlineDepth = 8;
    SparseInputMask::InputIterator stack_[kMaxInlineDepth];
    int current_depth_;
  };

  explicit StateValuesAccess(Node* node) : node_(node) {}

  size_t size();
  iterator begin() { return iterator(node_); }
  iterator end() { return iterator(); }

 private:
  Node* node_;
};

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

#endif  // V8_COMPILER_STATE_VALUES_UTILS_H_
