// 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_UTILS_IDENTITY_MAP_H_
#define V8_UTILS_IDENTITY_MAP_H_

#include <type_traits>

#include "src/base/functional.h"
#include "src/handles/handles.h"
#include "src/objects/heap-object.h"

namespace v8 {
namespace internal {

// Forward declarations.
class Heap;
class StrongRootsEntry;

template <typename T>
struct IdentityMapFindResult {
  T* entry;
  bool already_exists;
};

// Base class of identity maps contains shared code for all template
// instantions.
class V8_EXPORT_PRIVATE IdentityMapBase {
 public:
  bool empty() const { return size_ == 0; }
  int size() const { return size_; }
  int capacity() const { return capacity_; }
  bool is_iterable() const { return is_iterable_; }

 protected:
  // Allow Tester to access internals, including changing the address of objects
  // within the {keys_} array in order to simulate a moving GC.
  friend class IdentityMapTester;

  using RawEntry = uintptr_t*;

  explicit IdentityMapBase(Heap* heap)
      : heap_(heap),
        gc_counter_(-1),
        size_(0),
        capacity_(0),
        mask_(0),
        keys_(nullptr),
        strong_roots_entry_(nullptr),
        values_(nullptr),
        is_iterable_(false) {}
  virtual ~IdentityMapBase();

  IdentityMapFindResult<uintptr_t> FindOrInsertEntry(Address key);
  RawEntry FindEntry(Address key) const;
  RawEntry InsertEntry(Address key);
  bool DeleteEntry(Address key, uintptr_t* deleted_value);
  void Clear();

  Address KeyAtIndex(int index) const;

  RawEntry EntryAtIndex(int index) const;
  int NextIndex(int index) const;

  void EnableIteration();
  void DisableIteration();

  virtual uintptr_t* NewPointerArray(size_t length) = 0;
  virtual void DeletePointerArray(uintptr_t* array, size_t length) = 0;

 private:
  // Internal implementation should not be called directly by subclasses.
  int ScanKeysFor(Address address, uint32_t hash) const;
  std::pair<int, bool> InsertKey(Address address, uint32_t hash);
  int Lookup(Address key) const;
  std::pair<int, bool> LookupOrInsert(Address key);
  bool DeleteIndex(int index, uintptr_t* deleted_value);
  void Rehash();
  void Resize(int new_capacity);
  uint32_t Hash(Address address) const;

  base::hash<uintptr_t> hasher_;
  Heap* heap_;
  int gc_counter_;
  int size_;
  int capacity_;
  int mask_;
  Address* keys_;
  StrongRootsEntry* strong_roots_entry_;
  uintptr_t* values_;
  bool is_iterable_;

  DISALLOW_COPY_AND_ASSIGN(IdentityMapBase);
};

// Implements an identity map from object addresses to a given value type {V}.
// The map is robust w.r.t. garbage collection by synchronization with the
// supplied {heap}.
//  * Keys are treated as strong roots.
//  * The value type {V} must be reinterpret_cast'able to {uintptr_t}
//  * The value type {V} must not be a heap type.
template <typename V, class AllocationPolicy>
class IdentityMap : public IdentityMapBase {
 public:
  STATIC_ASSERT(sizeof(V) <= sizeof(uintptr_t));
  STATIC_ASSERT(std::is_trivially_copyable<V>::value);
  STATIC_ASSERT(std::is_trivially_destructible<V>::value);

  explicit IdentityMap(Heap* heap,
                       AllocationPolicy allocator = AllocationPolicy())
      : IdentityMapBase(heap), allocator_(allocator) {}
  ~IdentityMap() override { Clear(); }

  // Searches this map for the given key using the object's address
  // as the identity, returning:
  //    found => a pointer to the storage location for the value, true
  //    not found => a pointer to a new storage location for the value, false
  IdentityMapFindResult<V> FindOrInsert(Handle<Object> key) {
    return FindOrInsert(*key);
  }
  IdentityMapFindResult<V> FindOrInsert(Object key) {
    auto raw = FindOrInsertEntry(key.ptr());
    return {reinterpret_cast<V*>(raw.entry), raw.already_exists};
  }

  // Searches this map for the given key using the object's address
  // as the identity, returning:
  //    found => a pointer to the storage location for the value
  //    not found => {nullptr}
  V* Find(Handle<Object> key) const { return Find(*key); }
  V* Find(Object key) const {
    return reinterpret_cast<V*>(FindEntry(key.ptr()));
  }

  // Insert the value for the given key. The key must not have previously
  // existed.
  void Insert(Handle<Object> key, V v) { Insert(*key, v); }
  void Insert(Object key, V v) {
    *reinterpret_cast<V*>(InsertEntry(key.ptr())) = v;
  }

  bool Delete(Handle<Object> key, V* deleted_value) {
    return Delete(*key, deleted_value);
  }
  bool Delete(Object key, V* deleted_value) {
    uintptr_t v;
    bool deleted_something = DeleteEntry(key.ptr(), &v);
    if (deleted_value != nullptr && deleted_something) {
      *deleted_value = *reinterpret_cast<V*>(&v);
    }
    return deleted_something;
  }

  // Removes all elements from the map.
  void Clear() { IdentityMapBase::Clear(); }

  // Iterator over IdentityMap. The IteratableScope used to create this Iterator
  // must be live for the duration of the iteration.
  class Iterator {
   public:
    Iterator& operator++() {
      index_ = map_->NextIndex(index_);
      return *this;
    }

    Object key() const { return Object(map_->KeyAtIndex(index_)); }
    V* entry() const {
      return reinterpret_cast<V*>(map_->EntryAtIndex(index_));
    }

    V* operator*() { return entry(); }
    V* operator->() { return entry(); }
    bool operator!=(const Iterator& other) { return index_ != other.index_; }

   private:
    Iterator(IdentityMap* map, int index) : map_(map), index_(index) {}

    IdentityMap* map_;
    int index_;

    friend class IdentityMap;
  };

  class IteratableScope {
   public:
    explicit IteratableScope(IdentityMap* map) : map_(map) {
      CHECK(!map_->is_iterable());
      map_->EnableIteration();
    }
    ~IteratableScope() {
      CHECK(map_->is_iterable());
      map_->DisableIteration();
    }

    Iterator begin() { return Iterator(map_, map_->NextIndex(-1)); }
    Iterator end() { return Iterator(map_, map_->capacity()); }

   private:
    IdentityMap* map_;
    DISALLOW_COPY_AND_ASSIGN(IteratableScope);
  };

 protected:
  // This struct is just a type tag for Zone::NewArray<T>(size_t) call.
  struct Buffer {};

  // TODO(ishell): consider removing virtual methods in favor of combining
  // IdentityMapBase and IdentityMap into one class. This would also save
  // space when sizeof(V) is less than sizeof(uintptr_t).
  uintptr_t* NewPointerArray(size_t length) override {
    return allocator_.template NewArray<uintptr_t, Buffer>(length);
  }
  void DeletePointerArray(uintptr_t* array, size_t length) override {
    allocator_.template DeleteArray<uintptr_t, Buffer>(array, length);
  }

 private:
  AllocationPolicy allocator_;
  DISALLOW_COPY_AND_ASSIGN(IdentityMap);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_UTILS_IDENTITY_MAP_H_
