5#ifndef V8_COMPILER_PERSISTENT_MAP_H_
6#define V8_COMPILER_PERSISTENT_MAP_H_
23 bool operator()(
const T& a,
const T& b) {
return a != b; }
42template <
class Key,
class Value,
class Hasher = base::hash<Key>>
59 const Key&
key()
const {
return this->first; }
61 using std::pair<Key,
Value>::pair;
93 if (
tree_ == other.tree_)
return true;
94 if (
def_value_ != other.def_value_)
return false;
95 for (std::tuple<Key, Value, Value> triple :
Zip(other)) {
96 if (std::get<1>(triple) != std::get<2>(triple))
return false;
102 return !(*
this == other);
119 class double_iterator;
144 std::array<const FocusedTree*, kHashBits>* path,
153 static const FocusedTree*
GetChild(
const FocusedTree* tree,
int level,
160 const FocusedTree*
start,
int* level,
161 std::array<const FocusedTree*, kHashBits>* path);
171template <
class Key,
class Value,
class Hasher>
175 return a.tree_ != b.
tree_;
194template <
class Key,
class Value,
class Hasher>
212 reinterpret_cast<uint8_t*
>(
this) +
217 return reinterpret_cast<const FocusedTree* const*
>(
218 reinterpret_cast<const uint8_t*
>(
this) +
223template <
class Key,
class Value,
class Hasher>
226 explicit HashValue(
size_t hash) : bits_(static_cast<uint32_t>(hash)) {}
230 return bits_ & (
static_cast<decltype(bits_)
>(1) << (
kHashBits -
pos - 1))
243 static_assert(
sizeof(uint32_t) * 8 ==
kHashBits,
"wrong type for bits_");
247template <
class Key,
class Value,
class Hasher>
267 if (more_iter_ !=
current_->more->end())
return *
this;
274 while (
current_->key_hash[level_] ==
kRight || path_[level_] ==
nullptr) {
281 const FocusedTree* first_right_alternative = path_[level_];
285 more_iter_ =
current_->more->begin();
287 }
while (!((**this).second != def_value()));
292 if (is_end())
return other.is_end();
293 if (other.is_end())
return false;
294 if (
current_->key_hash != other.current_->key_hash) {
297 return (**this).first == (*other).first;
303 if (is_end())
return false;
304 if (other.is_end())
return true;
305 if (
current_->key_hash == other.current_->key_hash) {
306 return (**this).first < (*other).first;
308 return current_->key_hash < other.current_->key_hash;
319 if (
i.current_->
more) {
320 i.more_iter_ =
i.current_->
more->begin();
324 while (!
i.is_end() && !((*i).second != def_value)) ++
i;
334 std::array<const FocusedTree*, kHashBits>
path_;
341template <
class Key,
class Value,
class Hasher>
345 if (first_current_) {
347 return std::make_tuple(
348 pair.first, pair.second,
349 second_current_ ? (*second_).second : second_.def_value());
352 auto pair = *second_;
353 return std::make_tuple(pair.first, first_.def_value(), pair.second);
362 if (first_current_) {
364 DCHECK(old_first < first_);
366 if (second_current_) {
368 DCHECK(old_second < second_);
374 : first_(first), second_(
second) {
375 if (first_ == second_) {
376 first_current_ = second_current_ =
true;
377 }
else if (first_ < second_) {
378 first_current_ =
true;
379 second_current_ =
false;
382 first_current_ =
false;
383 second_current_ =
true;
388 return first_ != other.first_ || second_ != other.second_;
391 bool is_end()
const {
return first_.is_end() && second_.is_end(); }
400template <
class Key,
class Value,
class Hasher>
402 Modify(
key, [&](
Value* value) { *value = std::move(new_value); });
405template <
class Key,
class Value,
class Hasher>
408 static_assert(std::is_void_v<decltype(f(std::declval<Value*>()))>);
410 std::array<const FocusedTree*, kHashBits> path;
412 const FocusedTree* old = FindHash(key_hash, &path, &length);
414 const Value& old_value = GetFocusedValue(old,
key);
415 Value new_value = old_value;
418 if (old && !(old->more ==
nullptr && old->key_value.key() ==
key)) {
423 more->erase(old->key_value.key());
424 more->emplace(old->key_value.key(), old->key_value.value());
427 more->emplace(
key, new_value);
430 std::max(0, length - 1) *
sizeof(
const FocusedTree*);
433 static_cast<int8_t
>(
length),
438 tree->path(
i) = path[
i];
443template <
class Key,
class Value,
class Hasher>
448 while (tree && hash != tree->key_hash) {
449 while ((hash ^ tree->key_hash)[level] == 0) {
452 tree = level < tree->length ? tree->path(level) :
nullptr;
458template <
class Key,
class Value,
class Hasher>
461 HashValue hash, std::array<const FocusedTree*, kHashBits>* path,
465 while (tree && hash != tree->key_hash) {
466 int map_length = tree->length;
467 while ((hash ^ tree->key_hash)[level] == 0) {
468 (*path)[level] = level < map_length ? tree->path(level) :
nullptr;
471 (*path)[level] = tree;
472 tree = level < tree->length ? tree->path(level) :
nullptr;
476 while (level < tree->length) {
477 (*path)[level] = tree->path(level);
485template <
class Key,
class Value,
class Hasher>
492 auto it = tree->more->find(
key);
493 if (it == tree->more->end())
498 if (
key == tree->key_value.key()) {
499 return tree->key_value.value();
506template <
class Key,
class Value,
class Hasher>
510 if (tree->key_hash[level] == bit) {
512 }
else if (level < tree->length) {
513 return tree->path(level);
519template <
class Key,
class Value,
class Hasher>
523 std::array<const FocusedTree*, kHashBits>* path) {
525 while (*level < current->length) {
527 (*path)[*level] = GetChild(current, *level,
kRight);
528 current = left_child;
531 GetChild(current, *level,
kRight)) {
532 (*path)[*level] = GetChild(current, *level,
kLeft);
533 current = right_child;
542template <
class Key,
class Value,
class Hasher>
547 for (
auto pair : map) {
548 if (!first) os <<
", ";
550 os << pair.first <<
": " << pair.second;
bool operator==(HashValue other) const
bool operator!=(HashValue other) const
Bit operator[](int pos) const
HashValue operator^(HashValue other) const
bool operator<(HashValue other) const
double_iterator & operator++()
std::tuple< Key, Value, Value > operator*()
double_iterator(iterator first, iterator second)
bool operator!=(const double_iterator &other)
bool operator<(const iterator &other) const
static iterator end(Value def_value)
const Value & def_value()
iterator(Value def_value)
FocusedTree::more_iterator more_iter_
static iterator begin(const FocusedTree *tree, Value def_value)
bool operator!=(const iterator &other) const
std::array< const FocusedTree *, kHashBits > path_
bool operator==(const iterator &other) const
const FocusedTree * current_
const value_type operator*() const
size_t last_depth() const
std::pair< Key, Value > value_type
const Value & Get(const Key &key) const
void Modify(Key key, F f)
static const FocusedTree * GetChild(const FocusedTree *tree, int level, Bit bit)
const FocusedTree * tree_
const Value & GetFocusedValue(const FocusedTree *tree, const Key &key) const
PersistentMap(Zone *zone, Value def_value=Value())
static const FocusedTree * FindLeftmost(const FocusedTree *start, int *level, std::array< const FocusedTree *, kHashBits > *path)
void Set(Key key, Value value)
PersistentMap(const FocusedTree *tree, Zone *zone, Value def_value)
const FocusedTree * FindHash(HashValue hash) const
const FocusedTree * FindHash(HashValue hash, std::array< const FocusedTree *, kHashBits > *path, int *length) const
ZipIterable Zip(const PersistentMap &other) const
static constexpr size_t kHashBits
bool operator==(const PersistentMap &other) const
bool operator!=(const PersistentMap &other) const
std::ostream & operator<<(std::ostream &os, AccessMode access_mode)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
const FocusedTree *& path(int i)
const FocusedTree * path(int i) const
typename ZoneMap< Key, Value >::const_iterator more_iterator
const ZoneMap< Key, Value > * more
const Value & value() const
bool operator()(const PersistentMap< Key, Value, Hasher > &a, const PersistentMap< Key, Value, Hasher > &b)
bool operator()(const T &a, const T &b)