// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_HASH_MAP_H_
#define RUNTIME_VM_HASH_MAP_H_

#include "platform/utils.h"
#include "vm/growable_array.h"  // For Malloc, EmptyBase
#include "vm/hash.h"
#include "vm/zone.h"

namespace dart {

template <typename KeyValueTrait, typename B, typename Allocator = Zone>
class BaseDirectChainedHashMap : public B {
 public:
  explicit BaseDirectChainedHashMap(Allocator* allocator,
                                    intptr_t initial_size = kInitialSize)
      : allocator_(allocator) {
    Resize(initial_size);
  }

  BaseDirectChainedHashMap(const BaseDirectChainedHashMap& other);

  intptr_t Length() const { return next_pair_index_ - deleted_count_; }

  ~BaseDirectChainedHashMap() {
    allocator_->template Free<uint32_t>(hash_table_, hash_table_size_);
    allocator_->template Free<typename KeyValueTrait::Pair>(pairs_,
                                                            pairs_size_);
  }

  // Assumes that no existing pair in the map has a key equal to [kv.key].
  void Insert(typename KeyValueTrait::Pair kv);
  bool Remove(typename KeyValueTrait::Key key);

  // If a pair already exists in the map with an equal key, replace that pair
  // with this one. Otherwise, insert the pair as a new entry.
  //
  // Note: Insert operates in constant time, while Update must walk the chained
  // entries for a given hash value, checking keys for equality. However, if
  // multiple value updates are needed for the same key, only using Update
  // guarantees constant space usage whereas Insert does not.
  void Update(typename KeyValueTrait::Pair kv);

  typename KeyValueTrait::Value LookupValue(
      typename KeyValueTrait::Key key) const;

  typename KeyValueTrait::Pair* Lookup(typename KeyValueTrait::Key key) const;
  bool HasKey(typename KeyValueTrait::Key key) const {
    return Lookup(key) != nullptr;
  }

  intptr_t Size() const { return next_pair_index_ - deleted_count_; }
  bool IsEmpty() const { return Size() == 0; }

  void Clear() {
    for (uint32_t i = 0; i < hash_table_size_; i++) {
      hash_table_[i] = kEmpty;
    }
    for (uint32_t i = 0; i < next_pair_index_; i++) {
      pairs_[i] = typename KeyValueTrait::Pair();
    }
    next_pair_index_ = 0;
    deleted_count_ = 0;
  }

  class Iterator {
   public:
    typename KeyValueTrait::Pair* Next();

    void Reset() { pair_index_ = 0; }

   private:
    explicit Iterator(const BaseDirectChainedHashMap& map)
        : map_(map), pair_index_(0) {}

    const BaseDirectChainedHashMap& map_;
    uint32_t pair_index_;

    template <typename T, typename Bs, typename A>
    friend class BaseDirectChainedHashMap;
  };

  Iterator GetIterator() const { return Iterator(*this); }

 protected:
  static constexpr intptr_t kInitialSize = 16;

  void Resize(intptr_t new_size);

  Allocator* const allocator_;
  uint32_t* hash_table_ = nullptr;
  typename KeyValueTrait::Pair* pairs_ = nullptr;
  uint32_t hash_table_size_ = 0;
  uint32_t pairs_size_ = 0;
  uint32_t next_pair_index_ = 0;
  uint32_t deleted_count_ = 0;

  static constexpr uint32_t kEmpty = kMaxUint32;
  static constexpr uint32_t kDeleted = kMaxUint32 - 1;
  static constexpr uint32_t kMaxPairs = kMaxUint32 - 2;

 private:
  void operator=(const BaseDirectChainedHashMap& other) = delete;
};

template <typename KeyValueTrait, typename B, typename Allocator>
BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::BaseDirectChainedHashMap(
    const BaseDirectChainedHashMap& other)
    : B(),
      allocator_(other.allocator_),
      hash_table_(
          other.allocator_->template Alloc<uint32_t>(other.hash_table_size_)),
      pairs_(other.allocator_->template Alloc<typename KeyValueTrait::Pair>(
          other.pairs_size_)),
      hash_table_size_(other.hash_table_size_),
      pairs_size_(other.pairs_size_),
      next_pair_index_(other.next_pair_index_),
      deleted_count_(other.deleted_count_) {
  memmove(hash_table_, other.hash_table_, hash_table_size_ * sizeof(uint32_t));
  memmove(pairs_, other.pairs_,
          pairs_size_ * sizeof(typename KeyValueTrait::Pair));
}

template <typename KeyValueTrait, typename B, typename Allocator>
typename KeyValueTrait::Pair*
BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Lookup(
    typename KeyValueTrait::Key key) const {
  uword hash = KeyValueTrait::Hash(key);
  uint32_t mask = hash_table_size_ - 1;
  uint32_t hash_index = hash & mask;
  uint32_t start = hash_index;
  for (;;) {
    uint32_t pair_index = hash_table_[hash_index];
    if (pair_index == kEmpty) {
      return nullptr;
    }
    if (pair_index != kDeleted) {
      ASSERT(pair_index < pairs_size_);
      if (KeyValueTrait::IsKeyEqual(pairs_[pair_index], key)) {
        return &pairs_[pair_index];
      }
    }
    hash_index = (hash_index + 1) & mask;
    // Hashtable must contain at least one empty marker.
    ASSERT(hash_index != start);
  }
  UNREACHABLE();
  return nullptr;
}

template <typename KeyValueTrait, typename B, typename Allocator>
typename KeyValueTrait::Value
BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::LookupValue(
    typename KeyValueTrait::Key key) const {
  const typename KeyValueTrait::Value kNoValue =
      KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
  typename KeyValueTrait::Pair* pair = Lookup(key);
  return (pair == nullptr) ? kNoValue : KeyValueTrait::ValueOf(*pair);
}

template <typename KeyValueTrait, typename B, typename Allocator>
typename KeyValueTrait::Pair*
BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Iterator::Next() {
  const typename KeyValueTrait::Value kNoValue =
      KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
  while (pair_index_ < map_.next_pair_index_) {
    if (KeyValueTrait::ValueOf(map_.pairs_[pair_index_]) != kNoValue) {
      intptr_t old_index = pair_index_;
      pair_index_++;
      return &map_.pairs_[old_index];
    }
    pair_index_++;
  }
  return nullptr;
}

template <typename KeyValueTrait, typename B, typename Allocator>
void BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Resize(
    intptr_t new_size) {
  ASSERT(new_size >= Size());

  uint32_t old_hash_table_size = hash_table_size_;
  // 75% load factor + at least one kEmpty slot
  hash_table_size_ = Utils::RoundUpToPowerOfTwo(new_size * 4 / 3 + 1);
  hash_table_ = allocator_->template Realloc<uint32_t>(
      hash_table_, old_hash_table_size, hash_table_size_);
  for (uint32_t i = 0; i < hash_table_size_; i++) {
    hash_table_[i] = kEmpty;
  }

  typename KeyValueTrait::Pair* old_pairs = pairs_;
  uint32_t old_pairs_size = pairs_size_;
  uint32_t old_next_pair_index = next_pair_index_;
  uint32_t old_deleted_count = deleted_count_;
  next_pair_index_ = 0;
  deleted_count_ = 0;
  pairs_size_ = new_size;
  pairs_ =
      allocator_->template Alloc<typename KeyValueTrait::Pair>(pairs_size_);
  for (uint32_t i = 0; i < pairs_size_; i++) {
    pairs_[i] = typename KeyValueTrait::Pair();
  }

  const typename KeyValueTrait::Value kNoValue =
      KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
  uint32_t used = 0;
  uint32_t deleted = 0;
  for (uint32_t i = 0; i < old_next_pair_index; i++) {
    if (KeyValueTrait::ValueOf(old_pairs[i]) == kNoValue) {
      deleted++;
    } else {
      Insert(old_pairs[i]);
      used++;
    }
  }
  ASSERT_EQUAL(deleted, old_deleted_count);
  ASSERT_EQUAL(used, old_next_pair_index - old_deleted_count);
  ASSERT_EQUAL(used, next_pair_index_);
  allocator_->template Free<typename KeyValueTrait::Pair>(old_pairs,
                                                          old_pairs_size);
}

template <typename KeyValueTrait, typename B, typename Allocator>
void BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Insert(
    typename KeyValueTrait::Pair kv) {
  // TODO(dartbug.com/38018):
  // ASSERT(Lookup(KeyValueTrait::KeyOf(kv)) == nullptr);
  ASSERT(next_pair_index_ < pairs_size_);
  uword hash = KeyValueTrait::Hash(KeyValueTrait::KeyOf(kv));
  uint32_t mask = hash_table_size_ - 1;
  uint32_t hash_index = hash & mask;
  uint32_t start = hash_index;
  for (;;) {
    uint32_t pair_index = hash_table_[hash_index];
    if ((pair_index == kEmpty) || (pair_index == kDeleted)) {
      hash_table_[hash_index] = next_pair_index_;
      pairs_[next_pair_index_] = kv;
      next_pair_index_++;
      break;
    }
    ASSERT(pair_index < pairs_size_);
    hash_index = (hash_index + 1) & mask;
    // Hashtable must contain at least one empty marker.
    ASSERT(hash_index != start);
  }

  if (next_pair_index_ == pairs_size_) {
    Resize(Size() << 1);
  }
}

template <typename KeyValueTrait, typename B, typename Allocator>
void BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Update(
    typename KeyValueTrait::Pair kv) {
  const typename KeyValueTrait::Value kNoValue =
      KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());

  ASSERT(KeyValueTrait::ValueOf(kv) != kNoValue);
  if (auto const old_kv = Lookup(KeyValueTrait::KeyOf(kv))) {
    *old_kv = kv;
  } else {
    Insert(kv);
  }
}

template <typename KeyValueTrait, typename B, typename Allocator>
bool BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Remove(
    typename KeyValueTrait::Key key) {
  uword hash = KeyValueTrait::Hash(key);
  uint32_t mask = hash_table_size_ - 1;
  uint32_t hash_index = hash & mask;
  uint32_t start = hash_index;
  for (;;) {
    uint32_t pair_index = hash_table_[hash_index];
    if (pair_index == kEmpty) {
      return false;
    }
    if (pair_index != kDeleted) {
      ASSERT(pair_index < pairs_size_);
      if (KeyValueTrait::IsKeyEqual(pairs_[pair_index], key)) {
        hash_table_[hash_index] = kDeleted;
        pairs_[pair_index] = typename KeyValueTrait::Pair();
        deleted_count_++;
        return true;
      }
    }
    hash_index = (hash_index + 1) & mask;
    // Hashtable must contain at least one empty marker.
    ASSERT(hash_index != start);
  }
  UNREACHABLE();
  return false;
}

template <typename KeyValueTrait>
class DirectChainedHashMap
    : public BaseDirectChainedHashMap<KeyValueTrait, ValueObject> {
 public:
  DirectChainedHashMap()
      : BaseDirectChainedHashMap<KeyValueTrait, ValueObject>(
            ASSERT_NOTNULL(ThreadState::Current()->zone())) {}

  explicit DirectChainedHashMap(
      Zone* zone,
      intptr_t initial_size = DirectChainedHashMap::kInitialSize)
      : BaseDirectChainedHashMap<KeyValueTrait, ValueObject>(
            ASSERT_NOTNULL(zone),
            initial_size) {}

  // There is a current use of the copy constructor in CSEInstructionMap
  // (compiler/backend/redundancy_elimination.cc), so work is needed if we
  // want to disallow it.
  DirectChainedHashMap(const DirectChainedHashMap& other)
      : BaseDirectChainedHashMap<KeyValueTrait, ValueObject>(other) {}

 private:
  void operator=(const DirectChainedHashMap& other) = delete;
};

template <typename KeyValueTrait>
class MallocDirectChainedHashMap
    : public BaseDirectChainedHashMap<KeyValueTrait, MallocAllocated, Malloc> {
 public:
  MallocDirectChainedHashMap(
      intptr_t initial_size = MallocDirectChainedHashMap::kInitialSize)
      : BaseDirectChainedHashMap<KeyValueTrait, MallocAllocated, Malloc>(
            nullptr,
            initial_size) {}

  // The only use of the copy constructor seems to be in hash_map_test.cc.
  // Not disallowing it for now just in case there are other users.
  MallocDirectChainedHashMap(const MallocDirectChainedHashMap& other)
      : BaseDirectChainedHashMap<KeyValueTrait, MallocAllocated, Malloc>(
            other) {}

 private:
  void operator=(const MallocDirectChainedHashMap& other) = delete;
};

template <typename KeyValueTrait>
class ZoneDirectChainedHashMap
    : public BaseDirectChainedHashMap<KeyValueTrait, ZoneAllocated, Zone> {
 public:
  ZoneDirectChainedHashMap()
      : BaseDirectChainedHashMap<KeyValueTrait, ZoneAllocated, Zone>(
            ThreadState::Current()->zone()) {}
  explicit ZoneDirectChainedHashMap(
      Zone* zone,
      intptr_t initial_size = ZoneDirectChainedHashMap::kInitialSize)
      : BaseDirectChainedHashMap<KeyValueTrait, ZoneAllocated, Zone>(
            zone,
            initial_size) {}

 private:
  DISALLOW_COPY_AND_ASSIGN(ZoneDirectChainedHashMap);
};

template <typename T>
class PointerSetKeyValueTrait {
 public:
  typedef T* Value;
  typedef T* Key;
  typedef T* Pair;

  static Key KeyOf(Pair kv) { return kv; }
  static Value ValueOf(Pair kv) { return kv; }
  static inline uword Hash(Key key) { return key->Hash(); }
  static inline bool IsKeyEqual(Pair kv, Key key) { return kv->Equals(*key); }
};

template <typename T>
using PointerSet = DirectChainedHashMap<PointerSetKeyValueTrait<T>>;

template <typename T>
class NumbersKeyValueTrait {
 public:
  typedef T Value;
  typedef intptr_t Key;
  typedef T Pair;

  static intptr_t KeyOf(Pair kv) { return kv.first(); }
  static T ValueOf(Pair kv) { return kv; }
  static inline uword Hash(Key key) { return key; }
  static inline bool IsKeyEqual(Pair kv, Key key) { return kv.first() == key; }
};

template <typename K, typename V>
class RawPointerKeyValueTrait {
 public:
  typedef K* Key;
  typedef V Value;

  struct Pair {
    Key key;
    Value value;
    Pair() : key(nullptr), value() {}
    Pair(const Key key, const Value& value) : key(key), value(value) {}
    Pair(const Pair& other) : key(other.key), value(other.value) {}
    Pair& operator=(const Pair&) = default;
  };

  static Key KeyOf(Pair kv) { return kv.key; }
  static Value ValueOf(Pair kv) { return kv.value; }
  static uword Hash(Key key) { return reinterpret_cast<intptr_t>(key); }
  static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; }
};

class CStringSetKeyValueTrait {
 public:
  using Key = const char*;
  using Value = const char*;
  using Pair = const char*;

  static Key KeyOf(Pair kv) { return kv; }
  static Value ValueOf(Pair kv) { return kv; }
  static uword Hash(Key key) {
    ASSERT(key != nullptr);
    return Utils::StringHash(key, strlen(key));
  }
  static bool IsKeyEqual(Pair kv, Key key) {
    ASSERT(kv != nullptr && key != nullptr);
    return kv == key || strcmp(kv, key) == 0;
  }
};

template <typename B, typename Allocator>
class BaseCStringSet
    : public BaseDirectChainedHashMap<CStringSetKeyValueTrait, B, Allocator> {
 public:
  explicit BaseCStringSet(Allocator* allocator)
      : BaseDirectChainedHashMap<CStringSetKeyValueTrait, B, Allocator>(
            allocator) {}

 private:
  DISALLOW_COPY_AND_ASSIGN(BaseCStringSet);
};

class ZoneCStringSet : public BaseCStringSet<ZoneAllocated, Zone> {
 public:
  ZoneCStringSet()
      : BaseCStringSet<ZoneAllocated, Zone>(ThreadState::Current()->zone()) {}
  explicit ZoneCStringSet(Zone* zone)
      : BaseCStringSet<ZoneAllocated, Zone>(zone) {}

 private:
  DISALLOW_COPY_AND_ASSIGN(ZoneCStringSet);
};

struct CStringIntMapKeyValueTrait {
  using Key = const char*;
  using Value = intptr_t;

  static constexpr Value kNoValue = kIntptrMin;

  struct Pair {
    Key key;
    Value value;
    Pair() : key(nullptr), value(kNoValue) {}
    Pair(const Key key, const Value& value) : key(key), value(value) {}
    Pair(const Pair& other) : key(other.key), value(other.value) {}
    Pair& operator=(const Pair&) = default;
  };

  static Key KeyOf(const Pair& pair) { return pair.key; }
  static Value ValueOf(const Pair& pair) { return pair.value; }
  static uword Hash(const Key& key) {
    ASSERT(key != nullptr);
    return Utils::StringHash(key, strlen(key));
  }
  static bool IsKeyEqual(const Pair& kv, const Key& key) {
    ASSERT(kv.key != nullptr && key != nullptr);
    return kv.key == key || strcmp(kv.key, key) == 0;
  }
};

template <typename B, typename Allocator>
class BaseCStringIntMap
    : public BaseDirectChainedHashMap<CStringIntMapKeyValueTrait,
                                      B,
                                      Allocator> {
 public:
  explicit BaseCStringIntMap(Allocator* allocator)
      : BaseDirectChainedHashMap<CStringIntMapKeyValueTrait, B, Allocator>(
            allocator) {}

 private:
  DISALLOW_COPY_AND_ASSIGN(BaseCStringIntMap);
};

class CStringIntMap : public BaseCStringIntMap<ValueObject, Zone> {
 public:
  CStringIntMap()
      : BaseCStringIntMap<ValueObject, Zone>(ThreadState::Current()->zone()) {}
  explicit CStringIntMap(Zone* zone)
      : BaseCStringIntMap<ValueObject, Zone>(zone) {}

 private:
  DISALLOW_COPY_AND_ASSIGN(CStringIntMap);
};

template <typename V>
class IntKeyRawPointerValueTrait {
 public:
  typedef intptr_t Key;
  typedef V Value;

  struct Pair {
    Key key;
    Value value;
    Pair() : key(0), value() {}
    Pair(const Key key, const Value& value) : key(key), value(value) {}
    Pair(const Pair& other) : key(other.key), value(other.value) {}
    Pair& operator=(const Pair&) = default;
  };

  static Key KeyOf(Pair kv) { return kv.key; }
  static Value ValueOf(Pair kv) { return kv.value; }
  static uword Hash(Key key) { return key; }
  static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; }
};

template <typename V>
class IntMap : public DirectChainedHashMap<IntKeyRawPointerValueTrait<V> > {
 public:
  IntMap() : DirectChainedHashMap<IntKeyRawPointerValueTrait<V>>() {}
  explicit IntMap(Zone* zone)
      : DirectChainedHashMap<IntKeyRawPointerValueTrait<V>>(zone) {}

  typedef typename IntKeyRawPointerValueTrait<V>::Key Key;
  typedef typename IntKeyRawPointerValueTrait<V>::Value Value;
  typedef typename IntKeyRawPointerValueTrait<V>::Pair Pair;

  inline void Insert(const Key& key, const Value& value) {
    Pair pair(key, value);
    DirectChainedHashMap<IntKeyRawPointerValueTrait<V> >::Insert(pair);
  }

  inline V Lookup(const Key& key) const {
    Pair* pair =
        DirectChainedHashMap<IntKeyRawPointerValueTrait<V> >::Lookup(key);
    if (pair == nullptr) {
      return V();
    } else {
      return pair->value;
    }
  }

  inline Pair* LookupPair(const Key& key) const {
    return DirectChainedHashMap<IntKeyRawPointerValueTrait<V> >::Lookup(key);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(IntMap);
};

template <typename V>
class IdentitySetKeyValueTrait {
 public:
  // Typedefs needed for the DirectChainedHashMap template.
  typedef V Key;
  typedef V Value;
  typedef V Pair;

  static Key KeyOf(Pair kv) { return kv; }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) {
    return Utils::StringHash(reinterpret_cast<const char*>(&key), sizeof(key));
  }

  static inline bool IsKeyEqual(Pair pair, Key key) { return pair == key; }
};

}  // namespace dart

#endif  // RUNTIME_VM_HASH_MAP_H_
