v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
off-heap-hash-table.h
Go to the documentation of this file.
1// Copyright 2023 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_OBJECTS_OFF_HEAP_HASH_TABLE_H_
6#define V8_OBJECTS_OFF_HEAP_HASH_TABLE_H_
7
11#include "src/objects/slots.h"
12#include "src/objects/smi.h"
14#include "src/roots/roots.h"
15
16// Has to be the last include (doesn't have include guards):
18
19namespace v8 {
20namespace internal {
21
22// A base class for building off-heap hash tables (e.g. the string table) that
23// stores tagged values.
24//
25// It is a variable sized structure, with a "header" followed directly in memory
26// by the elements themselves. These are accessed as offsets from the elements_
27// field, which itself provides storage for the first element.
28//
29// The elements themselves are stored as an open-addressed hash table, with
30// quadratic probing and Smi 0 and Smi 1 as the empty and deleted sentinels,
31// respectively.
32//
33// It is a CRTP class whose derived class must provide the following
34// definitions:
35//
36// // The number of elements per table entry.
37// static constexpr int kEntrySize;
38//
39// // The factor by which to decide if the table ought to shrink.
40// static constexpr int kMaxEmptyFactor;
41//
42// // The minimum number of elements for new tables.
43// static constexpr int kMinCapacity;
44//
45// // Computes the hash of a key {obj}.
46// static uint32_t Hash(Tagged<Object> obj);
47//
48// // Returns whether the lookup key {key} matches the key element {obj}.
49// template <typename IsolateT, typename Key>
50// static bool KeyIsMatch(IsolateT* isolate, Key key, Tagged<Object> obj);
51//
52// // Load the key object at entry {index}, decompressing it if needed.
53// Tagged<Object> GetKey(PtrComprCageBase, InternalIndex index);
54//
55// // Store the key object at the entry {index}.
56// void SetKey(InternalIndex index, Tagged<Object> key);
57//
58// // Store an entire entry at {index}. The arity of this function must be
59// // kEntrySize + 1.
60// void Set(InternalIndex index, Tagged<Object>...);
61//
62// // Copy an entry in this table at {from_index} into the entry in {to} at
63// // {to_index}, exclusive of the key.
64// void CopyEntryExcludingKeyInto(PtrComprCageBase, InternalIndex from_index,
65// Derived* to, InternalIndex to_index);
66//
67template <typename Derived>
69 public:
70 static constexpr Tagged<Smi> empty_element() { return Smi::FromInt(0); }
71 static constexpr Tagged<Smi> deleted_element() { return Smi::FromInt(1); }
72
73 static bool IsKey(Tagged<Object> k) {
74 return k != empty_element() && k != deleted_element();
75 }
76
77 int capacity() const { return capacity_; }
80
82 DCHECK_LT(offset, Derived::kEntrySize);
83 return OffHeapObjectSlot(
84 &elements_[index.as_uint32() * Derived::kEntrySize + offset]);
85 }
86
87 template <typename... Args>
88 void AddAt(PtrComprCageBase cage_base, InternalIndex entry, Args&&... args) {
89 Derived* derived_this = static_cast<Derived*>(this);
90
91 DCHECK_EQ(derived_this->GetKey(cage_base, entry), empty_element());
94
95 derived_this->Set(entry, std::forward<Args>(args)...);
97 }
98
99 template <typename... Args>
101 Args&&... args) {
102 Derived* derived_this = static_cast<Derived*>(this);
103
104 DCHECK_EQ(derived_this->GetKey(cage_base, entry), deleted_element());
108
109 derived_this->Set(entry, std::forward<Args>(args)...);
112 }
113
119
120 size_t GetSizeExcludingHeader() const {
122 }
123
124 template <typename IsolateT, typename FindKey>
125 inline InternalIndex FindEntry(IsolateT* isolate, FindKey key,
126 uint32_t hash) const;
127
129 uint32_t hash) const;
130
131 template <typename IsolateT, typename FindKey>
132 inline InternalIndex FindEntryOrInsertionEntry(IsolateT* isolate, FindKey key,
133 uint32_t hash) const;
134
135 inline bool ShouldResizeToAdd(int number_of_additional_elements,
136 int* new_capacity);
137
138 inline void RehashInto(PtrComprCageBase cage_base, Derived* new_table);
139
140 inline void IterateElements(Root root, RootVisitor* visitor);
141
142 protected:
143 explicit OffHeapHashTableBase(int capacity);
144
145 // Returns probe entry.
146 static inline InternalIndex FirstProbe(uint32_t hash, uint32_t size) {
147 return InternalIndex(hash & (size - 1));
148 }
149
150 static inline InternalIndex NextProbe(InternalIndex last, uint32_t number,
151 uint32_t size) {
152 return InternalIndex((last.as_uint32() + number) & (size - 1));
153 }
154
155 bool HasSufficientCapacityToAdd(int number_of_additional_elements) const {
158 number_of_additional_elements);
159 }
160 static inline bool HasSufficientCapacityToAdd(
161 int capacity, int number_of_elements, int number_of_deleted_elements,
162 int number_of_additional_elements);
163 static inline int ComputeCapacity(int at_least_space_for);
164 static inline int ComputeCapacityWithShrink(int current_capacity,
165 int at_least_space_for);
166
167 static inline size_t GetSizeExcludingHeader(int capacity) {
168 // Subtract sizeof(Tagged_t) from the result, as the member elements_
169 // already supplies the storage for the first element.
170 return (capacity * sizeof(Tagged_t) * Derived::kEntrySize) -
171 sizeof(Tagged_t);
172 }
173
174 // Returns memory to hold a Derived, which may be inline inside Container. The
175 // offset of the elements_ field relative to Container must be passed for
176 // static layout checks.
177 template <typename Container, size_t OffsetOfElementsInContainer>
178 static inline void* Allocate(int capacity);
179
180 static inline void Free(void* container);
181
184 const int capacity_;
186};
187
188} // namespace internal
189} // namespace v8
190
192
193#endif // V8_OBJECTS_OFF_HEAP_HASH_TABLE_H_
InternalIndex FindEntryOrInsertionEntry(IsolateT *isolate, FindKey key, uint32_t hash) const
InternalIndex FindEntry(IsolateT *isolate, FindKey key, uint32_t hash) const
static size_t GetSizeExcludingHeader(int capacity)
void RehashInto(PtrComprCageBase cage_base, Derived *new_table)
static constexpr Tagged< Smi > deleted_element()
bool HasSufficientCapacityToAdd(int number_of_additional_elements) const
void AddAt(PtrComprCageBase cage_base, InternalIndex entry, Args &&... args)
void OverwriteDeletedAt(PtrComprCageBase cage_base, InternalIndex entry, Args &&... args)
bool ShouldResizeToAdd(int number_of_additional_elements, int *new_capacity)
void IterateElements(Root root, RootVisitor *visitor)
static int ComputeCapacity(int at_least_space_for)
static InternalIndex FirstProbe(uint32_t hash, uint32_t size)
static int ComputeCapacityWithShrink(int current_capacity, int at_least_space_for)
static InternalIndex NextProbe(InternalIndex last, uint32_t number, uint32_t size)
OffHeapObjectSlot slot(InternalIndex index, int offset=0) const
static bool IsKey(Tagged< Object > k)
static constexpr Tagged< Smi > empty_element()
InternalIndex FindInsertionEntry(PtrComprCageBase cage_base, uint32_t hash) const
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
uint32_t count
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
int32_t offset
Address Tagged_t
Definition globals.h:547
SlotTraits::TOffHeapObjectSlot OffHeapObjectSlot
Definition globals.h:1258
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485