5 #ifndef V8_COMPILER_PERSISTENT_MAP_H_ 6 #define V8_COMPILER_PERSISTENT_MAP_H_ 11 #include "src/base/functional.h" 12 #include "src/zone/zone-containers.h" 34 template <
class Key,
class Value,
class Hasher = base::hash<Key>>
39 using value_type = std::pair<Key, Value>;
42 static constexpr
size_t kHashBits = 32;
43 enum Bit :
int { kLeft = 0, kRight = 1 };
50 struct KeyValue : std::pair<Key, Value> {
51 const Key& key()
const {
return this->first; }
52 const Value& value()
const {
return this->second; }
53 using std::pair<Key, Value>::pair;
61 size_t last_depth()
const {
69 const Value& Get(
const Key& key)
const {
72 return GetFocusedValue(tree, key);
79 if (tree_ == other.tree_)
return true;
80 if (def_value_ != other.def_value_)
return false;
81 for (
const std::tuple<Key, Value, Value>& triple : Zip(other)) {
82 if (std::get<1>(triple) != std::get<2>(triple))
return false;
88 return !(*
this == other);
97 if (!tree_)
return end();
98 return iterator::begin(tree_, def_value_);
100 iterator end()
const {
return iterator::end(def_value_); }
118 : PersistentMap(nullptr, zone, def_value) {}
122 const FocusedTree* FindHash(HashValue hash)
const;
129 const FocusedTree* FindHash(HashValue hash,
130 std::array<const FocusedTree*, kHashBits>* path,
134 const Value& GetFocusedValue(
const FocusedTree* tree,
const Key& key)
const;
139 static const FocusedTree* GetChild(
const FocusedTree* tree,
int level,
145 static const FocusedTree* FindLeftmost(
146 const FocusedTree* start,
int* level,
147 std::array<const FocusedTree*, kHashBits>* path);
149 PersistentMap(
const FocusedTree* tree, Zone* zone,
Value def_value)
150 : tree_(tree), def_value_(def_value), zone_(zone) {}
152 const FocusedTree* tree_;
172 template <
class Key,
class Value,
class Hasher>
190 reinterpret_cast<byte*
>(
this) + offsetof(
FocusedTree, path_array))[
i];
194 return reinterpret_cast<const FocusedTree* const*
>(
195 reinterpret_cast<const byte*
>(
this) +
200 template <
class Key,
class Value,
class Hasher>
203 explicit HashValue(
size_t hash) : bits_(static_cast<uint32_t>(hash)) {}
205 Bit operator[](
int pos)
const {
206 DCHECK_LT(pos, kHashBits);
207 return bits_ & (
static_cast<decltype(bits_)
>(1) << (kHashBits - pos - 1))
212 bool operator<(
HashValue other)
const {
return bits_ < other.bits_; }
213 bool operator==(
HashValue other)
const {
return bits_ == other.bits_; }
214 bool operator!=(
HashValue other)
const {
return bits_ != other.bits_; }
220 static_assert(
sizeof(
uint32_t) * 8 == kHashBits,
"wrong type for bits_");
224 template <
class Key,
class Value,
class Hasher>
227 const value_type operator*()
const {
228 if (current_->more) {
231 return current_->key_value;
241 if (current_->more) {
242 DCHECK(more_iter_ != current_->more->end());
244 if (more_iter_ != current_->more->end())
return *
this;
247 *
this = end(def_value_);
251 while (current_->key_hash[level_] == kRight || path_[level_] ==
nullptr) {
253 *
this = end(def_value_);
258 const FocusedTree* first_right_alternative = path_[level_];
260 current_ = FindLeftmost(first_right_alternative, &level_, &path_);
261 if (current_->more) {
262 more_iter_ = current_->more->begin();
264 }
while (!((**this).second != def_value()));
268 bool operator==(
const iterator& other)
const {
269 if (is_end())
return other.is_end();
270 if (other.is_end())
return false;
271 if (current_->key_hash != other.current_->key_hash) {
274 return (**this).first == (*other).first;
277 bool operator!=(
const iterator& other)
const {
return !(*
this == other); }
279 bool operator<(
const iterator& other)
const {
280 if (is_end())
return false;
281 if (other.is_end())
return true;
282 if (current_->key_hash == other.current_->key_hash) {
283 return (**this).first < (*other).first;
285 return current_->key_hash < other.current_->key_hash;
289 bool is_end()
const {
return current_ ==
nullptr; }
291 const Value& def_value() {
return def_value_; }
295 i.current_ = FindLeftmost(tree, &
i.level_, &
i.path_);
296 if (
i.current_->more) {
297 i.more_iter_ =
i.current_->more->begin();
301 while (!
i.is_end() && !((*i).second != def_value)) ++
i;
309 typename FocusedTree::more_iterator more_iter_;
311 std::array<const FocusedTree*, kHashBits> path_;
315 : level_(0), current_(
nullptr), def_value_(def_value) {}
318 template <
class Key,
class Value,
class Hasher>
321 std::tuple<Key, Value, Value> operator*() {
322 if (first_current_) {
324 return std::make_tuple(
325 pair.first, pair.second,
326 second_current_ ? (*second_).second : second_.def_value());
328 DCHECK(second_current_);
329 auto pair = *second_;
330 return std::make_tuple(pair.first, first_.def_value(), pair.second);
339 if (first_current_) {
341 DCHECK(old_first < first_);
343 if (second_current_) {
345 DCHECK(old_second < second_);
351 : first_(first), second_(second) {
352 if (first_ == second_) {
353 first_current_ = second_current_ =
true;
354 }
else if (first_ < second_) {
355 first_current_ =
true;
356 second_current_ =
false;
358 DCHECK(second_ < first_);
359 first_current_ =
false;
360 second_current_ =
true;
365 return first_ != other.first_ || second_ != other.second_;
368 bool is_end()
const {
return first_.is_end() && second_.is_end(); }
374 bool second_current_;
377 template <
class Key,
class Value,
class Hasher>
380 std::array<const FocusedTree*, kHashBits> path;
382 const FocusedTree* old = FindHash(key_hash, &path, &length);
384 if (!(GetFocusedValue(old, key) != value))
return;
385 if (old && !(old->more ==
nullptr && old->key_value.key() == key)) {
390 (*more)[old->key_value.key()] = old->key_value.value();
392 (*more)[key] = value;
395 new (zone_->New(
sizeof(FocusedTree) +
396 std::max(0, length - 1) *
sizeof(
const FocusedTree*)))
397 FocusedTree{KeyValue(std::move(key), std::move(value)),
398 static_cast<int8_t
>(length),
402 for (
int i = 0;
i < length; ++
i) {
403 tree->path(
i) = path[
i];
405 *
this = PersistentMap(tree, zone_, def_value_);
408 template <
class Key,
class Value,
class Hasher>
409 const typename PersistentMap<Key, Value, Hasher>::FocusedTree*
410 PersistentMap<Key, Value, Hasher>::FindHash(HashValue hash)
const {
411 const FocusedTree* tree = tree_;
413 while (tree && hash != tree->key_hash) {
414 while ((hash ^ tree->key_hash)[level] == 0) {
417 tree = level < tree->length ? tree->path(level) :
nullptr;
423 template <
class Key,
class Value,
class Hasher>
424 const typename PersistentMap<Key, Value, Hasher>::FocusedTree*
425 PersistentMap<Key, Value, Hasher>::FindHash(
426 HashValue hash, std::array<const FocusedTree*, kHashBits>* path,
428 const FocusedTree* tree = tree_;
430 while (tree && hash != tree->key_hash) {
431 int map_length = tree->length;
432 while ((hash ^ tree->key_hash)[level] == 0) {
433 (*path)[level] = level < map_length ? tree->path(level) :
nullptr;
436 (*path)[level] = tree;
437 tree = level < tree->length ? tree->path(level) :
nullptr;
441 while (level < tree->length) {
442 (*path)[level] = tree->path(level);
450 template <
class Key,
class Value,
class Hasher>
451 const Value& PersistentMap<Key, Value, Hasher>::GetFocusedValue(
452 const FocusedTree* tree,
const Key& key)
const {
457 auto it = tree->more->find(key);
458 if (it == tree->more->end())
463 if (key == tree->key_value.key()) {
464 return tree->key_value.value();
471 template <
class Key,
class Value,
class Hasher>
472 const typename PersistentMap<Key, Value, Hasher>::FocusedTree*
473 PersistentMap<Key, Value, Hasher>::GetChild(
const FocusedTree* tree,
int level,
475 if (tree->key_hash[level] == bit) {
477 }
else if (level < tree->length) {
478 return tree->path(level);
484 template <
class Key,
class Value,
class Hasher>
485 const typename PersistentMap<Key, Value, Hasher>::FocusedTree*
486 PersistentMap<Key, Value, Hasher>::FindLeftmost(
487 const FocusedTree* start,
int* level,
488 std::array<const FocusedTree*, kHashBits>* path) {
489 const FocusedTree* current = start;
490 while (*level < current->length) {
491 if (
const FocusedTree* child = GetChild(current, *level, kLeft)) {
492 (*path)[*level] = GetChild(current, *level, kRight);
495 }
else if (
const FocusedTree* child = GetChild(current, *level, kRight)) {
496 (*path)[*level] = GetChild(current, *level, kLeft);
506 template <
class Key,
class Value,
class Hasher>
507 std::ostream& operator<<(std::ostream& os,
508 const PersistentMap<Key, Value, Hasher>& map) {
511 for (
auto pair : map) {
512 if (!first) os <<
", ";
514 os << pair.first <<
": " << pair.second;
523 #endif // V8_COMPILER_PERSISTENT_MAP_H_