5#ifndef RUNTIME_VM_HASH_TABLE_H_
6#define RUNTIME_VM_HASH_TABLE_H_
18 static constexpr intptr_t
ArrayCid = kArrayCid;
39 return array->
At(index);
50 static constexpr intptr_t
ArrayCid = kWeakArrayCid;
73 return array->
At(index);
168template <
typename KeyTraits,
169 intptr_t kPayloadSize,
170 intptr_t kMetaDataSize,
171 typename StorageTraits = ArrayStorageTraits>
190 data_(&StorageTraits::PtrToHandle(
data)),
195 typename StorageTraits::ArrayHandle&
Release() {
245 template <
typename Key>
251 template <
typename Key>
258 intptr_t probe =
hash & (num_entries - 1);
259 int probe_distance = 1;
274 probe = (probe + probe_distance) & (num_entries - 1);
285 template <
typename Key>
292 intptr_t probe =
hash & (num_entries - 1);
293 int probe_distance = 1;
294 intptr_t deleted = -1;
297 *entry = (deleted != -1) ? deleted : probe;
315 probe = (probe + probe_distance) & (num_entries - 1);
361 ASSERT(0 <= component && component < kPayloadSize);
367 for (intptr_t
i = 0;
i < kPayloadSize; ++
i) {
398 if (KeyTraits::ReportStats()) {
403 if (KeyTraits::ReportStats()) {
404 if (Storage::IsImmutable(*
data_)) {
408 if (collisions < 5) {
410 }
else if (collisions < 25) {
418 if (!KeyTraits::ReportStats()) {
426 " Size of table = %" Pd ",Number of Occupied entries = %" Pd "\n"
427 " Number of Grows = %" Pd "\n"
428 " Number of lookups with < 5 collisions = %" Pd "\n"
429 " Number of lookups with < 25 collisions = %" Pd "\n"
430 " Number of lookups with > 25 collisions = %" Pd "\n"
431 " Average number of probes = %g\n",
434 num5, num25, num_more,
435 static_cast<double>(
NumProbes()) / (num5 + num25 + num_more));
441 if (StorageTraits::ArrayCid != kWeakArrayCid)
return;
446 intptr_t num_occupied = 0;
447 intptr_t num_deleted = 0;
483 ASSERT(0 <= component && component < kPayloadSize);
484 return KeyIndex(entry) + 1 + component;
498 if (StorageTraits::At(
data_, index)->IsHeapObject()) {
501 ASSERT(!StorageTraits::At(
data_, index)->IsHeapObject());
517 typename StorageTraits::ArrayHandle*
data_;
521 template <
typename Table,
bool kAllCanonicalObjectsAreIncludedIntoSet>
523 template <
typename Table,
525 typename PointerType,
526 bool kAllCanonicalObjectsAreIncludedIntoSet>
531template <
typename KeyTraits,
532 intptr_t kUserPayloadSize,
535 :
public HashTable<KeyTraits, kUserPayloadSize, 0, StorageTraits> {
550 : table_(
table), entry_(-1) {}
573 template <
typename Table>
574 static typename Table::Storage::ArrayPtr
New(intptr_t initial_capacity,
580 zone, Table::ArrayLengthForNumOccupied(initial_capacity), space));
582 return table.Release().ptr();
585 template <
typename Table>
586 static typename Table::Storage::ArrayPtr
New(
587 const typename Table::Storage::ArrayHandle& array) {
590 return table.Release().ptr();
595 template <
typename From,
typename To>
596 static void Copy(
const From& from,
const To& to) {
599 ASSERT(from.NumOccupied() < to.NumEntries());
600 typename From::Iterator it(&from);
602 while (it.MoveNext()) {
603 intptr_t from_entry = it.Current();
604 obj = from.GetKey(from_entry);
605 intptr_t to_entry = -1;
607 bool present = to.FindKeyOrDeletedOrUnused(
key, &to_entry);
609 to.InsertKey(to_entry, obj);
610 for (intptr_t
i = 0;
i < From::kPayloadSize; ++
i) {
611 obj = from.GetPayload(from_entry,
i);
612 to.UpdatePayload(to_entry,
i, obj);
619 template <
typename Table>
623 const double current = (1 +
table.NumOccupied() +
table.NumDeleted()) /
624 static_cast<double>(
table.NumEntries());
625 const bool too_many_deleted =
table.NumOccupied() <=
table.NumDeleted();
626 if (current < high && !too_many_deleted) {
630 table.UpdateWeakDeleted();
640 const intptr_t new_capacity =
table.NumOccupied() * 2 + 1;
642 ((1.0 +
table.NumOccupied()) /
644 Table new_table(New<Table>(new_capacity,
647 Table::Storage::SetHandle(*
table.data_, new_table.Release());
652 template <
typename Table>
654 const intptr_t entry_size = include_payload ? (1 + Table::kPayloadSize) : 1;
656 typename Table::Iterator it(&
table);
658 intptr_t result_index = 0;
659 while (it.MoveNext()) {
660 intptr_t entry = it.Current();
661 obj =
table.GetKey(entry);
662 result.SetAt(result_index++, obj);
663 if (include_payload) {
664 for (intptr_t
i = 0;
i < Table::kPayloadSize; ++
i) {
665 obj =
table.GetPayload(entry,
i);
666 result.SetAt(result_index++, obj);
673#if defined(DART_PRECOMPILER)
676 if (!
table.IsNull()) {
678 for (intptr_t
i = 0;
i <
table.Length();
i++) {
680 if (!element.IsSmi()) {
691template <
typename BaseIterTable>
695 : BaseIterTable(
Thread::Current()->zone(),
data) {}
699 template <
typename Key>
701 intptr_t entry = BaseIterTable::FindKey(
key);
702 if (present !=
nullptr) {
703 *present = (entry != -1);
705 return (entry == -1) ?
Object::null() : BaseIterTable::GetPayload(entry, 0);
707 template <
typename Key>
709 intptr_t entry = BaseIterTable::FindKey(
key);
711 return BaseIterTable::GetPayload(entry, 0);
716 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(
key, &entry);
718 BaseIterTable::InsertKey(entry,
key);
720 BaseIterTable::UpdatePayload(entry, 0,
value);
724 template <
typename Key>
726 intptr_t entry = BaseIterTable::FindKey(
key);
728 BaseIterTable::UpdatePayload(entry, 0,
value);
733 const Object& value_if_absent)
const {
736 if (!BaseIterTable::FindKeyOrDeletedOrUnused(
key, &entry)) {
737 BaseIterTable::InsertKey(entry,
key);
738 BaseIterTable::UpdatePayload(entry, 0, value_if_absent);
739 return value_if_absent.
ptr();
741 return BaseIterTable::GetPayload(entry, 0);
745 template <
typename Key>
747 const Object& value_if_absent)
const {
750 if (!BaseIterTable::FindKeyOrDeletedOrUnused(
key, &entry)) {
751 BaseIterTable::KeyHandle() =
752 BaseIterTable::BaseTable::Traits::NewKey(
key);
753 BaseIterTable::InsertKey(entry, BaseIterTable::KeyHandle());
754 BaseIterTable::UpdatePayload(entry, 0, value_if_absent);
755 return value_if_absent.
ptr();
757 return BaseIterTable::GetPayload(entry, 0);
761 template <
typename Key>
763 intptr_t entry = BaseIterTable::FindKey(
key);
767 BaseIterTable::DeleteEntry(entry);
780template <
typename KeyTraits>
791template <
typename BaseIterTable,
typename StorageTraits>
797 : BaseIterTable(
Thread::Current()->zone(),
data) {}
804 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(
key, &entry);
806 BaseIterTable::InsertKey(entry,
key);
816 if (!BaseIterTable::FindKeyOrDeletedOrUnused(
key, &entry)) {
817 BaseIterTable::InsertKey(entry,
key);
820 return BaseIterTable::GetKey(entry);
825 template <
typename Key>
829 if (!BaseIterTable::FindKeyOrDeletedOrUnused(
key, &entry)) {
830 BaseIterTable::KeyHandle() =
831 BaseIterTable::BaseTable::Traits::NewKey(
key);
832 BaseIterTable::InsertKey(entry, BaseIterTable::KeyHandle());
833 return BaseIterTable::KeyHandle().ptr();
835 return BaseIterTable::GetKey(entry);
839 template <
typename Key>
841 intptr_t entry = BaseIterTable::FindKey(
key);
842 if (present !=
nullptr) {
843 *present = (entry != -1);
845 return (entry == -1) ?
Object::null() : BaseIterTable::GetKey(entry);
848 template <
typename Key>
850 intptr_t entry = BaseIterTable::FindKey(
key);
854 BaseIterTable::DeleteEntry(entry);
867template <
typename KeyTraits,
typename TableStorageTraits = ArrayStorageTraits>
869 :
public HashSet<UnorderedHashTable<KeyTraits, 0, TableStorageTraits>,
870 TableStorageTraits> {
875 typedef typename TableStorageTraits::ArrayPtr
ArrayPtr;
887 for (intptr_t
i = 0;
i < this->
data_->Length();
i++) {
889 TableStorageTraits::At(this->
data_,
i));
890 if (entry.
ptr() == BaseSet::UnusedMarker().ptr() ||
891 entry.
ptr() == BaseSet::DeletedMarker().ptr() || entry.IsSmi()) {
static uint32_t hash(const SkShaderBase::GradientInfo &v)
ObjectPtr AtAcquire(intptr_t index) const
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
void SetAtRelease(intptr_t index, const Object &value) const
ObjectPtr At(intptr_t index) const
void SetAt(intptr_t index, const Object &value) const
HashMap(Zone *zone, ArrayPtr data)
ObjectPtr GetOrNull(const Key &key, bool *present=nullptr) const
ObjectPtr GetOrDie(const Key &key) const
ObjectPtr InsertNewOrGetValue(const Key &key, const Object &value_if_absent) const
ObjectPtr InsertOrGetValue(const Object &key, const Object &value_if_absent) const
bool UpdateOrInsert(const Object &key, const Object &value) const
bool Remove(const Key &key) const
void EnsureCapacity() const
HashMap(Object *key, Smi *value, Array *data)
void UpdateValue(const Key &key, const Object &value) const
StorageTraits::ArrayHandle ArrayHandle
bool Remove(const Key &key) const
HashSet(Object *key, Smi *value, ArrayHandle *data)
bool Insert(const Object &key)
HashSet(Zone *zone, ArrayPtr data)
void EnsureCapacity() const
ObjectPtr GetOrNull(const Key &key, bool *present=nullptr) const
ObjectPtr InsertOrGet(const Object &key) const
ObjectPtr InsertNewOrGet(const Key &key) const
StorageTraits::ArrayPtr ArrayPtr
static const Object & DeletedMarker()
static const Object & UnusedMarker()
bool IsOccupied(intptr_t entry) const
Object & KeyHandle() const
static intptr_t ArrayLengthForNumOccupied(intptr_t num_occupied)
intptr_t NumDeleted() const
intptr_t NumLT5Collisions() const
static constexpr intptr_t kMetaDataIndex
intptr_t NumLT25Collisions() const
bool IsUnused(intptr_t entry) const
bool ContainsKey(const Key &key) const
void AdjustSmiValueAt(intptr_t index, intptr_t delta) const
static constexpr intptr_t kEntrySize
ObjectPtr GetPayload(intptr_t entry, intptr_t component) const
StorageTraits::ArrayHandle & Release()
void UpdateGrowth() const
static constexpr intptr_t kNumGT25LookupsIndex
static constexpr intptr_t kNumLT25LookupsIndex
HashTable(Object *key, Smi *index, typename StorageTraits::ArrayHandle *data)
intptr_t GetSmiValueAt(intptr_t index) const
intptr_t NumOccupied() const
static constexpr intptr_t kHeaderSize
bool FindKeyOrDeletedOrUnused(const Key &key, intptr_t *entry) const
intptr_t NumGrows() const
static constexpr intptr_t kFirstKeyIndex
intptr_t FindKey(const Key &key) const
static constexpr intptr_t kOccupiedEntriesIndex
void InsertKey(intptr_t entry, const Object &key) const
StorageTraits::ArrayHandle * data_
bool IsDeleted(intptr_t entry) const
static constexpr intptr_t kNumGrowsIndex
intptr_t NumUnused() const
HashTable(Zone *zone, typename StorageTraits::ArrayPtr data)
ObjectPtr InternalGetKey(intptr_t entry) const
void UpdateWeakDeleted() const
intptr_t NumEntries() const
intptr_t PayloadIndex(intptr_t entry, intptr_t component) const
intptr_t NumGT25Collisions() const
void SetSmiValueAt(intptr_t index, intptr_t value) const
void UpdateCollisions(intptr_t collisions) const
void InternalSetKey(intptr_t entry, const Object &key) const
StorageTraits::ArrayHandle * released_data_
ObjectPtr GetKey(intptr_t entry) const
void DeleteEntry(intptr_t entry) const
intptr_t KeyIndex(intptr_t entry) const
void UpdatePayload(intptr_t entry, intptr_t component, const Object &value) const
static constexpr intptr_t kNumLT5LookupsIndex
static constexpr intptr_t kDeletedEntriesIndex
intptr_t NumProbes() const
static constexpr intptr_t kNumProbesIndex
static constexpr double kMaxLoadFactor
static ArrayPtr ToArray(const Table &table, bool include_payload)
static Table::Storage::ArrayPtr New(const typename Table::Storage::ArrayHandle &array)
static void EnsureLoadFactor(double high, const Table &table)
static Table::Storage::ArrayPtr New(intptr_t initial_capacity, Heap::Space space=Heap::kNew)
static void Copy(const From &from, const To &to)
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
UntaggedObject * untag() const
virtual const char * ToCString() const
static ObjectPtr RawCast(ObjectPtr obj)
static SmiPtr New(intptr_t value)
static Thread * Current()
UnorderedHashMap(Object *key, Smi *value, Array *data)
UnorderedHashMap(ArrayPtr data)
HashMap< UnorderedHashTable< KeyTraits, 1 > > BaseMap
UnorderedHashMap(Zone *zone, ArrayPtr data)
UnorderedHashSet(ArrayPtr data)
TableStorageTraits::ArrayHandle ArrayHandle
UnorderedHashSet(Object *key, Smi *value, ArrayHandle *data)
HashSet< UnderlyingTable, TableStorageTraits > BaseSet
TableStorageTraits::ArrayPtr ArrayPtr
UnorderedHashSet(Zone *zone, ArrayPtr data)
Iterator(const UnorderedHashTable *table)
UnorderedHashTable(Object *key, Smi *value, ArrayHandle *data)
StorageTraits::ArrayHandle ArrayHandle
HashTable< KeyTraits, kUserPayloadSize, 0, StorageTraits > BaseTable
StorageTraits::ArrayPtr ArrayPtr
static constexpr intptr_t kPayloadSize
UnorderedHashTable(ArrayPtr data)
UnorderedHashTable(Zone *zone, ArrayPtr data)
bool InVMIsolateHeap() const
static constexpr uintptr_t RoundUpToPowerOfTwo(uintptr_t x)
static constexpr bool IsPowerOfTwo(T x)
void SetAt(intptr_t index, const Object &value) const
ObjectPtr AtAcquire(intptr_t index) const
ObjectPtr At(intptr_t index) const
static WeakArrayPtr New(intptr_t length, Heap::Space space=Heap::kNew)
void SetAtRelease(intptr_t index, const Object &value) const
static ObjectPtr Unwrap(ObjectPtr obj)
static ObjectPtr New(const Object &target, const Object &replacement)
UnorderedHashMap< SmiTraits > IntHashMap
static uint32_t Hash(uint32_t key)
static int8_t data[kExtLength]
NOT_IN_PRODUCT(LibraryPtr ReloadTestScript(const char *script))
COMPILE_ASSERT(kUnreachableReference==WeakTable::kNoValue)
void Initialize(zx::channel directory_request, std::optional< zx::eventpair > view_ref)
Initializes Dart bindings for the Fuchsia application model.
SK_API sk_sp< PrecompileColorFilter > Table()
static void SetAt(ArrayHandle *array, intptr_t index, const Object &value)
static ObjectPtr At(ArrayHandle *array, intptr_t index)
static void SetAt(ArrayHandle *array, intptr_t index, const Object &value)
static ArrayPtr New(Zone *zone, intptr_t length, Heap::Space space)
static void ClearHandle(ArrayHandle &handle)
static bool IsImmutable(const ArrayHandle &handle)
static ArrayHandle & PtrToHandle(ArrayPtr ptr)
static constexpr intptr_t ArrayCid
static void SetHandle(ArrayHandle &dst, const ArrayHandle &src)
static ObjectPtr At(ArrayHandle *array, intptr_t index)
static void SetAt(ArrayHandle *array, intptr_t index, const Object &value)
static ObjectPtr At(ArrayHandle *array, intptr_t index)
static ArrayPtr New(Zone *zone, intptr_t length, Heap::Space space)
static void SetHandle(ArrayHandle &dst, const ArrayHandle &src)
static void ClearHandle(ArrayHandle &handle)
static bool IsImmutable(const ArrayHandle &handle)
static ArrayHandle & PtrToHandle(ArrayPtr ptr)
dart::WeakArrayPtr ArrayPtr
static constexpr intptr_t ArrayCid
static ObjectPtr At(ArrayHandle *array, intptr_t index)
static void SetAt(ArrayHandle *array, intptr_t index, const Object &value)