// 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"
#include "src/zone/zone-hashmap.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:
    bool operator!=(iterator const& other) const;
    iterator& operator++();
    TypedNode operator*();

    Node* node();
    bool done() const { return current_depth_ < 0; }

    // Returns the number of empty nodes that were skipped over.
    size_t AdvanceTillNotEmpty();

   private:
    friend class StateValuesAccess;

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

    MachineType type();
    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() const;
  iterator begin() const { return iterator(node_); }
  iterator end() const { return iterator(); }

 private:
  Node* node_;
};

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

#endif  // V8_COMPILER_STATE_VALUES_UTILS_H_
