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

// The reason we write our own hash map instead of using unordered_map in STL,
// is that STL containers use a mutex pool on debug build, which will lead to
// deadlock when we are using async signal handler.

#ifndef V8_BASE_HASHMAP_H_
#define V8_BASE_HASHMAP_H_

#include <stdlib.h>

#include "src/base/bits.h"
#include "src/base/hashmap-entry.h"
#include "src/base/logging.h"

namespace v8 {
namespace base {

class DefaultAllocationPolicy {
 public:
  template <typename T, typename TypeTag = T[]>
  V8_INLINE T* NewArray(size_t length) {
    return static_cast<T*>(malloc(length * sizeof(T)));
  }
  template <typename T, typename TypeTag = T[]>
  V8_INLINE void DeleteArray(T* p, size_t length) {
    free(p);
  }
};

template <typename Key, typename Value, class MatchFun, class AllocationPolicy>
class TemplateHashMapImpl {
 public:
  using Entry = TemplateHashMapEntry<Key, Value>;

  // The default capacity.  This is used by the call sites which want
  // to pass in a non-default AllocationPolicy but want to use the
  // default value of capacity specified by the implementation.
  static const uint32_t kDefaultHashMapCapacity = 8;

  // initial_capacity is the size of the initial hash map;
  // it must be a power of 2 (and thus must not be 0).
  explicit TemplateHashMapImpl(uint32_t capacity = kDefaultHashMapCapacity,
                               MatchFun match = MatchFun(),
                               AllocationPolicy allocator = AllocationPolicy());

  TemplateHashMapImpl(const TemplateHashMapImpl&) = delete;
  TemplateHashMapImpl& operator=(const TemplateHashMapImpl&) = delete;

  // Clones the given hashmap and creates a copy with the same entries.
  explicit TemplateHashMapImpl(const TemplateHashMapImpl* original,
                               AllocationPolicy allocator = AllocationPolicy());

  TemplateHashMapImpl(TemplateHashMapImpl&& other) V8_NOEXCEPT = default;

  ~TemplateHashMapImpl();

  TemplateHashMapImpl& operator=(TemplateHashMapImpl&& other)
      V8_NOEXCEPT = default;

  // If an entry with matching key is found, returns that entry.
  // Otherwise, nullptr is returned.
  Entry* Lookup(const Key& key, uint32_t hash) const;

  // If an entry with matching key is found, returns that entry.
  // If no matching entry is found, a new entry is inserted with
  // corresponding key, key hash, and default initialized value.
  Entry* LookupOrInsert(const Key& key, uint32_t hash);

  // If an entry with matching key is found, returns that entry.
  // If no matching entry is found, a new entry is inserted with
  // corresponding key, key hash, and value created by func.
  template <typename Func>
  Entry* LookupOrInsert(const Key& key, uint32_t hash, const Func& value_func);

  // Heterogeneous version of LookupOrInsert, which allows a
  // different lookup key type than the hashmap's key type.
  // The requirement is that MatchFun has an overload:
  //
  //   operator()(const LookupKey& lookup_key, const Key& entry_key)
  //
  // If an entry with matching key is found, returns that entry.
  // If no matching entry is found, a new entry is inserted with
  // a key created by key_func, key hash, and value created by
  // value_func.
  template <typename LookupKey, typename KeyFunc, typename ValueFunc>
  Entry* LookupOrInsert(const LookupKey& lookup_key, uint32_t hash,
                        const KeyFunc& key_func, const ValueFunc& value_func);

  Entry* InsertNew(const Key& key, uint32_t hash);

  // Removes the entry with matching key.
  // It returns the value of the deleted entry
  // or null if there is no value for such key.
  Value Remove(const Key& key, uint32_t hash);

  // Empties the hash map (occupancy() == 0).
  void Clear();

  // Empties the map and makes it unusable for allocation.
  void Invalidate() {
    DCHECK_NOT_NULL(impl_.map_);
    impl_.allocator().DeleteArray(impl_.map_, capacity());
    impl_ = Impl(impl_.match(), AllocationPolicy());
  }

  // The number of (non-empty) entries in the table.
  uint32_t occupancy() const { return impl_.occupancy_; }

  // The capacity of the table. The implementation
  // makes sure that occupancy is at most 80% of
  // the table capacity.
  uint32_t capacity() const { return impl_.capacity_; }

  // Iteration
  //
  // for (Entry* p = map.Start(); p != nullptr; p = map.Next(p)) {
  //   ...
  // }
  //
  // If entries are inserted during iteration, the effect of
  // calling Next() is undefined.
  Entry* Start() const;
  Entry* Next(Entry* entry) const;

  AllocationPolicy allocator() const { return impl_.allocator(); }

 protected:
  void Initialize(uint32_t capacity);

 private:
  Entry* map_end() const { return impl_.map_ + impl_.capacity_; }
  template <typename LookupKey>
  Entry* Probe(const LookupKey& key, uint32_t hash) const;
  Entry* FillEmptyEntry(Entry* entry, const Key& key, const Value& value,
                        uint32_t hash);
  void Resize();

  // To support matcher and allocator that may not be possible to
  // default-construct, we have to store their instances. Using this to store
  // all internal state of the hash map and using private inheritance to store
  // matcher and allocator lets us take advantage of an empty base class
  // optimization to avoid extra space in the common case when MatchFun and
  // AllocationPolicy have no state.
  // TODO(ishell): Once we reach C++20, consider removing the Impl struct and
  // adding match and allocator as [[no_unique_address]] fields.
  struct Impl : private MatchFun, private AllocationPolicy {
    Impl(MatchFun match, AllocationPolicy allocator)
        : MatchFun(std::move(match)), AllocationPolicy(std::move(allocator)) {}

    Impl() = default;
    Impl(const Impl&) V8_NOEXCEPT = default;
    Impl(Impl&& other) V8_NOEXCEPT { *this = std::move(other); }

    Impl& operator=(const Impl& other) V8_NOEXCEPT = default;
    Impl& operator=(Impl&& other) V8_NOEXCEPT {
      MatchFun::operator=(std::move(other));
      AllocationPolicy::operator=(std::move(other));
      map_ = other.map_;
      capacity_ = other.capacity_;
      occupancy_ = other.occupancy_;

      other.map_ = nullptr;
      other.capacity_ = 0;
      other.occupancy_ = 0;
      return *this;
    }

    const MatchFun& match() const { return *this; }
    MatchFun& match() { return *this; }

    const AllocationPolicy& allocator() const { return *this; }
    AllocationPolicy& allocator() { return *this; }

    Entry* map_ = nullptr;
    uint32_t capacity_ = 0;
    uint32_t occupancy_ = 0;
  } impl_;
};
template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::
    TemplateHashMapImpl(uint32_t initial_capacity, MatchFun match,
                        AllocationPolicy allocator)
    : impl_(std::move(match), std::move(allocator)) {
  Initialize(initial_capacity);
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::
    TemplateHashMapImpl(const TemplateHashMapImpl* original,
                        AllocationPolicy allocator)
    : impl_(original->impl_.match(), std::move(allocator)) {
  impl_.capacity_ = original->capacity();
  impl_.occupancy_ = original->occupancy();
  impl_.map_ = impl_.allocator().template NewArray<Entry>(capacity());
  memcpy(impl_.map_, original->impl_.map_, capacity() * sizeof(Entry));
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
TemplateHashMapImpl<Key, Value, MatchFun,
                    AllocationPolicy>::~TemplateHashMapImpl() {
  if (impl_.map_) impl_.allocator().DeleteArray(impl_.map_, capacity());
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Lookup(
    const Key& key, uint32_t hash) const {
  Entry* entry = Probe(key, hash);
  return entry->exists() ? entry : nullptr;
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::LookupOrInsert(
    const Key& key, uint32_t hash) {
  return LookupOrInsert(key, hash, []() { return Value(); });
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
template <typename Func>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::LookupOrInsert(
    const Key& key, uint32_t hash, const Func& value_func) {
  return LookupOrInsert(
      key, hash, [&key]() { return key; }, value_func);
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
template <typename LookupKey, typename KeyFunc, typename ValueFunc>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::LookupOrInsert(
    const LookupKey& lookup_key, uint32_t hash, const KeyFunc& key_func,
    const ValueFunc& value_func) {
  // Find a matching entry.
  Entry* entry = Probe(lookup_key, hash);
  if (entry->exists()) {
    return entry;
  }

  return FillEmptyEntry(entry, key_func(), value_func(), hash);
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::InsertNew(
    const Key& key, uint32_t hash) {
  Entry* entry = Probe(key, hash);
  return FillEmptyEntry(entry, key, Value(), hash);
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
Value TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Remove(
    const Key& key, uint32_t hash) {
  // Lookup the entry for the key to remove.
  Entry* p = Probe(key, hash);
  if (!p->exists()) {
    // Key not found nothing to remove.
    return nullptr;
  }

  Value value = p->value;
  // To remove an entry we need to ensure that it does not create an empty
  // entry that will cause the search for another entry to stop too soon. If all
  // the entries between the entry to remove and the next empty slot have their
  // initial position inside this interval, clearing the entry to remove will
  // not break the search. If, while searching for the next empty entry, an
  // entry is encountered which does not have its initial position between the
  // entry to remove and the position looked at, then this entry can be moved to
  // the place of the entry to remove without breaking the search for it. The
  // entry made vacant by this move is now the entry to remove and the process
  // starts over.
  // Algorithm from http://en.wikipedia.org/wiki/Open_addressing.

  // This guarantees loop termination as there is at least one empty entry so
  // eventually the removed entry will have an empty entry after it.
  DCHECK(occupancy() < capacity());

  // p is the candidate entry to clear. q is used to scan forwards.
  Entry* q = p;  // Start at the entry to remove.
  while (true) {
    // Move q to the next entry.
    q = q + 1;
    if (q == map_end()) {
      q = impl_.map_;
    }

    // All entries between p and q have their initial position between p and q
    // and the entry p can be cleared without breaking the search for these
    // entries.
    if (!q->exists()) {
      break;
    }

    // Find the initial position for the entry at position q.
    Entry* r = impl_.map_ + (q->hash & (capacity() - 1));

    // If the entry at position q has its initial position outside the range
    // between p and q it can be moved forward to position p and will still be
    // found. There is now a new candidate entry for clearing.
    if ((q > p && (r <= p || r > q)) || (q < p && (r <= p && r > q))) {
      *p = *q;
      p = q;
    }
  }

  // Clear the entry which is allowed to en emptied.
  p->clear();
  impl_.occupancy_--;
  return value;
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Clear() {
  // Mark all entries as empty.
  for (size_t i = 0; i < capacity(); ++i) {
    impl_.map_[i].clear();
  }
  impl_.occupancy_ = 0;
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Start() const {
  return Next(impl_.map_ - 1);
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Next(
    Entry* entry) const {
  const Entry* end = map_end();
  DCHECK(impl_.map_ - 1 <= entry && entry < end);
  for (entry++; entry < end; entry++) {
    if (entry->exists()) {
      return entry;
    }
  }
  return nullptr;
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
template <typename LookupKey>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Probe(
    const LookupKey& key, uint32_t hash) const {
  DCHECK(base::bits::IsPowerOfTwo(capacity()));
  size_t i = hash & (capacity() - 1);
  DCHECK(i < capacity());

  DCHECK(occupancy() < capacity());  // Guarantees loop termination.
  Entry* map = impl_.map_;
  while (map[i].exists() &&
         !impl_.match()(hash, map[i].hash, key, map[i].key)) {
    i = (i + 1) & (capacity() - 1);
  }

  return &map[i];
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
typename TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Entry*
TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::FillEmptyEntry(
    Entry* entry, const Key& key, const Value& value, uint32_t hash) {
  DCHECK(!entry->exists());

  new (entry) Entry(key, value, hash);
  impl_.occupancy_++;

  // Grow the map if we reached >= 80% occupancy.
  if (occupancy() + occupancy() / 4 >= capacity()) {
    Resize();
    entry = Probe(key, hash);
  }

  return entry;
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Initialize(
    uint32_t capacity) {
  DCHECK(base::bits::IsPowerOfTwo(capacity));
  impl_.map_ = impl_.allocator().template NewArray<Entry>(capacity);
  if (impl_.map_ == nullptr) {
    FATAL("Out of memory: HashMap::Initialize");
    return;
  }
  impl_.capacity_ = capacity;
  Clear();
}

template <typename Key, typename Value, typename MatchFun,
          class AllocationPolicy>
void TemplateHashMapImpl<Key, Value, MatchFun, AllocationPolicy>::Resize() {
  Entry* old_map = impl_.map_;
  uint32_t old_capacity = capacity();
  uint32_t n = occupancy();

  // Allocate larger map.
  Initialize(capacity() * 2);

  // Rehash all current entries.
  for (Entry* entry = old_map; n > 0; entry++) {
    if (entry->exists()) {
      Entry* new_entry = Probe(entry->key, entry->hash);
      new_entry =
          FillEmptyEntry(new_entry, entry->key, entry->value, entry->hash);
      n--;
    }
  }

  // Delete old map.
  impl_.allocator().DeleteArray(old_map, old_capacity);
}

// Match function which compares hashes before executing a (potentially
// expensive) key comparison.
template <typename Key, typename MatchFun>
struct HashEqualityThenKeyMatcher {
  explicit HashEqualityThenKeyMatcher(MatchFun match) : match_(match) {}

  bool operator()(uint32_t hash1, uint32_t hash2, const Key& key1,
                  const Key& key2) const {
    return hash1 == hash2 && match_(key1, key2);
  }

 private:
  MatchFun match_;
};

// Hashmap<void*, void*> which takes a custom key comparison function pointer.
template <typename AllocationPolicy>
class CustomMatcherTemplateHashMapImpl
    : public TemplateHashMapImpl<
          void*, void*,
          HashEqualityThenKeyMatcher<void*, bool (*)(void*, void*)>,
          AllocationPolicy> {
  using Base = TemplateHashMapImpl<
      void*, void*, HashEqualityThenKeyMatcher<void*, bool (*)(void*, void*)>,
      AllocationPolicy>;

 public:
  using MatchFun = bool (*)(void*, void*);

  explicit CustomMatcherTemplateHashMapImpl(
      MatchFun match, uint32_t capacity = Base::kDefaultHashMapCapacity,
      AllocationPolicy allocator = AllocationPolicy())
      : Base(capacity, HashEqualityThenKeyMatcher<void*, MatchFun>(match),
             allocator) {}

  explicit CustomMatcherTemplateHashMapImpl(
      const CustomMatcherTemplateHashMapImpl* original,
      AllocationPolicy allocator = AllocationPolicy())
      : Base(original, allocator) {}

  CustomMatcherTemplateHashMapImpl(const CustomMatcherTemplateHashMapImpl&) =
      delete;
  CustomMatcherTemplateHashMapImpl& operator=(
      const CustomMatcherTemplateHashMapImpl&) = delete;
};

using CustomMatcherHashMap =
    CustomMatcherTemplateHashMapImpl<DefaultAllocationPolicy>;

// Match function which compares keys directly by equality.
template <typename Key>
struct KeyEqualityMatcher {
  bool operator()(uint32_t hash1, uint32_t hash2, const Key& key1,
                  const Key& key2) const {
    return key1 == key2;
  }
};

// Hashmap<void*, void*> which compares the key pointers directly.
template <typename AllocationPolicy>
class PointerTemplateHashMapImpl
    : public TemplateHashMapImpl<void*, void*, KeyEqualityMatcher<void*>,
                                 AllocationPolicy> {
  using Base = TemplateHashMapImpl<void*, void*, KeyEqualityMatcher<void*>,
                                   AllocationPolicy>;

 public:
  explicit PointerTemplateHashMapImpl(
      uint32_t capacity = Base::kDefaultHashMapCapacity,
      AllocationPolicy allocator = AllocationPolicy())
      : Base(capacity, KeyEqualityMatcher<void*>(), allocator) {}

  PointerTemplateHashMapImpl(const PointerTemplateHashMapImpl& other,
                             AllocationPolicy allocator = AllocationPolicy())
      : Base(&other, allocator) {}

  PointerTemplateHashMapImpl(PointerTemplateHashMapImpl&& other) V8_NOEXCEPT
      : Base(std::move(other)) {}

  PointerTemplateHashMapImpl& operator=(PointerTemplateHashMapImpl&& other)
      V8_NOEXCEPT {
    static_cast<Base&>(*this) = std::move(other);
    return *this;
  }
};

using HashMap = PointerTemplateHashMapImpl<DefaultAllocationPolicy>;

// A hash map for pointer keys and values with an STL-like interface.
template <class Key, class Value, class MatchFun, class AllocationPolicy>
class TemplateHashMap
    : private TemplateHashMapImpl<void*, void*,
                                  HashEqualityThenKeyMatcher<void*, MatchFun>,
                                  AllocationPolicy> {
  using Base = TemplateHashMapImpl<void*, void*,
                                   HashEqualityThenKeyMatcher<void*, MatchFun>,
                                   AllocationPolicy>;

 public:
  STATIC_ASSERT(sizeof(Key*) == sizeof(void*));    // NOLINT
  STATIC_ASSERT(sizeof(Value*) == sizeof(void*));  // NOLINT
  struct value_type {
    Key* first;
    Value* second;
  };

  class Iterator {
   public:
    Iterator& operator++() {
      entry_ = map_->Next(entry_);
      return *this;
    }

    value_type* operator->() { return reinterpret_cast<value_type*>(entry_); }
    bool operator!=(const Iterator& other) { return entry_ != other.entry_; }

   private:
    Iterator(const Base* map, typename Base::Entry* entry)
        : map_(map), entry_(entry) {}

    const Base* map_;
    typename Base::Entry* entry_;

    friend class TemplateHashMap;
  };

  explicit TemplateHashMap(MatchFun match,
                           AllocationPolicy allocator = AllocationPolicy())
      : Base(Base::kDefaultHashMapCapacity,
             HashEqualityThenKeyMatcher<void*, MatchFun>(match), allocator) {}

  Iterator begin() const { return Iterator(this, this->Start()); }
  Iterator end() const { return Iterator(this, nullptr); }
  Iterator find(Key* key, bool insert = false) {
    if (insert) {
      return Iterator(this, this->LookupOrInsert(key, key->Hash()));
    }
    return Iterator(this, this->Lookup(key, key->Hash()));
  }
};

}  // namespace base
}  // namespace v8

#endif  // V8_BASE_HASHMAP_H_
