Lines Matching +full:- +full:threadsafe
2 // Use of this source code is governed by a BSD-style license that can be
5 #include "src/objects/string-table.h"
11 #include "src/common/assert-scope.h"
13 #include "src/common/ptr-compr-inl.h"
14 #include "src/execution/isolate-utils-inl.h"
16 #include "src/objects/internal-index.h"
17 #include "src/objects/object-list-macros.h"
18 #include "src/objects/slots-inl.h"
20 #include "src/objects/string-inl.h"
21 #include "src/objects/string-table-inl.h"
42 ((number_of_deleted_elements <= (capacity - nof) / 2))) { in StringTableHasSufficientCapacityToAdd()
74 if (string.hash() != key->hash()) return false; in KeyIsMatch()
75 if (string.length() != key->length()) return false; in KeyIsMatch()
76 return key->IsMatch(isolate, string); in KeyIsMatch()
88 // The elements themselves are stored as an open-addressed hash table, with
119 capacity(), number_of_elements(), number_of_deleted_elements() - 1, 1)); in DeletedElementOverwritten()
122 number_of_deleted_elements_--; in DeletedElementOverwritten()
126 number_of_elements_ -= count; in ElementsRemoved()
169 return InternalIndex(hash & (size - 1)); in FirstProbe()
174 return InternalIndex((last.as_uint32() + number) & (size - 1)); in NextProbe()
191 sizeof(StringTable::Data) - sizeof(Tagged_t)); in operator new()
200 return AlignedAlloc(size + (capacity - 1) * sizeof(Tagged_t), in operator new()
207 size_t usage = sizeof(*this) + (capacity_ - 1) * sizeof(Tagged_t); in GetCurrentMemoryUsage()
209 usage += previous_data_->GetCurrentMemoryUsage(); in GetCurrentMemoryUsage()
231 DCHECK_LT(data->number_of_elements(), new_data->capacity()); in Resize()
233 new_data->capacity(), new_data->number_of_elements(), in Resize()
234 new_data->number_of_deleted_elements(), data->number_of_elements())); in Resize()
237 for (InternalIndex i : InternalIndex::Range(data->capacity())) { in Resize()
238 Object element = data->Get(cage_base, i); in Resize()
243 new_data->FindInsertionEntry(cage_base, hash); in Resize()
244 new_data->Set(insertion_index, string); in Resize()
246 new_data->number_of_elements_ = data->number_of_elements(); in Resize()
248 new_data->previous_data_ = std::move(data); in Resize()
316 visitor->VisitRootPointers(Root::kStringTable, nullptr, first_slot, end_slot); in IterateElements()
335 return data_.load(std::memory_order_acquire)->capacity(); in Capacity()
340 return data_.load(std::memory_order_relaxed)->number_of_elements(); in NumberOfElements()
344 // InternalizedStringKey carries a string/internalized-string object as key.
348 : StringTableKey(0, string->length()), string_(string) { in InternalizedStringKey()
352 DCHECK_IMPLIES(!FLAG_shared_string_table, !string->IsInternalizedString()); in InternalizedStringKey()
353 DCHECK(string->IsFlat()); in InternalizedStringKey()
355 string->EnsureHash(); in InternalizedStringKey()
356 set_raw_hash_field(string->raw_hash_field()); in InternalizedStringKey()
361 return string_->SlowEquals(string); in IsMatch()
366 isolate->factory()->ComputeInternalizationStrategyForString( in PrepareForInsertion()
372 // In-place transition will be done in GetHandleForInsertion, when we in PrepareForInsertion()
382 // Copying the string here is always threadsafe, as no instance type in PrepareForInsertion()
391 isolate->factory()->InternalizeExternalString<ExternalOneByteString>( in PrepareForInsertion()
397 isolate->factory()->InternalizeExternalString<ExternalTwoByteString>( in PrepareForInsertion()
401 string_ = isolate->factory()->NewInternalizedStringImpl( in PrepareForInsertion()
402 string_, string_->length(), string_->raw_hash_field()); in PrepareForInsertion()
408 // When preparing the string, the strategy was to in-place migrate it. in GetHandleForInsertion()
414 string_->set_map_no_write_barrier(*internalized_map); in GetHandleForInsertion()
415 DCHECK(string_->IsInternalizedString()); in GetHandleForInsertion()
422 // in-place migrate the original string instead of internalizing the copy in GetHandleForInsertion()
424 // seem to be common enough to justify re-computing the strategy here. in GetHandleForInsertion()
438 // - All in-place internalizable strings (i.e. old-generation flat strings) in LookupString()
440 // - LookupKey supports concurrent access (see comment below). in LookupString()
444 // - String::Flatten is not threadsafe but is only called on non-shared in LookupString()
445 // strings, since non-flat strings are not shared. in LookupString()
447 // - String::ComputeAndSetHash is threadsafe on flat strings. This is safe in LookupString()
452 // - In-place internalizable strings do not incur a copy regardless of string in LookupString()
453 // table sharing. The map mutation is threadsafe even with relaxed memory in LookupString()
456 // during the re-lookup. in LookupString()
461 // For lookup hits, String::MakeThin is threadsafe and spinlocks on in LookupString()
465 if (string->IsInternalizedString()) return string; in LookupString()
470 if (!string->IsInternalizedString()) { in LookupString()
471 string->MakeThin(isolate, *result); in LookupString()
481 // - The Heap access is allowed to be concurrent (using LocalHeap or in LookupKey()
483 // - All writes to the string table are guarded by the Isolate string table in LookupKey()
485 // - Resizes of the string table first copies the old contents to the new in LookupKey()
488 // - Only GCs can remove elements from the string table. in LookupKey()
504 // read lookup in case the non-locked read missed a write. in LookupKey()
506 // One complication is allocation -- we don't want to allocate while holding in LookupKey()
508 // re-allocation of the string table on resize. So, we optimistically allocate in LookupKey()
522 InternalIndex entry = current_data->FindEntry(isolate, key, key->hash()); in LookupKey()
524 Handle<String> result(String::cast(current_data->Get(isolate, entry)), in LookupKey()
526 DCHECK_IMPLIES(FLAG_shared_string_table, result->InSharedHeap()); in LookupKey()
531 key->PrepareForInsertion(isolate); in LookupKey()
539 entry = data->FindEntryOrInsertionEntry(isolate, key, key->hash()); in LookupKey()
541 Object element = data->Get(isolate, entry); in LookupKey()
545 Handle<String> new_string = key->GetHandleForInsertion(); in LookupKey()
546 DCHECK_IMPLIES(FLAG_shared_string_table, new_string->IsShared()); in LookupKey()
547 data->Set(entry, *new_string); in LookupKey()
548 data->ElementAdded(); in LookupKey()
553 Handle<String> new_string = key->GetHandleForInsertion(); in LookupKey()
554 DCHECK_IMPLIES(FLAG_shared_string_table, new_string->IsShared()); in LookupKey()
555 data->Set(entry, *new_string); in LookupKey()
556 data->DeletedElementOverwritten(); in LookupKey()
596 int current_capacity = data->capacity(); in EnsureCapacity()
597 int current_nof = data->number_of_elements(); in EnsureCapacity()
601 int new_capacity = -1; in EnsureCapacity()
608 data->number_of_deleted_elements(), 1)) { in EnsureCapacity()
612 if (new_capacity != -1) { in EnsureCapacity()
616 DCHECK_EQ(new_data->PreviousData(), data); in EnsureCapacity()
617 // Release-store the new data pointer as `data_`, so that it can be in EnsureCapacity()
618 // acquire-loaded by other threads. This string table becomes the owner of in EnsureCapacity()
654 // TODO(verwaest): Internalize to one-byte when possible. in TryStringToIndexOrLookupExisting()
671 isolate->string_table()->data_.load(std::memory_order_acquire); in TryStringToIndexOrLookupExisting()
673 InternalIndex entry = string_table_data->FindEntry(isolate, &key, key.hash()); in TryStringToIndexOrLookupExisting()
680 String internalized = String::cast(string_table_data->Get(isolate, entry)); in TryStringToIndexOrLookupExisting()
736 data_.load(std::memory_order_acquire)->Print(cage_base); in Print()
741 data_.load(std::memory_order_acquire)->GetCurrentMemoryUsage(); in GetCurrentMemoryUsage()
747 isolate_->heap()->safepoint()->AssertActive(); in IterateElements()
748 data_.load(std::memory_order_relaxed)->IterateElements(visitor); in IterateElements()
754 isolate_->heap()->safepoint()->AssertActive(); in DropOldData()
755 DCHECK_NE(isolate_->heap()->gc_state(), Heap::NOT_IN_GC); in DropOldData()
756 data_.load(std::memory_order_relaxed)->DropPreviousData(); in DropOldData()
762 isolate_->heap()->safepoint()->AssertActive(); in NotifyElementsRemoved()
763 DCHECK_NE(isolate_->heap()->gc_state(), Heap::NOT_IN_GC); in NotifyElementsRemoved()
764 data_.load(std::memory_order_relaxed)->ElementsRemoved(count); in NotifyElementsRemoved()
768 DCHECK_EQ(isolate->string_table(), this); in UpdateCountersIfOwnedBy()
769 if (!isolate->OwnsStringTable()) return; in UpdateCountersIfOwnedBy()
770 isolate->counters()->string_table_capacity()->Set(Capacity()); in UpdateCountersIfOwnedBy()
771 isolate->counters()->number_of_symbols()->Set(NumberOfElements()); in UpdateCountersIfOwnedBy()