45 template <
typename IsolateT,
typename StringTableKey>
49 if (string->hash() !=
key->hash())
return false;
50 if (string->length() !=
key->length())
return false;
51 return key->IsMatch(isolate,
string);
85 static std::unique_ptr<Data>
New(
int capacity);
87 std::unique_ptr<Data> data,
int capacity);
89 void*
operator new(
size_t size,
int capacity);
90 void*
operator new(
size_t size) =
delete;
91 void operator delete(
void* description);
97 template <
typename Char>
120void* StringTable::Data::operator
new(
size_t size,
int capacity) {
123 return OffHeapStringHashSet::Allocate<
Data, offsetof(
Data,
table_.elements_)>(
127void StringTable::Data::operator
delete(
void* table) {
128 OffHeapStringHashSet::Free(table);
140 return std::unique_ptr<Data>(
new (capacity)
Data(capacity));
145 std::unique_ptr<Data> new_data(
new (capacity)
Data(capacity));
146 data->table_.RehashInto(cage_base, &new_data->table_);
147 new_data->previous_data_ = std::move(data);
153 os <<
"StringTable {" << std::endl;
155 os <<
" " <<
i.as_uint32() <<
": " <<
Brief(
table_.GetKey(cage_base,
i))
158 os <<
"}" << std::endl;
171 return data_.load(std::memory_order_acquire)->table().capacity();
176 return data_.load(std::memory_order_relaxed)->table().number_of_elements();
189 !IsInternalizedString(*
string));
196 return string_->SlowEquals(
string);
201 isolate->factory()->ComputeInternalizationStrategyForString(
227 const bool can_avoid_copy =
264 string_->set_map_safe_transition_no_write_barrier(isolate,
294 DCHECK(!IsThinString(
string));
295 DCHECK(!IsInternalizedString(
string));
296 DCHECK(IsInternalizedString(internalized));
298 if (string->IsShared() ||
v8_flags.always_use_string_forwarding_table) {
313 const int forwarding_index =
315 isolate->string_forwarding_table()->UpdateForwardString(forwarding_index,
321 const int forwarding_index =
322 isolate->string_forwarding_table()->AddForwardString(
string,
324 string->set_raw_hash_field(
330 string->MakeThin(isolate, internalized);
368 if (!IsInternalizedString(*
result)) {
375 isolate->string_forwarding_table()->GetForwardString(isolate, index),
379 raw_hash_field =
result->EnsureRawHash();
385 if (*
string != *
result && !IsThinString(*
string)) {
386 SetInternalizedReference(isolate, *
string, *
result);
391template <
typename StringTableKey,
typename IsolateT>
430 Data*
const current_data =
data_.load(std::memory_order_acquire);
448 key->PrepareForInsertion(isolate);
457 entry = table.FindEntryOrInsertionEntry(isolate,
key,
key->hash());
465 table.AddAt(isolate, entry, *new_string);
472 table.OverwriteDeletedAt(isolate, entry, *new_string);
501 int additional_elements) {
507 Data* data =
data_.load(std::memory_order_relaxed);
510 if (data->table().ShouldResizeToAdd(additional_elements, &new_capacity)) {
511 std::unique_ptr<Data> new_data =
512 Data::Resize(cage_base, std::unique_ptr<Data>(data), new_capacity);
514 DCHECK_EQ(new_data->PreviousData(), data);
518 data = new_data.release();
519 data_.store(data, std::memory_order_release);
526template <
typename Char>
529 void Reset(
size_t length) {
531 outofline_ = std::make_unique<Char[]>(length);
549template <
typename Char>
559 uint32_t length =
string->length();
563 const bool is_source_hash_usable =
start == 0 && length == source->length();
566 uint32_t raw_hash_field = source->raw_hash_field(
kAcquireLoad);
568 is_source_hash_usable) {
571 isolate->string_forwarding_table()->GetForwardString(isolate, index);
572 return internalized.
ptr();
577 CharBuffer<Char> buffer;
581 if (IsConsString(source, isolate)) {
582 DCHECK(!source->IsFlat());
583 buffer.Reset(length);
585 chars = buffer.Data();
587 chars = source->GetDirectStringChars<Char>(no_gc, access_guard) +
start;
609 Data* string_table_data =
610 isolate->string_table()->data_.load(std::memory_order_acquire);
626 if (!IsInternalizedString(
string)) {
627 SetInternalizedReference(isolate,
string, internalized);
631 return internalized.
ptr();
638 if (IsInternalizedString(
string)) {
654 if (IsSlicedString(source)) {
656 start = sliced->offset();
657 source = sliced->parent();
658 }
else if (IsConsString(source) && source->IsFlat()) {
661 if (IsThinString(source)) {
663 if (string->length() == source->length()) {
668 if (source->IsOneByteRepresentation()) {
670 isolate,
string, source,
start);
673 isolate,
string, source,
start);
680 const int length =
static_cast<int>(strings.size());
690 data->table().FindEntryOrInsertionEntry(isolate, &
key,
key.hash());
694 data->table().AddAt(isolate, entry, *inserted_string);
709 uint32_t hash = empty_string->EnsureHash();
711 InternalIndex entry = data->table().FindInsertionEntry(isolate, hash);
714 data->table().AddAt(isolate, entry, *empty_string);
720 data_.load(std::memory_order_acquire)->Print(cage_base);
724 return sizeof(*this) +
725 data_.load(std::memory_order_acquire)->GetCurrentMemoryUsage();
732 data_.load(std::memory_order_relaxed)->IterateElements(visitor);
740 data_.load(std::memory_order_relaxed)->DropPreviousData();
748 data_.load(std::memory_order_relaxed)->table().ElementsRemoved(
count);
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
static constexpr T decode(U value)
static constexpr bool is_valid(T value)
static V8_NODISCARD constexpr U update(U previous, T value)
V8_INLINE void AssertHeld() const
Tagged< Object > Acquire_Load() const
void Release_Store(Tagged< Object > value) const
static V8_INLINE bool InAnySharedSpace(Tagged< HeapObject > object)
HeapState gc_state() const
IsolateSafepoint * safepoint()
bool is_not_found() const
void PrepareForInsertion(Isolate *isolate)
MaybeDirectHandle< String > internalized_string_
InternalizedStringKey(DirectHandle< String > string, uint32_t hash)
DirectHandle< String > string_
DirectHandle< String > GetHandleForInsertion(Isolate *isolate)
bool IsMatch(Isolate *isolate, Tagged< String > string)
MaybeDirectHandle< Map > maybe_internalized_map_
static bool IsIntegerIndex(uint32_t raw_hash_field)
static bool IsForwardingIndex(uint32_t raw_hash_field)
static bool ContainsCachedArrayIndex(uint32_t hash)
static uint32_t CreateInternalizedForwardingIndex(uint32_t index)
static bool IsInternalizedForwardingIndex(uint32_t raw_hash_field)
static bool IsHashFieldComputed(uint32_t raw_hash_field)
InternalIndex FindEntry(IsolateT *isolate, FindKey key, uint32_t hash) const
static constexpr Tagged< Smi > deleted_element()
size_t GetSizeExcludingHeader() const
void IterateElements(Root root, RootVisitor *visitor)
OffHeapObjectSlot slot(InternalIndex index, int offset=0) const
static constexpr Tagged< Smi > empty_element()
static bool IsNeeded(Tagged< String > str, LocalIsolate *local_isolate)
static constexpr Tagged< Smi > FromInt(int value)
static uint32_t HashSequentialString(const char_t *chars, uint32_t length, uint64_t seed)
V8_INLINE bool IsShared() const
V8_INLINE bool IsExternalOneByte() const
V8_INLINE bool IsExternalTwoByte() const
V8_INLINE bool IsUncachedExternal() const
uint32_t raw_hash_field() const
static std::unique_ptr< Data > Resize(PtrComprCageBase cage_base, std::unique_ptr< Data > data, int capacity)
OffHeapStringHashSet & table()
static std::unique_ptr< Data > New(int capacity)
static Address TryStringToIndexOrLookupExisting(Isolate *isolate, Tagged< String > string, Tagged< String > source, size_t start)
const OffHeapStringHashSet & table() const
void IterateElements(RootVisitor *visitor)
void Print(PtrComprCageBase cage_base) const
OffHeapStringHashSet table_
size_t GetCurrentMemoryUsage() const
std::unique_ptr< Data > previous_data_
void CopyEntryExcludingKeyInto(PtrComprCageBase, InternalIndex, OffHeapStringHashSet *, InternalIndex)
void SetKey(InternalIndex index, Tagged< Object > key)
void Set(InternalIndex index, Tagged< String > key)
static bool KeyIsMatch(IsolateT *isolate, StringTableKey *key, Tagged< Object > obj)
static uint32_t Hash(PtrComprCageBase, Tagged< Object > key)
Tagged< Object > GetKey(PtrComprCageBase cage_base, InternalIndex index) const
static constexpr int kMinCapacity
static constexpr int kEntrySize
static constexpr int kMaxEmptyFactor
OffHeapStringHashSet(int capacity)
static Address TryStringToIndexOrLookupExisting(Isolate *isolate, Address raw_string)
void InsertForIsolateDeserialization(Isolate *isolate, const base::Vector< DirectHandle< String > > &strings)
void IterateElements(RootVisitor *visitor)
DirectHandle< String > LookupString(Isolate *isolate, DirectHandle< String > key)
void InsertEmptyStringForBootstrapping(Isolate *isolate)
Data * EnsureCapacity(PtrComprCageBase cage_base, int additional_elements)
size_t GetCurrentMemoryUsage() const
StringTable(Isolate *isolate)
static constexpr Tagged< Smi > empty_element()
void NotifyElementsRemoved(int count)
DirectHandle< String > LookupKey(IsolateT *isolate, StringTableKey *key)
static constexpr Tagged< Smi > deleted_element()
void Print(PtrComprCageBase cage_base) const
std::atomic< Data * > data_
int NumberOfElements() const
static void WriteToFlat(Tagged< String > source, SinkCharT *sink, uint32_t start, uint32_t length)
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
V8_INLINE constexpr StorageType ptr() const
ZoneVector< RpoNumber > & result
@ kNotDeserializingUserCode
V8_INLINE IndirectHandle< T > indirect_handle(DirectHandle< T > handle)
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
V8_EXPORT_PRIVATE FlagValues v8_flags
uint64_t HashSeed(Isolate *isolate)
template const char * string
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
static constexpr ReleaseStoreTag kReleaseStore
static constexpr AcquireLoadTag kAcquireLoad
SourcePositionTable *const table_
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
std::unique_ptr< Char[]> outofline_
static constexpr size_t kInlinedBufferSize
Char inlined_[kInlinedBufferSize]