Update Dictionary classes to use InternalIndex
for "entries", i.e. indices into the backing store (as opposed to "public indices" going into the hash function). This improves consistency and compiler-enforced type safety; no change in behavior is intended. Change-Id: I25e57e3ddcf18a406e2dfbd66786b6980c4e9615 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1852768 Commit-Queue: Jakob Kummerow <jkummerow@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#64317}
This commit is contained in:
parent
38301e7bb9
commit
0b9f10532a
@ -300,8 +300,8 @@ MaybeHandle<JSObject> ProbeInstantiationsCache(
|
||||
(serial_number <= TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
|
||||
SimpleNumberDictionary slow_cache =
|
||||
native_context->slow_template_instantiations_cache();
|
||||
int entry = slow_cache.FindEntry(isolate, serial_number);
|
||||
if (entry != SimpleNumberDictionary::kNotFound) {
|
||||
InternalIndex entry = slow_cache.FindEntry(isolate, serial_number);
|
||||
if (entry.is_found()) {
|
||||
return handle(JSObject::cast(slow_cache.ValueAt(entry)), isolate);
|
||||
}
|
||||
}
|
||||
@ -348,8 +348,8 @@ void UncacheTemplateInstantiation(Isolate* isolate,
|
||||
TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
|
||||
Handle<SimpleNumberDictionary> cache =
|
||||
handle(native_context->slow_template_instantiations_cache(), isolate);
|
||||
int entry = cache->FindEntry(isolate, serial_number);
|
||||
DCHECK_NE(SimpleNumberDictionary::kNotFound, entry);
|
||||
InternalIndex entry = cache->FindEntry(isolate, serial_number);
|
||||
DCHECK(entry.is_found());
|
||||
cache = SimpleNumberDictionary::DeleteEntry(isolate, cache, entry);
|
||||
native_context->set_slow_template_instantiations_cache(*cache);
|
||||
}
|
||||
|
@ -6442,8 +6442,8 @@ Local<v8::Object> v8::Object::New(Isolate* isolate,
|
||||
} else {
|
||||
// Internalize the {name} first.
|
||||
name = i_isolate->factory()->InternalizeName(name);
|
||||
int const entry = properties->FindEntry(i_isolate, name);
|
||||
if (entry == i::NameDictionary::kNotFound) {
|
||||
i::InternalIndex const entry = properties->FindEntry(i_isolate, name);
|
||||
if (entry.is_not_found()) {
|
||||
// Add the {name}/{value} pair as a new entry.
|
||||
properties = i::NameDictionary::Add(i_isolate, properties, name, value,
|
||||
i::PropertyDetails::Empty());
|
||||
|
@ -853,9 +853,8 @@ uint32_t EstimateElementCount(Isolate* isolate, Handle<JSArray> array) {
|
||||
}
|
||||
case DICTIONARY_ELEMENTS: {
|
||||
NumberDictionary dictionary = NumberDictionary::cast(array->elements());
|
||||
int capacity = dictionary.Capacity();
|
||||
ReadOnlyRoots roots(isolate);
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary.IterateEntries()) {
|
||||
Object key = dictionary.KeyAt(i);
|
||||
if (dictionary.IsKey(roots, key)) {
|
||||
element_count++;
|
||||
@ -930,7 +929,7 @@ void CollectElementIndices(Isolate* isolate, Handle<JSObject> object,
|
||||
uint32_t capacity = dict.Capacity();
|
||||
ReadOnlyRoots roots(isolate);
|
||||
FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, {
|
||||
Object k = dict.KeyAt(j);
|
||||
Object k = dict.KeyAt(InternalIndex(j));
|
||||
if (!dict.IsKey(roots, k)) continue;
|
||||
DCHECK(k.IsNumber());
|
||||
uint32_t index = static_cast<uint32_t>(k.Number());
|
||||
|
@ -1350,7 +1350,7 @@ Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) {
|
||||
int capacity =
|
||||
NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity);
|
||||
DCHECK(base::bits::IsPowerOfTwo(capacity));
|
||||
int length = NameDictionary::EntryToIndex(capacity);
|
||||
int length = NameDictionary::EntryToIndex(InternalIndex(capacity));
|
||||
int size = NameDictionary::SizeFor(length);
|
||||
|
||||
AllocationBuilder a(jsgraph(), effect, control);
|
||||
|
@ -1986,8 +1986,7 @@ void MapData::SerializeOwnDescriptors(JSHeapBroker* broker) {
|
||||
TraceScope tracer(broker, this, "MapData::SerializeOwnDescriptors");
|
||||
Handle<Map> map = Handle<Map>::cast(object());
|
||||
|
||||
int const number_of_own = map->NumberOfOwnDescriptors();
|
||||
for (InternalIndex i : InternalIndex::Range(number_of_own)) {
|
||||
for (InternalIndex i : map->IterateOwnDescriptors()) {
|
||||
SerializeOwnDescriptor(broker, i);
|
||||
}
|
||||
}
|
||||
|
@ -477,8 +477,7 @@ bool JSObject::PrintProperties(std::ostream& os) { // NOLINT
|
||||
if (HasFastProperties()) {
|
||||
DescriptorArray descs = map().instance_descriptors();
|
||||
int nof_inobject_properties = map().GetInObjectProperties();
|
||||
for (InternalIndex i :
|
||||
InternalIndex::Range(map().NumberOfOwnDescriptors())) {
|
||||
for (InternalIndex i : map().IterateOwnDescriptors()) {
|
||||
os << "\n ";
|
||||
descs.GetKey(i).NamePrint(os);
|
||||
os << ": ";
|
||||
@ -926,9 +925,9 @@ void PrintHashTableWithHeader(std::ostream& os, T table, const char* type) {
|
||||
os << "\n - capacity: " << table.Capacity();
|
||||
|
||||
os << "\n - elements: {";
|
||||
for (int i = 0; i < table.Capacity(); i++) {
|
||||
for (InternalIndex i : table.IterateEntries()) {
|
||||
os << '\n'
|
||||
<< std::setw(12) << i << ": " << Brief(table.KeyAt(i)) << " -> "
|
||||
<< std::setw(12) << i.as_int() << ": " << Brief(table.KeyAt(i)) << " -> "
|
||||
<< Brief(table.ValueAt(i));
|
||||
}
|
||||
os << "\n }\n";
|
||||
|
@ -543,8 +543,8 @@ class StackFrameCacheHelper : public AllStatic {
|
||||
return MaybeHandle<StackTraceFrame>();
|
||||
|
||||
const auto cache = Handle<SimpleNumberDictionary>::cast(maybe_cache);
|
||||
const int entry = cache->FindEntry(isolate, code_offset);
|
||||
if (entry != NumberDictionary::kNotFound) {
|
||||
const InternalIndex entry = cache->FindEntry(isolate, code_offset);
|
||||
if (entry.is_found()) {
|
||||
return handle(StackTraceFrame::cast(cache->ValueAt(entry)), isolate);
|
||||
}
|
||||
return MaybeHandle<StackTraceFrame>();
|
||||
@ -3865,9 +3865,9 @@ Handle<Symbol> Isolate::SymbolFor(RootIndex dictionary_index,
|
||||
Handle<String> key = factory()->InternalizeString(name);
|
||||
Handle<NameDictionary> dictionary =
|
||||
Handle<NameDictionary>::cast(root_handle(dictionary_index));
|
||||
int entry = dictionary->FindEntry(this, key);
|
||||
InternalIndex entry = dictionary->FindEntry(this, key);
|
||||
Handle<Symbol> symbol;
|
||||
if (entry == NameDictionary::kNotFound) {
|
||||
if (entry.is_not_found()) {
|
||||
symbol =
|
||||
private_symbol ? factory()->NewPrivateSymbol() : factory()->NewSymbol();
|
||||
symbol->set_name(*key);
|
||||
|
@ -479,7 +479,7 @@ class ConcurrentMarkingVisitor final
|
||||
if (!ShouldVisit(table)) return 0;
|
||||
weak_objects_->ephemeron_hash_tables.Push(task_id_, table);
|
||||
|
||||
for (int i = 0; i < table.Capacity(); i++) {
|
||||
for (InternalIndex i : table.IterateEntries()) {
|
||||
ObjectSlot key_slot =
|
||||
table.RawFieldOfElementAt(EphemeronHashTable::EntryToIndex(i));
|
||||
HeapObject key = HeapObject::cast(table.KeyAt(i));
|
||||
|
@ -2770,7 +2770,7 @@ Handle<JSGlobalObject> Factory::NewJSGlobalObject(
|
||||
// The global object might be created from an object template with accessors.
|
||||
// Fill these accessors into the dictionary.
|
||||
Handle<DescriptorArray> descs(map->instance_descriptors(), isolate());
|
||||
for (InternalIndex i : InternalIndex::Range(map->NumberOfOwnDescriptors())) {
|
||||
for (InternalIndex i : map->IterateOwnDescriptors()) {
|
||||
PropertyDetails details = descs->GetDetails(i);
|
||||
// Only accessors are expected.
|
||||
DCHECK_EQ(kAccessor, details.kind());
|
||||
|
@ -4086,8 +4086,8 @@ class OldToNewSlotVerifyingVisitor : public SlotVerifyingVisitor {
|
||||
CHECK(it != ephemeron_remembered_set_->end());
|
||||
int slot_index =
|
||||
EphemeronHashTable::SlotToIndex(table.address(), key.address());
|
||||
int entry = EphemeronHashTable::IndexToEntry(slot_index);
|
||||
CHECK(it->second.find(entry) != it->second.end());
|
||||
InternalIndex entry = EphemeronHashTable::IndexToEntry(slot_index);
|
||||
CHECK(it->second.find(entry.as_int()) != it->second.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6184,10 +6184,10 @@ void Heap::GenerationalBarrierSlow(HeapObject object, Address slot,
|
||||
void Heap::RecordEphemeronKeyWrite(EphemeronHashTable table, Address slot) {
|
||||
DCHECK(ObjectInYoungGeneration(HeapObjectSlot(slot).ToHeapObject()));
|
||||
int slot_index = EphemeronHashTable::SlotToIndex(table.address(), slot);
|
||||
int entry = EphemeronHashTable::IndexToEntry(slot_index);
|
||||
InternalIndex entry = EphemeronHashTable::IndexToEntry(slot_index);
|
||||
auto it =
|
||||
ephemeron_remembered_set_.insert({table, std::unordered_set<int>()});
|
||||
it.first->second.insert(entry);
|
||||
it.first->second.insert(entry.as_int());
|
||||
}
|
||||
|
||||
void Heap::EphemeronKeyWriteBarrierFromCode(Address raw_object,
|
||||
|
@ -167,7 +167,7 @@ int MarkingVisitor<fixed_array_mode, retaining_path_mode, MarkingState>::
|
||||
VisitEphemeronHashTable(Map map, EphemeronHashTable table) {
|
||||
collector_->AddEphemeronHashTable(table);
|
||||
|
||||
for (int i = 0; i < table.Capacity(); i++) {
|
||||
for (InternalIndex i : table.IterateEntries()) {
|
||||
ObjectSlot key_slot =
|
||||
table.RawFieldOfElementAt(EphemeronHashTable::EntryToIndex(i));
|
||||
HeapObject key = HeapObject::cast(table.KeyAt(i));
|
||||
|
@ -2297,7 +2297,7 @@ void MarkCompactCollector::ClearWeakCollections() {
|
||||
EphemeronHashTable table;
|
||||
|
||||
while (weak_objects_.ephemeron_hash_tables.Pop(kMainThread, &table)) {
|
||||
for (int i = 0; i < table.Capacity(); i++) {
|
||||
for (InternalIndex i : table.IterateEntries()) {
|
||||
HeapObject key = HeapObject::cast(table.KeyAt(i));
|
||||
#ifdef VERIFY_HEAP
|
||||
Object value = table.ValueAt(i);
|
||||
@ -3654,8 +3654,8 @@ class EphemeronTableUpdatingItem : public UpdatingItem {
|
||||
DCHECK(table.Object::IsEphemeronHashTable());
|
||||
for (auto iti = indices.begin(); iti != indices.end();) {
|
||||
// EphemeronHashTable keys must be heap objects.
|
||||
HeapObjectSlot key_slot(
|
||||
table.RawFieldOfElementAt(EphemeronHashTable::EntryToIndex(*iti)));
|
||||
HeapObjectSlot key_slot(table.RawFieldOfElementAt(
|
||||
EphemeronHashTable::EntryToIndex(InternalIndex(*iti))));
|
||||
HeapObject key = key_slot.ToHeapObject();
|
||||
MapWord map_word = key.map_word();
|
||||
if (map_word.IsForwardingAddress()) {
|
||||
|
@ -482,7 +482,7 @@ int ScavengeVisitor::VisitEphemeronHashTable(Map map,
|
||||
// later. This allows to only iterate the tables' values, which are treated
|
||||
// as strong independetly of whether the key is live.
|
||||
scavenger_->AddEphemeronHashTable(table);
|
||||
for (int i = 0; i < table.Capacity(); i++) {
|
||||
for (InternalIndex i : table.IterateEntries()) {
|
||||
ObjectSlot value_slot =
|
||||
table.RawFieldOfElementAt(EphemeronHashTable::EntryToValueIndex(i));
|
||||
VisitPointer(table, value_slot);
|
||||
|
@ -535,7 +535,7 @@ void ScavengerCollector::ProcessWeakReferences(
|
||||
void ScavengerCollector::ClearYoungEphemerons(
|
||||
EphemeronTableList* ephemeron_table_list) {
|
||||
ephemeron_table_list->Iterate([this](EphemeronHashTable table) {
|
||||
for (int i = 0; i < table.Capacity(); i++) {
|
||||
for (InternalIndex i : table.IterateEntries()) {
|
||||
// Keys in EphemeronHashTables must be heap objects.
|
||||
HeapObjectSlot key_slot(
|
||||
table.RawFieldOfElementAt(EphemeronHashTable::EntryToIndex(i)));
|
||||
@ -560,11 +560,11 @@ void ScavengerCollector::ClearOldEphemerons() {
|
||||
auto& indices = it->second;
|
||||
for (auto iti = indices.begin(); iti != indices.end();) {
|
||||
// Keys in EphemeronHashTables must be heap objects.
|
||||
HeapObjectSlot key_slot(
|
||||
table.RawFieldOfElementAt(EphemeronHashTable::EntryToIndex(*iti)));
|
||||
HeapObjectSlot key_slot(table.RawFieldOfElementAt(
|
||||
EphemeronHashTable::EntryToIndex(InternalIndex(*iti))));
|
||||
HeapObject key = key_slot.ToHeapObject();
|
||||
if (IsUnscavengedHeapObject(heap_, key)) {
|
||||
table.RemoveEntry(*iti);
|
||||
table.RemoveEntry(InternalIndex(*iti));
|
||||
iti = indices.erase(iti);
|
||||
} else {
|
||||
HeapObject forwarded = ForwardingAddress(key);
|
||||
|
@ -772,10 +772,10 @@ Handle<Object> LoadIC::ComputeHandler(LookupIterator* lookup) {
|
||||
Handle<ObjectHashTable> exports(
|
||||
Handle<JSModuleNamespace>::cast(holder)->module().exports(),
|
||||
isolate());
|
||||
int entry = exports->FindEntry(roots, lookup->name(),
|
||||
Smi::ToInt(lookup->name()->GetHash()));
|
||||
InternalIndex entry = exports->FindEntry(
|
||||
roots, lookup->name(), Smi::ToInt(lookup->name()->GetHash()));
|
||||
// We found the accessor, so the entry must exist.
|
||||
DCHECK_NE(entry, ObjectHashTable::kNotFound);
|
||||
DCHECK(entry.is_found());
|
||||
int index = ObjectHashTable::EntryToValueIndex(entry);
|
||||
return LoadHandler::LoadModuleExport(isolate(), index);
|
||||
}
|
||||
|
@ -5345,7 +5345,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
|
||||
Handle<FixedArray> indices =
|
||||
GlobalDictionary::IterationIndices(isolate(), properties);
|
||||
for (int i = 0; i < indices->length(); i++) {
|
||||
int index = Smi::ToInt(indices->get(i));
|
||||
InternalIndex index(Smi::ToInt(indices->get(i)));
|
||||
Handle<PropertyCell> cell(properties->CellAt(index), isolate());
|
||||
Handle<Name> key(cell->name(), isolate());
|
||||
// If the property is already there we skip it.
|
||||
@ -5365,7 +5365,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
|
||||
NameDictionary::IterationIndices(isolate(), properties);
|
||||
ReadOnlyRoots roots(isolate());
|
||||
for (int i = 0; i < key_indices->length(); i++) {
|
||||
int key_index = Smi::ToInt(key_indices->get(i));
|
||||
InternalIndex key_index(Smi::ToInt(key_indices->get(i)));
|
||||
Object raw_key = properties->KeyAt(key_index);
|
||||
DCHECK(properties->IsKey(roots, raw_key));
|
||||
DCHECK(raw_key.IsName());
|
||||
|
@ -70,14 +70,15 @@ void NumberDictionary::set_requires_slow_elements() {
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
void Dictionary<Derived, Shape>::ClearEntry(Isolate* isolate, int entry) {
|
||||
void Dictionary<Derived, Shape>::ClearEntry(Isolate* isolate,
|
||||
InternalIndex entry) {
|
||||
Object the_hole = this->GetReadOnlyRoots().the_hole_value();
|
||||
PropertyDetails details = PropertyDetails::Empty();
|
||||
Derived::cast(*this).SetEntry(isolate, entry, the_hole, the_hole, details);
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
void Dictionary<Derived, Shape>::SetEntry(Isolate* isolate, int entry,
|
||||
void Dictionary<Derived, Shape>::SetEntry(Isolate* isolate, InternalIndex entry,
|
||||
Object key, Object value,
|
||||
PropertyDetails details) {
|
||||
DCHECK(Dictionary::kEntrySize == 2 || Dictionary::kEntrySize == 3);
|
||||
@ -98,12 +99,12 @@ RootIndex GlobalDictionaryShape::GetMapRootIndex() {
|
||||
return RootIndex::kGlobalDictionaryMap;
|
||||
}
|
||||
|
||||
Name NameDictionary::NameAt(int entry) {
|
||||
Name NameDictionary::NameAt(InternalIndex entry) {
|
||||
Isolate* isolate = GetIsolateForPtrCompr(*this);
|
||||
return NameAt(isolate, entry);
|
||||
}
|
||||
|
||||
Name NameDictionary::NameAt(Isolate* isolate, int entry) {
|
||||
Name NameDictionary::NameAt(Isolate* isolate, InternalIndex entry) {
|
||||
return Name::cast(KeyAt(isolate, entry));
|
||||
}
|
||||
|
||||
@ -111,12 +112,12 @@ RootIndex NameDictionaryShape::GetMapRootIndex() {
|
||||
return RootIndex::kNameDictionaryMap;
|
||||
}
|
||||
|
||||
PropertyCell GlobalDictionary::CellAt(int entry) {
|
||||
PropertyCell GlobalDictionary::CellAt(InternalIndex entry) {
|
||||
Isolate* isolate = GetIsolateForPtrCompr(*this);
|
||||
return CellAt(isolate, entry);
|
||||
}
|
||||
|
||||
PropertyCell GlobalDictionary::CellAt(Isolate* isolate, int entry) {
|
||||
PropertyCell GlobalDictionary::CellAt(Isolate* isolate, InternalIndex entry) {
|
||||
DCHECK(KeyAt(isolate, entry).IsPropertyCell(isolate));
|
||||
return PropertyCell::cast(KeyAt(isolate, entry));
|
||||
}
|
||||
@ -130,32 +131,33 @@ bool GlobalDictionaryShape::IsKey(ReadOnlyRoots roots, Object k) {
|
||||
return IsLive(roots, k) && !PropertyCell::cast(k).value().IsTheHole(roots);
|
||||
}
|
||||
|
||||
Name GlobalDictionary::NameAt(int entry) {
|
||||
Name GlobalDictionary::NameAt(InternalIndex entry) {
|
||||
Isolate* isolate = GetIsolateForPtrCompr(*this);
|
||||
return NameAt(isolate, entry);
|
||||
}
|
||||
|
||||
Name GlobalDictionary::NameAt(Isolate* isolate, int entry) {
|
||||
Name GlobalDictionary::NameAt(Isolate* isolate, InternalIndex entry) {
|
||||
return CellAt(isolate, entry).name(isolate);
|
||||
}
|
||||
|
||||
Object GlobalDictionary::ValueAt(int entry) {
|
||||
Object GlobalDictionary::ValueAt(InternalIndex entry) {
|
||||
Isolate* isolate = GetIsolateForPtrCompr(*this);
|
||||
return ValueAt(isolate, entry);
|
||||
}
|
||||
|
||||
Object GlobalDictionary::ValueAt(Isolate* isolate, int entry) {
|
||||
Object GlobalDictionary::ValueAt(Isolate* isolate, InternalIndex entry) {
|
||||
return CellAt(isolate, entry).value(isolate);
|
||||
}
|
||||
|
||||
void GlobalDictionary::SetEntry(Isolate* isolate, int entry, Object key,
|
||||
Object value, PropertyDetails details) {
|
||||
void GlobalDictionary::SetEntry(Isolate* isolate, InternalIndex entry,
|
||||
Object key, Object value,
|
||||
PropertyDetails details) {
|
||||
DCHECK_EQ(key, PropertyCell::cast(value).name());
|
||||
set(EntryToIndex(entry) + kEntryKeyIndex, value);
|
||||
DetailsAtPut(isolate, entry, details);
|
||||
}
|
||||
|
||||
void GlobalDictionary::ValueAtPut(int entry, Object value) {
|
||||
void GlobalDictionary::ValueAtPut(InternalIndex entry, Object value) {
|
||||
set(EntryToIndex(entry), value);
|
||||
}
|
||||
|
||||
@ -219,15 +221,17 @@ Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
|
||||
}
|
||||
|
||||
template <typename Dictionary>
|
||||
PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary dict, int entry) {
|
||||
DCHECK_LE(0, entry); // Not found is -1, which is not caught by get().
|
||||
PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary dict,
|
||||
InternalIndex entry) {
|
||||
DCHECK(entry.is_found());
|
||||
return dict.CellAt(entry).property_details();
|
||||
}
|
||||
|
||||
template <typename Dictionary>
|
||||
void GlobalDictionaryShape::DetailsAtPut(Isolate* isolate, Dictionary dict,
|
||||
int entry, PropertyDetails value) {
|
||||
DCHECK_LE(0, entry); // Not found is -1, which is not caught by get().
|
||||
InternalIndex entry,
|
||||
PropertyDetails value) {
|
||||
DCHECK(entry.is_found());
|
||||
PropertyCell cell = dict.CellAt(entry);
|
||||
if (cell.property_details().IsReadOnly() != value.IsReadOnly()) {
|
||||
cell.dependent_code().DeoptimizeDependentCodeGroup(
|
||||
|
@ -31,32 +31,35 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) Dictionary
|
||||
public:
|
||||
using Key = typename Shape::Key;
|
||||
// Returns the value at entry.
|
||||
Object ValueAt(int entry) {
|
||||
Object ValueAt(InternalIndex entry) {
|
||||
Isolate* isolate = GetIsolateForPtrCompr(*this);
|
||||
return ValueAt(isolate, entry);
|
||||
}
|
||||
Object ValueAt(Isolate* isolate, int entry) {
|
||||
return this->get(isolate, DerivedHashTable::EntryToIndex(entry) + 1);
|
||||
Object ValueAt(Isolate* isolate, InternalIndex entry) {
|
||||
return this->get(isolate, DerivedHashTable::EntryToIndex(entry) +
|
||||
Derived::kEntryValueIndex);
|
||||
}
|
||||
|
||||
// Set the value for entry.
|
||||
void ValueAtPut(int entry, Object value) {
|
||||
this->set(DerivedHashTable::EntryToIndex(entry) + 1, value);
|
||||
void ValueAtPut(InternalIndex entry, Object value) {
|
||||
this->set(DerivedHashTable::EntryToIndex(entry) + Derived::kEntryValueIndex,
|
||||
value);
|
||||
}
|
||||
|
||||
// Returns the property details for the property at entry.
|
||||
PropertyDetails DetailsAt(int entry) {
|
||||
PropertyDetails DetailsAt(InternalIndex entry) {
|
||||
return Shape::DetailsAt(Derived::cast(*this), entry);
|
||||
}
|
||||
|
||||
// Set the details for entry.
|
||||
void DetailsAtPut(Isolate* isolate, int entry, PropertyDetails value) {
|
||||
void DetailsAtPut(Isolate* isolate, InternalIndex entry,
|
||||
PropertyDetails value) {
|
||||
Shape::DetailsAtPut(isolate, Derived::cast(*this), entry, value);
|
||||
}
|
||||
|
||||
// Delete a property from the dictionary.
|
||||
V8_WARN_UNUSED_RESULT static Handle<Derived> DeleteEntry(
|
||||
Isolate* isolate, Handle<Derived> dictionary, int entry);
|
||||
Isolate* isolate, Handle<Derived> dictionary, InternalIndex entry);
|
||||
|
||||
// Attempt to shrink the dictionary after deletion of key.
|
||||
V8_WARN_UNUSED_RESULT static inline Handle<Derived> Shrink(
|
||||
@ -76,13 +79,14 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) Dictionary
|
||||
Object SlowReverseLookup(Object value);
|
||||
|
||||
// Sets the entry to (key, value) pair.
|
||||
inline void ClearEntry(Isolate* isolate, int entry);
|
||||
inline void SetEntry(Isolate* isolate, int entry, Object key, Object value,
|
||||
PropertyDetails details);
|
||||
inline void ClearEntry(Isolate* isolate, InternalIndex entry);
|
||||
inline void SetEntry(Isolate* isolate, InternalIndex entry, Object key,
|
||||
Object value, PropertyDetails details);
|
||||
|
||||
V8_WARN_UNUSED_RESULT static Handle<Derived> Add(
|
||||
Isolate* isolate, Handle<Derived> dictionary, Key key,
|
||||
Handle<Object> value, PropertyDetails details, int* entry_out = nullptr);
|
||||
Handle<Object> value, PropertyDetails details,
|
||||
InternalIndex* entry_out = nullptr);
|
||||
|
||||
protected:
|
||||
// Generic at put operation.
|
||||
@ -100,16 +104,17 @@ class BaseDictionaryShape : public BaseShape<Key> {
|
||||
public:
|
||||
static const bool kHasDetails = true;
|
||||
template <typename Dictionary>
|
||||
static inline PropertyDetails DetailsAt(Dictionary dict, int entry) {
|
||||
static inline PropertyDetails DetailsAt(Dictionary dict,
|
||||
InternalIndex entry) {
|
||||
STATIC_ASSERT(Dictionary::kEntrySize == 3);
|
||||
DCHECK_GE(entry, 0); // Not found is -1, which is not caught by get().
|
||||
DCHECK(entry.is_found());
|
||||
return PropertyDetails(Smi::cast(dict.get(Dictionary::EntryToIndex(entry) +
|
||||
Dictionary::kEntryDetailsIndex)));
|
||||
}
|
||||
|
||||
template <typename Dictionary>
|
||||
static inline void DetailsAtPut(Isolate* isolate, Dictionary dict, int entry,
|
||||
PropertyDetails value) {
|
||||
static inline void DetailsAtPut(Isolate* isolate, Dictionary dict,
|
||||
InternalIndex entry, PropertyDetails value) {
|
||||
STATIC_ASSERT(Dictionary::kEntrySize == 3);
|
||||
dict.set(Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex,
|
||||
value.AsSmi());
|
||||
@ -190,11 +195,13 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) BaseNameDictionary
|
||||
|
||||
V8_WARN_UNUSED_RESULT static Handle<Derived> AddNoUpdateNextEnumerationIndex(
|
||||
Isolate* isolate, Handle<Derived> dictionary, Key key,
|
||||
Handle<Object> value, PropertyDetails details, int* entry_out = nullptr);
|
||||
Handle<Object> value, PropertyDetails details,
|
||||
InternalIndex* entry_out = nullptr);
|
||||
|
||||
V8_WARN_UNUSED_RESULT static Handle<Derived> Add(
|
||||
Isolate* isolate, Handle<Derived> dictionary, Key key,
|
||||
Handle<Object> value, PropertyDetails details, int* entry_out = nullptr);
|
||||
Handle<Object> value, PropertyDetails details,
|
||||
InternalIndex* entry_out = nullptr);
|
||||
|
||||
OBJECT_CONSTRUCTORS(BaseNameDictionary, Dictionary<Derived, Shape>);
|
||||
};
|
||||
@ -209,11 +216,12 @@ class V8_EXPORT_PRIVATE NameDictionary
|
||||
public:
|
||||
DECL_CAST(NameDictionary)
|
||||
|
||||
static const int kEntryValueIndex = 1;
|
||||
static const int kEntryDetailsIndex = 2;
|
||||
static const int kInitialCapacity = 2;
|
||||
|
||||
inline Name NameAt(int entry);
|
||||
inline Name NameAt(Isolate* isolate, int entry);
|
||||
inline Name NameAt(InternalIndex entry);
|
||||
inline Name NameAt(Isolate* isolate, InternalIndex entry);
|
||||
|
||||
inline void set_hash(int hash);
|
||||
inline int hash() const;
|
||||
@ -230,11 +238,11 @@ class GlobalDictionaryShape : public NameDictionaryShape {
|
||||
static const int kEntrySize = 1; // Overrides NameDictionaryShape::kEntrySize
|
||||
|
||||
template <typename Dictionary>
|
||||
static inline PropertyDetails DetailsAt(Dictionary dict, int entry);
|
||||
static inline PropertyDetails DetailsAt(Dictionary dict, InternalIndex entry);
|
||||
|
||||
template <typename Dictionary>
|
||||
static inline void DetailsAtPut(Isolate* isolate, Dictionary dict, int entry,
|
||||
PropertyDetails value);
|
||||
static inline void DetailsAtPut(Isolate* isolate, Dictionary dict,
|
||||
InternalIndex entry, PropertyDetails value);
|
||||
|
||||
static inline Object Unwrap(Object key);
|
||||
static inline bool IsKey(ReadOnlyRoots roots, Object k);
|
||||
@ -252,15 +260,15 @@ class V8_EXPORT_PRIVATE GlobalDictionary
|
||||
public:
|
||||
DECL_CAST(GlobalDictionary)
|
||||
|
||||
inline Object ValueAt(int entry);
|
||||
inline Object ValueAt(Isolate* isolate, int entry);
|
||||
inline PropertyCell CellAt(int entry);
|
||||
inline PropertyCell CellAt(Isolate* isolate, int entry);
|
||||
inline void SetEntry(Isolate* isolate, int entry, Object key, Object value,
|
||||
PropertyDetails details);
|
||||
inline Name NameAt(int entry);
|
||||
inline Name NameAt(Isolate* isolate, int entry);
|
||||
inline void ValueAtPut(int entry, Object value);
|
||||
inline Object ValueAt(InternalIndex entry);
|
||||
inline Object ValueAt(Isolate* isolate, InternalIndex entry);
|
||||
inline PropertyCell CellAt(InternalIndex entry);
|
||||
inline PropertyCell CellAt(Isolate* isolate, InternalIndex entry);
|
||||
inline void SetEntry(Isolate* isolate, InternalIndex entry, Object key,
|
||||
Object value, PropertyDetails details);
|
||||
inline Name NameAt(InternalIndex entry);
|
||||
inline Name NameAt(Isolate* isolate, InternalIndex entry);
|
||||
inline void ValueAtPut(InternalIndex entry, Object value);
|
||||
|
||||
OBJECT_CONSTRUCTORS(
|
||||
GlobalDictionary,
|
||||
@ -291,13 +299,14 @@ class SimpleNumberDictionaryShape : public NumberDictionaryBaseShape {
|
||||
static const int kEntrySize = 2;
|
||||
|
||||
template <typename Dictionary>
|
||||
static inline PropertyDetails DetailsAt(Dictionary dict, int entry) {
|
||||
static inline PropertyDetails DetailsAt(Dictionary dict,
|
||||
InternalIndex entry) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
template <typename Dictionary>
|
||||
static inline void DetailsAtPut(Isolate* isolate, Dictionary dict, int entry,
|
||||
PropertyDetails value) {
|
||||
static inline void DetailsAtPut(Isolate* isolate, Dictionary dict,
|
||||
InternalIndex entry, PropertyDetails value) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
@ -228,8 +228,8 @@ void CopyDictionaryToObjectElements(Isolate* isolate, FixedArrayBase from_base,
|
||||
}
|
||||
WriteBarrierMode write_barrier_mode = GetWriteBarrierMode(to_kind);
|
||||
for (int i = 0; i < copy_size; i++) {
|
||||
int entry = from.FindEntry(isolate, i + from_start);
|
||||
if (entry != NumberDictionary::kNotFound) {
|
||||
InternalIndex entry = from.FindEntry(isolate, i + from_start);
|
||||
if (entry.is_found()) {
|
||||
Object value = from.ValueAt(entry);
|
||||
DCHECK(!value.IsTheHole(isolate));
|
||||
to.set(i + to_start, value, write_barrier_mode);
|
||||
@ -432,8 +432,8 @@ void CopyDictionaryToDoubleElements(Isolate* isolate, FixedArrayBase from_base,
|
||||
copy_size = to_length - to_start;
|
||||
}
|
||||
for (int i = 0; i < copy_size; i++) {
|
||||
int entry = from.FindEntry(isolate, i + from_start);
|
||||
if (entry != NumberDictionary::kNotFound) {
|
||||
InternalIndex entry = from.FindEntry(isolate, i + from_start);
|
||||
if (entry.is_found()) {
|
||||
to.set(i + to_start, from.ValueAt(entry).Number());
|
||||
} else {
|
||||
to.set_the_hole(i + to_start);
|
||||
@ -1364,7 +1364,6 @@ class DictionaryElementsAccessor
|
||||
Handle<FixedArrayBase> backing_store) {
|
||||
Handle<NumberDictionary> dict =
|
||||
Handle<NumberDictionary>::cast(backing_store);
|
||||
int capacity = dict->Capacity();
|
||||
uint32_t old_length = 0;
|
||||
CHECK(array->length().ToArrayLength(&old_length));
|
||||
{
|
||||
@ -1374,7 +1373,7 @@ class DictionaryElementsAccessor
|
||||
if (dict->requires_slow_elements()) {
|
||||
// Find last non-deletable element in range of elements to be
|
||||
// deleted and adjust range accordingly.
|
||||
for (int entry = 0; entry < capacity; entry++) {
|
||||
for (InternalIndex entry : dict->IterateEntries()) {
|
||||
Object index = dict->KeyAt(entry);
|
||||
if (dict->IsKey(roots, index)) {
|
||||
uint32_t number = static_cast<uint32_t>(index.Number());
|
||||
@ -1392,7 +1391,7 @@ class DictionaryElementsAccessor
|
||||
} else {
|
||||
// Remove elements that should be deleted.
|
||||
int removed_entries = 0;
|
||||
for (int entry = 0; entry < capacity; entry++) {
|
||||
for (InternalIndex entry : dict->IterateEntries()) {
|
||||
Object index = dict->KeyAt(entry);
|
||||
if (dict->IsKey(roots, index)) {
|
||||
uint32_t number = static_cast<uint32_t>(index.Number());
|
||||
@ -1425,8 +1424,7 @@ class DictionaryElementsAccessor
|
||||
static void DeleteImpl(Handle<JSObject> obj, InternalIndex entry) {
|
||||
Handle<NumberDictionary> dict(NumberDictionary::cast(obj->elements()),
|
||||
obj->GetIsolate());
|
||||
dict =
|
||||
NumberDictionary::DeleteEntry(obj->GetIsolate(), dict, entry.as_int());
|
||||
dict = NumberDictionary::DeleteEntry(obj->GetIsolate(), dict, entry);
|
||||
obj->set_elements(*dict);
|
||||
}
|
||||
|
||||
@ -1434,9 +1432,8 @@ class DictionaryElementsAccessor
|
||||
DisallowHeapAllocation no_gc;
|
||||
NumberDictionary dict = NumberDictionary::cast(backing_store);
|
||||
if (!dict.requires_slow_elements()) return false;
|
||||
int capacity = dict.Capacity();
|
||||
ReadOnlyRoots roots = holder.GetReadOnlyRoots();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dict.IterateEntries()) {
|
||||
Object key = dict.KeyAt(i);
|
||||
if (!dict.IsKey(roots, key)) continue;
|
||||
PropertyDetails details = dict.DetailsAt(i);
|
||||
@ -1447,7 +1444,7 @@ class DictionaryElementsAccessor
|
||||
|
||||
static Object GetRaw(FixedArrayBase store, InternalIndex entry) {
|
||||
NumberDictionary backing_store = NumberDictionary::cast(store);
|
||||
return backing_store.ValueAt(entry.as_int());
|
||||
return backing_store.ValueAt(entry);
|
||||
}
|
||||
|
||||
static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase backing_store,
|
||||
@ -1462,7 +1459,7 @@ class DictionaryElementsAccessor
|
||||
|
||||
static inline void SetImpl(FixedArrayBase backing_store, InternalIndex entry,
|
||||
Object value) {
|
||||
NumberDictionary::cast(backing_store).ValueAtPut(entry.as_int(), value);
|
||||
NumberDictionary::cast(backing_store).ValueAtPut(entry, value);
|
||||
}
|
||||
|
||||
static void ReconfigureImpl(Handle<JSObject> object,
|
||||
@ -1471,12 +1468,12 @@ class DictionaryElementsAccessor
|
||||
PropertyAttributes attributes) {
|
||||
NumberDictionary dictionary = NumberDictionary::cast(*store);
|
||||
if (attributes != NONE) object->RequireSlowElements(dictionary);
|
||||
dictionary.ValueAtPut(entry.as_int(), *value);
|
||||
PropertyDetails details = dictionary.DetailsAt(entry.as_int());
|
||||
dictionary.ValueAtPut(entry, *value);
|
||||
PropertyDetails details = dictionary.DetailsAt(entry);
|
||||
details = PropertyDetails(kData, attributes, PropertyCellType::kNoCell,
|
||||
details.dictionary_index());
|
||||
|
||||
dictionary.DetailsAtPut(object->GetIsolate(), entry.as_int(), details);
|
||||
dictionary.DetailsAtPut(object->GetIsolate(), entry, details);
|
||||
}
|
||||
|
||||
static void AddImpl(Handle<JSObject> object, uint32_t index,
|
||||
@ -1500,7 +1497,7 @@ class DictionaryElementsAccessor
|
||||
InternalIndex entry) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
NumberDictionary dict = NumberDictionary::cast(store);
|
||||
Object index = dict.KeyAt(entry.as_int());
|
||||
Object index = dict.KeyAt(entry);
|
||||
return !index.IsTheHole(isolate);
|
||||
}
|
||||
|
||||
@ -1509,7 +1506,7 @@ class DictionaryElementsAccessor
|
||||
DisallowHeapAllocation no_gc;
|
||||
NumberDictionary dict = NumberDictionary::cast(store);
|
||||
uint32_t result = 0;
|
||||
CHECK(dict.KeyAt(entry.as_int()).ToArrayIndex(&result));
|
||||
CHECK(dict.KeyAt(entry).ToArrayIndex(&result));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1519,16 +1516,15 @@ class DictionaryElementsAccessor
|
||||
PropertyFilter filter) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
NumberDictionary dictionary = NumberDictionary::cast(store);
|
||||
int entry = dictionary.FindEntry(isolate, index);
|
||||
if (entry == NumberDictionary::kNotFound) {
|
||||
return InternalIndex::NotFound();
|
||||
}
|
||||
InternalIndex entry = dictionary.FindEntry(isolate, index);
|
||||
if (entry.is_not_found()) return entry;
|
||||
|
||||
if (filter != ALL_PROPERTIES) {
|
||||
PropertyDetails details = dictionary.DetailsAt(entry);
|
||||
PropertyAttributes attr = details.attributes();
|
||||
if ((attr & filter) != 0) return InternalIndex::NotFound();
|
||||
}
|
||||
return InternalIndex(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
static PropertyDetails GetDetailsImpl(JSObject holder, InternalIndex entry) {
|
||||
@ -1537,11 +1533,12 @@ class DictionaryElementsAccessor
|
||||
|
||||
static PropertyDetails GetDetailsImpl(FixedArrayBase backing_store,
|
||||
InternalIndex entry) {
|
||||
return NumberDictionary::cast(backing_store).DetailsAt(entry.as_int());
|
||||
return NumberDictionary::cast(backing_store).DetailsAt(entry);
|
||||
}
|
||||
|
||||
static uint32_t FilterKey(Handle<NumberDictionary> dictionary, int entry,
|
||||
Object raw_key, PropertyFilter filter) {
|
||||
static uint32_t FilterKey(Handle<NumberDictionary> dictionary,
|
||||
InternalIndex entry, Object raw_key,
|
||||
PropertyFilter filter) {
|
||||
DCHECK(raw_key.IsNumber());
|
||||
DCHECK_LE(raw_key.Number(), kMaxUInt32);
|
||||
PropertyDetails details = dictionary->DetailsAt(entry);
|
||||
@ -1552,7 +1549,8 @@ class DictionaryElementsAccessor
|
||||
|
||||
static uint32_t GetKeyForEntryImpl(Isolate* isolate,
|
||||
Handle<NumberDictionary> dictionary,
|
||||
int entry, PropertyFilter filter) {
|
||||
InternalIndex entry,
|
||||
PropertyFilter filter) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
Object raw_key = dictionary->KeyAt(entry);
|
||||
if (!dictionary->IsKey(ReadOnlyRoots(isolate), raw_key)) return kMaxUInt32;
|
||||
@ -1566,13 +1564,12 @@ class DictionaryElementsAccessor
|
||||
Isolate* isolate = keys->isolate();
|
||||
Handle<NumberDictionary> dictionary =
|
||||
Handle<NumberDictionary>::cast(backing_store);
|
||||
int capacity = dictionary->Capacity();
|
||||
Handle<FixedArray> elements = isolate->factory()->NewFixedArray(
|
||||
GetMaxNumberOfEntries(*object, *backing_store));
|
||||
int insertion_index = 0;
|
||||
PropertyFilter filter = keys->filter();
|
||||
ReadOnlyRoots roots(isolate);
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary->IterateEntries()) {
|
||||
Object raw_key = dictionary->KeyAt(i);
|
||||
if (!dictionary->IsKey(roots, raw_key)) continue;
|
||||
uint32_t key = FilterKey(dictionary, i, raw_key, filter);
|
||||
@ -1600,8 +1597,7 @@ class DictionaryElementsAccessor
|
||||
|
||||
Handle<NumberDictionary> dictionary =
|
||||
Handle<NumberDictionary>::cast(backing_store);
|
||||
uint32_t capacity = dictionary->Capacity();
|
||||
for (uint32_t i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary->IterateEntries()) {
|
||||
uint32_t key = GetKeyForEntryImpl(isolate, dictionary, i, filter);
|
||||
if (key == kMaxUInt32) continue;
|
||||
Handle<Object> index = isolate->factory()->NewNumberFromUint(key);
|
||||
@ -1618,9 +1614,8 @@ class DictionaryElementsAccessor
|
||||
Isolate* isolate = accumulator->isolate();
|
||||
Handle<NumberDictionary> dictionary(
|
||||
NumberDictionary::cast(receiver->elements()), isolate);
|
||||
int capacity = dictionary->Capacity();
|
||||
ReadOnlyRoots roots(isolate);
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary->IterateEntries()) {
|
||||
Object k = dictionary->KeyAt(i);
|
||||
if (!dictionary->IsKey(roots, k)) continue;
|
||||
Object value = dictionary->ValueAt(i);
|
||||
@ -1637,14 +1632,13 @@ class DictionaryElementsAccessor
|
||||
uint32_t length, Maybe<bool>* result) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
NumberDictionary dictionary = NumberDictionary::cast(receiver->elements());
|
||||
int capacity = dictionary.Capacity();
|
||||
Object the_hole = ReadOnlyRoots(isolate).the_hole_value();
|
||||
Object undefined = ReadOnlyRoots(isolate).undefined_value();
|
||||
|
||||
// Scan for accessor properties. If accessors are present, then elements
|
||||
// must be accessed in order via the slow path.
|
||||
bool found = false;
|
||||
for (int i = 0; i < capacity; ++i) {
|
||||
for (InternalIndex i : dictionary.IterateEntries()) {
|
||||
Object k = dictionary.KeyAt(i);
|
||||
if (k == the_hole) continue;
|
||||
if (k == undefined) continue;
|
||||
@ -1690,14 +1684,13 @@ class DictionaryElementsAccessor
|
||||
// observable
|
||||
for (uint32_t k = start_from; k < length; ++k) {
|
||||
DCHECK_EQ(receiver->GetElementsKind(), original_elements_kind);
|
||||
int entry = dictionary->FindEntry(isolate, k);
|
||||
if (entry == NumberDictionary::kNotFound) {
|
||||
InternalIndex entry = dictionary->FindEntry(isolate, k);
|
||||
if (entry.is_not_found()) {
|
||||
if (search_for_hole) return Just(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
PropertyDetails details =
|
||||
GetDetailsImpl(*dictionary, InternalIndex(entry));
|
||||
PropertyDetails details = GetDetailsImpl(*dictionary, entry);
|
||||
switch (details.kind()) {
|
||||
case kData: {
|
||||
Object element_k = dictionary->ValueAt(entry);
|
||||
@ -1763,8 +1756,8 @@ class DictionaryElementsAccessor
|
||||
// observable.
|
||||
for (uint32_t k = start_from; k < length; ++k) {
|
||||
DCHECK_EQ(receiver->GetElementsKind(), original_elements_kind);
|
||||
int entry = dictionary->FindEntry(isolate, k);
|
||||
if (entry == NumberDictionary::kNotFound) continue;
|
||||
InternalIndex entry = dictionary->FindEntry(isolate, k);
|
||||
if (entry.is_not_found()) continue;
|
||||
|
||||
PropertyDetails details =
|
||||
GetDetailsImpl(*dictionary, InternalIndex(entry));
|
||||
@ -1821,10 +1814,9 @@ class DictionaryElementsAccessor
|
||||
ReadOnlyRoots roots = holder.GetReadOnlyRoots();
|
||||
NumberDictionary dictionary = NumberDictionary::cast(holder.elements());
|
||||
// Validate the requires_slow_elements and max_number_key values.
|
||||
int capacity = dictionary.Capacity();
|
||||
bool requires_slow_elements = false;
|
||||
int max_key = 0;
|
||||
for (int i = 0; i < capacity; ++i) {
|
||||
for (InternalIndex i : dictionary.IterateEntries()) {
|
||||
Object k;
|
||||
if (!dictionary.ToKey(roots, i, &k)) continue;
|
||||
DCHECK_LE(0.0, k.Number());
|
||||
@ -4288,8 +4280,8 @@ class SlowSloppyArgumentsElementsAccessor
|
||||
Handle<NumberDictionary> dict(NumberDictionary::cast(elements->arguments()),
|
||||
isolate);
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
dict = NumberDictionary::DeleteEntry(isolate, dict,
|
||||
entry.as_uint32() - length);
|
||||
dict =
|
||||
NumberDictionary::DeleteEntry(isolate, dict, entry.adjust_down(length));
|
||||
elements->set_arguments(*dict);
|
||||
}
|
||||
static void AddImpl(Handle<JSObject> object, uint32_t index,
|
||||
@ -4391,9 +4383,9 @@ class FastSloppyArgumentsElementsAccessor
|
||||
uint32_t length = elements->parameter_map_length();
|
||||
if (entry->as_uint32() >= length) {
|
||||
*entry =
|
||||
InternalIndex(dictionary->FindEntry(object->GetIsolate(),
|
||||
entry->as_uint32() - length) +
|
||||
length);
|
||||
dictionary
|
||||
->FindEntry(object->GetIsolate(), entry->as_uint32() - length)
|
||||
.adjust_up(length);
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
@ -1278,8 +1278,8 @@ void FeedbackNexus::Collect(Handle<String> type, int position) {
|
||||
|
||||
Handle<ArrayList> position_specific_types;
|
||||
|
||||
int entry = types->FindEntry(isolate, position);
|
||||
if (entry == SimpleNumberDictionary::kNotFound) {
|
||||
InternalIndex entry = types->FindEntry(isolate, position);
|
||||
if (entry.is_not_found()) {
|
||||
position_specific_types = ArrayList::New(isolate, 1);
|
||||
types = SimpleNumberDictionary::Set(
|
||||
isolate, types, position,
|
||||
@ -1341,10 +1341,9 @@ std::vector<Handle<String>> FeedbackNexus::GetTypesForSourcePositions(
|
||||
SimpleNumberDictionary::cast(feedback->GetHeapObjectAssumeStrong()),
|
||||
isolate);
|
||||
|
||||
int entry = types->FindEntry(isolate, position);
|
||||
if (entry == SimpleNumberDictionary::kNotFound) {
|
||||
return types_for_position;
|
||||
}
|
||||
InternalIndex entry = types->FindEntry(isolate, position);
|
||||
if (entry.is_not_found()) return types_for_position;
|
||||
|
||||
DCHECK(types->ValueAt(entry).IsArrayList());
|
||||
Handle<ArrayList> position_specific_types =
|
||||
Handle<ArrayList>(ArrayList::cast(types->ValueAt(entry)), isolate);
|
||||
|
@ -85,6 +85,10 @@ int HashTableBase::Capacity() const {
|
||||
return TaggedField<Smi>::load(*this, offset).value();
|
||||
}
|
||||
|
||||
InternalIndex::Range HashTableBase::IterateEntries() const {
|
||||
return InternalIndex::Range(Capacity());
|
||||
}
|
||||
|
||||
void HashTableBase::ElementAdded() {
|
||||
SetNumberOfElements(NumberOfElements() + 1);
|
||||
}
|
||||
@ -127,16 +131,16 @@ RootIndex EphemeronHashTableShape::GetMapRootIndex() {
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
int HashTable<Derived, Shape>::FindEntry(Isolate* isolate, Key key) {
|
||||
InternalIndex HashTable<Derived, Shape>::FindEntry(Isolate* isolate, Key key) {
|
||||
return FindEntry(ReadOnlyRoots(isolate), key, Shape::Hash(isolate, key));
|
||||
}
|
||||
|
||||
// Find entry for key otherwise return kNotFound.
|
||||
template <typename Derived, typename Shape>
|
||||
int HashTable<Derived, Shape>::FindEntry(ReadOnlyRoots roots, Key key,
|
||||
int32_t hash) {
|
||||
InternalIndex HashTable<Derived, Shape>::FindEntry(ReadOnlyRoots roots, Key key,
|
||||
int32_t hash) {
|
||||
uint32_t capacity = Capacity();
|
||||
uint32_t entry = FirstProbe(hash, capacity);
|
||||
InternalIndex entry = FirstProbe(hash, capacity);
|
||||
uint32_t count = 1;
|
||||
// EnsureCapacity will guarantee the hash table is never full.
|
||||
Object undefined = roots.undefined_value();
|
||||
@ -152,7 +156,7 @@ int HashTable<Derived, Shape>::FindEntry(ReadOnlyRoots roots, Key key,
|
||||
}
|
||||
entry = NextProbe(entry, count++, capacity);
|
||||
}
|
||||
return kNotFound;
|
||||
return InternalIndex::NotFound();
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
@ -161,7 +165,7 @@ bool HashTable<Derived, Shape>::IsKey(ReadOnlyRoots roots, Object k) {
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
bool HashTable<Derived, Shape>::ToKey(ReadOnlyRoots roots, int entry,
|
||||
bool HashTable<Derived, Shape>::ToKey(ReadOnlyRoots roots, InternalIndex entry,
|
||||
Object* out_k) {
|
||||
Object k = KeyAt(entry);
|
||||
if (!IsKey(roots, k)) return false;
|
||||
@ -170,7 +174,7 @@ bool HashTable<Derived, Shape>::ToKey(ReadOnlyRoots roots, int entry,
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
bool HashTable<Derived, Shape>::ToKey(Isolate* isolate, int entry,
|
||||
bool HashTable<Derived, Shape>::ToKey(Isolate* isolate, InternalIndex entry,
|
||||
Object* out_k) {
|
||||
Object k = KeyAt(isolate, entry);
|
||||
if (!IsKey(GetReadOnlyRoots(isolate), k)) return false;
|
||||
@ -202,13 +206,13 @@ bool BaseShape<KeyT>::IsLive(ReadOnlyRoots roots, Object k) {
|
||||
}
|
||||
|
||||
bool ObjectHashSet::Has(Isolate* isolate, Handle<Object> key, int32_t hash) {
|
||||
return FindEntry(ReadOnlyRoots(isolate), key, hash) != kNotFound;
|
||||
return FindEntry(ReadOnlyRoots(isolate), key, hash).is_found();
|
||||
}
|
||||
|
||||
bool ObjectHashSet::Has(Isolate* isolate, Handle<Object> key) {
|
||||
Object hash = key->GetHash();
|
||||
if (!hash.IsSmi()) return false;
|
||||
return FindEntry(ReadOnlyRoots(isolate), key, Smi::ToInt(hash)) != kNotFound;
|
||||
return FindEntry(ReadOnlyRoots(isolate), key, Smi::ToInt(hash)).is_found();
|
||||
}
|
||||
|
||||
bool ObjectHashTableShape::IsMatch(Handle<Object> key, Object other) {
|
||||
|
@ -77,6 +77,8 @@ class V8_EXPORT_PRIVATE HashTableBase : public NON_EXPORTED_BASE(FixedArray) {
|
||||
// Returns the capacity of the hash table.
|
||||
inline int Capacity() const;
|
||||
|
||||
inline InternalIndex::Range IterateEntries() const;
|
||||
|
||||
// ElementAdded should be called whenever an element is added to a
|
||||
// hash table.
|
||||
inline void ElementAdded();
|
||||
@ -90,19 +92,11 @@ class V8_EXPORT_PRIVATE HashTableBase : public NON_EXPORTED_BASE(FixedArray) {
|
||||
// number of elements. May be more than HashTable::kMaxCapacity.
|
||||
static inline int ComputeCapacity(int at_least_space_for);
|
||||
|
||||
// Compute the probe offset (quadratic probing).
|
||||
V8_INLINE static uint32_t GetProbeOffset(uint32_t n) {
|
||||
return (n + n * n) >> 1;
|
||||
}
|
||||
|
||||
static const int kNumberOfElementsIndex = 0;
|
||||
static const int kNumberOfDeletedElementsIndex = 1;
|
||||
static const int kCapacityIndex = 2;
|
||||
static const int kPrefixStartIndex = 3;
|
||||
|
||||
// Constant used for denoting a absent entry.
|
||||
static const int kNotFound = -1;
|
||||
|
||||
// Minimum capacity for newly created hash tables.
|
||||
static const int kMinCapacity = 4;
|
||||
|
||||
@ -114,18 +108,13 @@ class V8_EXPORT_PRIVATE HashTableBase : public NON_EXPORTED_BASE(FixedArray) {
|
||||
inline void SetNumberOfDeletedElements(int nod);
|
||||
|
||||
// Returns probe entry.
|
||||
static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
|
||||
DCHECK(base::bits::IsPowerOfTwo(size));
|
||||
return (hash + GetProbeOffset(number)) & (size - 1);
|
||||
inline static InternalIndex FirstProbe(uint32_t hash, uint32_t size) {
|
||||
return InternalIndex(hash & (size - 1));
|
||||
}
|
||||
|
||||
inline static uint32_t FirstProbe(uint32_t hash, uint32_t size) {
|
||||
return hash & (size - 1);
|
||||
}
|
||||
|
||||
inline static uint32_t NextProbe(uint32_t last, uint32_t number,
|
||||
uint32_t size) {
|
||||
return (last + number) & (size - 1);
|
||||
inline static InternalIndex NextProbe(InternalIndex last, uint32_t number,
|
||||
uint32_t size) {
|
||||
return InternalIndex((last.as_uint32() + number) & (size - 1));
|
||||
}
|
||||
|
||||
OBJECT_CONSTRUCTORS(HashTableBase, FixedArray);
|
||||
@ -149,8 +138,8 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable
|
||||
void IterateElements(ObjectVisitor* visitor);
|
||||
|
||||
// Find entry for key otherwise return kNotFound.
|
||||
inline int FindEntry(ReadOnlyRoots roots, Key key, int32_t hash);
|
||||
inline int FindEntry(Isolate* isolate, Key key);
|
||||
inline InternalIndex FindEntry(ReadOnlyRoots roots, Key key, int32_t hash);
|
||||
inline InternalIndex FindEntry(Isolate* isolate, Key key);
|
||||
|
||||
// Rehashes the table in-place.
|
||||
void Rehash(ReadOnlyRoots roots);
|
||||
@ -159,15 +148,15 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable
|
||||
// as keys and can be used to indicate missing or deleted elements.
|
||||
static bool IsKey(ReadOnlyRoots roots, Object k);
|
||||
|
||||
inline bool ToKey(ReadOnlyRoots roots, int entry, Object* out_k);
|
||||
inline bool ToKey(Isolate* isolate, int entry, Object* out_k);
|
||||
inline bool ToKey(ReadOnlyRoots roots, InternalIndex entry, Object* out_k);
|
||||
inline bool ToKey(Isolate* isolate, InternalIndex entry, Object* out_k);
|
||||
|
||||
// Returns the key at entry.
|
||||
Object KeyAt(int entry) {
|
||||
Object KeyAt(InternalIndex entry) {
|
||||
Isolate* isolate = GetIsolateForPtrCompr(*this);
|
||||
return KeyAt(isolate, entry);
|
||||
}
|
||||
Object KeyAt(Isolate* isolate, int entry) {
|
||||
Object KeyAt(Isolate* isolate, InternalIndex entry) {
|
||||
return get(isolate, EntryToIndex(entry) + kEntryKeyIndex);
|
||||
}
|
||||
|
||||
@ -189,13 +178,13 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable
|
||||
static const int kMaxRegularCapacity = kMaxRegularHeapObjectSize / 32;
|
||||
|
||||
// Returns the index for an entry (of the key)
|
||||
static constexpr inline int EntryToIndex(int entry) {
|
||||
return (entry * kEntrySize) + kElementsStartIndex;
|
||||
static constexpr inline int EntryToIndex(InternalIndex entry) {
|
||||
return (entry.as_int() * kEntrySize) + kElementsStartIndex;
|
||||
}
|
||||
|
||||
// Returns the index for an entry (of the key)
|
||||
static constexpr inline int IndexToEntry(int index) {
|
||||
return (index - kElementsStartIndex) / kEntrySize;
|
||||
// Returns the entry for an index (of the key)
|
||||
static constexpr inline InternalIndex IndexToEntry(int index) {
|
||||
return InternalIndex((index - kElementsStartIndex) / kEntrySize);
|
||||
}
|
||||
|
||||
// Returns the index for a slot address in the object.
|
||||
@ -219,7 +208,7 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable
|
||||
|
||||
// Find the entry at which to insert element with the given key that
|
||||
// has the given hash value.
|
||||
uint32_t FindInsertionEntry(uint32_t hash);
|
||||
InternalIndex FindInsertionEntry(uint32_t hash);
|
||||
|
||||
// Attempt to shrink hash table after removal of key.
|
||||
V8_WARN_UNUSED_RESULT static Handle<Derived> Shrink(
|
||||
@ -230,10 +219,12 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable
|
||||
|
||||
private:
|
||||
// Ensure that kMaxRegularCapacity yields a non-large object dictionary.
|
||||
STATIC_ASSERT(EntryToIndex(kMaxRegularCapacity) < kMaxRegularLength);
|
||||
STATIC_ASSERT(EntryToIndex(InternalIndex(kMaxRegularCapacity)) <
|
||||
kMaxRegularLength);
|
||||
STATIC_ASSERT(v8::base::bits::IsPowerOfTwo(kMaxRegularCapacity));
|
||||
static const int kMaxRegularEntry = kMaxRegularCapacity / kEntrySize;
|
||||
static const int kMaxRegularIndex = EntryToIndex(kMaxRegularEntry);
|
||||
static const int kMaxRegularIndex =
|
||||
EntryToIndex(InternalIndex(kMaxRegularEntry));
|
||||
STATIC_ASSERT(OffsetOfElementAt(kMaxRegularIndex) <
|
||||
kMaxRegularHeapObjectSize);
|
||||
|
||||
@ -250,10 +241,10 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) HashTable
|
||||
// Returns _expected_ if one of entries given by the first _probe_ probes is
|
||||
// equal to _expected_. Otherwise, returns the entry given by the probe
|
||||
// number _probe_.
|
||||
uint32_t EntryForProbe(ReadOnlyRoots roots, Object k, int probe,
|
||||
uint32_t expected);
|
||||
InternalIndex EntryForProbe(ReadOnlyRoots roots, Object k, int probe,
|
||||
InternalIndex expected);
|
||||
|
||||
void Swap(uint32_t entry1, uint32_t entry2, WriteBarrierMode mode);
|
||||
void Swap(InternalIndex entry1, InternalIndex entry2, WriteBarrierMode mode);
|
||||
|
||||
// Rehashes this hash-table into the new table.
|
||||
void Rehash(ReadOnlyRoots roots, Derived new_table);
|
||||
@ -307,7 +298,7 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) ObjectHashTableBase
|
||||
Object Lookup(ReadOnlyRoots roots, Handle<Object> key, int32_t hash);
|
||||
|
||||
// Returns the value at entry.
|
||||
Object ValueAt(int entry);
|
||||
Object ValueAt(InternalIndex entry);
|
||||
|
||||
// Overwrite all keys and values with the hole value.
|
||||
static void FillEntriesWithHoles(Handle<Derived>);
|
||||
@ -327,14 +318,14 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) ObjectHashTableBase
|
||||
int32_t hash);
|
||||
|
||||
// Returns the index to the value of an entry.
|
||||
static inline int EntryToValueIndex(int entry) {
|
||||
static inline int EntryToValueIndex(InternalIndex entry) {
|
||||
return HashTable<Derived, Shape>::EntryToIndex(entry) +
|
||||
Shape::kEntryValueIndex;
|
||||
}
|
||||
|
||||
protected:
|
||||
void AddEntry(int entry, Object key, Object value);
|
||||
void RemoveEntry(int entry);
|
||||
void AddEntry(InternalIndex entry, Object key, Object value);
|
||||
void RemoveEntry(InternalIndex entry);
|
||||
|
||||
OBJECT_CONSTRUCTORS(ObjectHashTableBase, HashTable<Derived, Shape>);
|
||||
};
|
||||
|
@ -19,14 +19,14 @@ namespace internal {
|
||||
// wrapper: get it via GetEntryForIndex, pass it on to consumers.
|
||||
class InternalIndex {
|
||||
public:
|
||||
explicit InternalIndex(size_t raw) : entry_(raw) {}
|
||||
explicit constexpr InternalIndex(size_t raw) : entry_(raw) {}
|
||||
static InternalIndex NotFound() { return InternalIndex(kNotFound); }
|
||||
|
||||
InternalIndex adjust_down(size_t subtract) {
|
||||
V8_WARN_UNUSED_RESULT InternalIndex adjust_down(size_t subtract) const {
|
||||
DCHECK_GE(entry_, subtract);
|
||||
return InternalIndex(entry_ - subtract);
|
||||
}
|
||||
InternalIndex adjust_up(size_t add) {
|
||||
V8_WARN_UNUSED_RESULT InternalIndex adjust_up(size_t add) const {
|
||||
DCHECK_LT(entry_, std::numeric_limits<size_t>::max() - add);
|
||||
return InternalIndex(entry_ + add);
|
||||
}
|
||||
@ -39,8 +39,11 @@ class InternalIndex {
|
||||
DCHECK_LE(entry_, std::numeric_limits<uint32_t>::max());
|
||||
return static_cast<uint32_t>(entry_);
|
||||
}
|
||||
int as_int() const {
|
||||
DCHECK(entry_ >= 0 && entry_ <= std::numeric_limits<int>::max());
|
||||
constexpr int as_int() const {
|
||||
#if V8_CAN_HAVE_DCHECK_IN_CONSTEXPR
|
||||
// TODO(clemensb): DCHECK_LE is not constexpr.
|
||||
DCHECK(entry_ <= std::numeric_limits<int>::max());
|
||||
#endif
|
||||
return static_cast<int>(entry_);
|
||||
}
|
||||
|
||||
|
@ -705,15 +705,15 @@ Smi JSReceiver::GetOrCreateIdentityHash(Isolate* isolate) {
|
||||
}
|
||||
|
||||
void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
|
||||
int entry) {
|
||||
InternalIndex entry) {
|
||||
DCHECK(!object->HasFastProperties());
|
||||
Isolate* isolate = object->GetIsolate();
|
||||
DCHECK(entry.is_found());
|
||||
|
||||
if (object->IsJSGlobalObject()) {
|
||||
// If we have a global object, invalidate the cell and swap in a new one.
|
||||
Handle<GlobalDictionary> dictionary(
|
||||
JSGlobalObject::cast(*object).global_dictionary(), isolate);
|
||||
DCHECK_NE(GlobalDictionary::kNotFound, entry);
|
||||
|
||||
auto cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
|
||||
cell->set_value(ReadOnlyRoots(isolate).the_hole_value());
|
||||
@ -721,7 +721,6 @@ void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
|
||||
PropertyDetails::Empty(PropertyCellType::kUninitialized));
|
||||
} else {
|
||||
Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
|
||||
DCHECK_NE(NameDictionary::kNotFound, entry);
|
||||
|
||||
dictionary = NameDictionary::DeleteEntry(isolate, dictionary, entry);
|
||||
object->SetProperties(*dictionary);
|
||||
@ -2332,9 +2331,10 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object, Handle<Name> name,
|
||||
Handle<JSGlobalObject> global_obj = Handle<JSGlobalObject>::cast(object);
|
||||
Handle<GlobalDictionary> dictionary(global_obj->global_dictionary(),
|
||||
isolate);
|
||||
int entry = dictionary->FindEntry(ReadOnlyRoots(isolate), name, hash);
|
||||
InternalIndex entry =
|
||||
dictionary->FindEntry(ReadOnlyRoots(isolate), name, hash);
|
||||
|
||||
if (entry == GlobalDictionary::kNotFound) {
|
||||
if (entry.is_not_found()) {
|
||||
DCHECK_IMPLIES(global_obj->map().is_prototype_map(),
|
||||
Map::IsPrototypeChainInvalidated(global_obj->map()));
|
||||
auto cell = isolate->factory()->NewPropertyCell(name);
|
||||
@ -2355,8 +2355,8 @@ void JSObject::SetNormalizedProperty(Handle<JSObject> object, Handle<Name> name,
|
||||
} else {
|
||||
Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
|
||||
|
||||
int entry = dictionary->FindEntry(isolate, name);
|
||||
if (entry == NameDictionary::kNotFound) {
|
||||
InternalIndex entry = dictionary->FindEntry(isolate, name);
|
||||
if (entry.is_not_found()) {
|
||||
DCHECK_IMPLIES(object->map().is_prototype_map(),
|
||||
Map::IsPrototypeChainInvalidated(object->map()));
|
||||
dictionary =
|
||||
@ -3331,7 +3331,7 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
|
||||
// Compute the length of the instance descriptor.
|
||||
ReadOnlyRoots roots(isolate);
|
||||
for (int i = 0; i < instance_descriptor_length; i++) {
|
||||
int index = Smi::ToInt(iteration_order->get(i));
|
||||
InternalIndex index(Smi::ToInt(iteration_order->get(i)));
|
||||
DCHECK(dictionary->IsKey(roots, dictionary->KeyAt(index)));
|
||||
|
||||
PropertyKind kind = dictionary->DetailsAt(index).kind();
|
||||
@ -3391,7 +3391,7 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
|
||||
// Fill in the instance descriptor and the fields.
|
||||
int current_offset = 0;
|
||||
for (int i = 0; i < instance_descriptor_length; i++) {
|
||||
int index = Smi::ToInt(iteration_order->get(i));
|
||||
InternalIndex index(Smi::ToInt(iteration_order->get(i)));
|
||||
Name k = dictionary->NameAt(index);
|
||||
// Dictionary keys are internalized upon insertion.
|
||||
// TODO(jkummerow): Turn this into a DCHECK if it's not hit in the wild.
|
||||
@ -3611,8 +3611,7 @@ bool TestDictionaryPropertiesIntegrityLevel(Dictionary dict,
|
||||
PropertyAttributes level) {
|
||||
DCHECK(level == SEALED || level == FROZEN);
|
||||
|
||||
uint32_t capacity = dict.Capacity();
|
||||
for (uint32_t i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dict.IterateEntries()) {
|
||||
Object key;
|
||||
if (!dict.ToKey(roots, i, &key)) continue;
|
||||
if (key.FilterKey(ALL_PROPERTIES)) continue;
|
||||
@ -3773,8 +3772,7 @@ template <typename Dictionary>
|
||||
void JSObject::ApplyAttributesToDictionary(
|
||||
Isolate* isolate, ReadOnlyRoots roots, Handle<Dictionary> dictionary,
|
||||
const PropertyAttributes attributes) {
|
||||
int capacity = dictionary->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary->IterateEntries()) {
|
||||
Object k;
|
||||
if (!dictionary->ToKey(roots, i, &k)) continue;
|
||||
if (k.FilterKey(ALL_PROPERTIES)) continue;
|
||||
@ -4615,7 +4613,7 @@ static ElementsKind BestFittingFastElementsKind(JSObject object) {
|
||||
DCHECK(object.HasDictionaryElements());
|
||||
NumberDictionary dictionary = object.element_dictionary();
|
||||
ElementsKind kind = HOLEY_SMI_ELEMENTS;
|
||||
for (int i = 0; i < dictionary.Capacity(); i++) {
|
||||
for (InternalIndex i : dictionary.IterateEntries()) {
|
||||
Object key = dictionary.KeyAt(i);
|
||||
if (key.IsNumber()) {
|
||||
Object value = dictionary.ValueAt(i);
|
||||
@ -5632,20 +5630,20 @@ void JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global,
|
||||
|
||||
DCHECK(!global->HasFastProperties());
|
||||
auto dictionary = handle(global->global_dictionary(), global->GetIsolate());
|
||||
int entry = dictionary->FindEntry(global->GetIsolate(), name);
|
||||
if (entry == GlobalDictionary::kNotFound) return;
|
||||
InternalIndex entry = dictionary->FindEntry(global->GetIsolate(), name);
|
||||
if (entry.is_not_found()) return;
|
||||
PropertyCell::InvalidateEntry(global->GetIsolate(), dictionary, entry);
|
||||
}
|
||||
|
||||
Handle<PropertyCell> JSGlobalObject::EnsureEmptyPropertyCell(
|
||||
Handle<JSGlobalObject> global, Handle<Name> name,
|
||||
PropertyCellType cell_type, int* entry_out) {
|
||||
PropertyCellType cell_type, InternalIndex* entry_out) {
|
||||
Isolate* isolate = global->GetIsolate();
|
||||
DCHECK(!global->HasFastProperties());
|
||||
Handle<GlobalDictionary> dictionary(global->global_dictionary(), isolate);
|
||||
int entry = dictionary->FindEntry(isolate, name);
|
||||
InternalIndex entry = dictionary->FindEntry(isolate, name);
|
||||
Handle<PropertyCell> cell;
|
||||
if (entry != GlobalDictionary::kNotFound) {
|
||||
if (entry.is_found()) {
|
||||
if (entry_out) *entry_out = entry;
|
||||
cell = handle(dictionary->CellAt(entry), isolate);
|
||||
PropertyCellType original_cell_type = cell->property_details().cell_type();
|
||||
|
@ -68,7 +68,8 @@ class JSReceiver : public HeapObject {
|
||||
inline void initialize_properties(Isolate* isolate);
|
||||
|
||||
// Deletes an existing named property in a normalized object.
|
||||
static void DeleteNormalizedProperty(Handle<JSReceiver> object, int entry);
|
||||
static void DeleteNormalizedProperty(Handle<JSReceiver> object,
|
||||
InternalIndex entry);
|
||||
|
||||
DECL_CAST(JSReceiver)
|
||||
DECL_VERIFIER(JSReceiver)
|
||||
@ -1205,7 +1206,7 @@ class JSGlobalObject : public JSSpecialObject {
|
||||
// Ensure that the global object has a cell for the given property name.
|
||||
static Handle<PropertyCell> EnsureEmptyPropertyCell(
|
||||
Handle<JSGlobalObject> global, Handle<Name> name,
|
||||
PropertyCellType cell_type, int* entry_out = nullptr);
|
||||
PropertyCellType cell_type, InternalIndex* entry_out = nullptr);
|
||||
|
||||
DECL_CAST(JSGlobalObject)
|
||||
|
||||
|
@ -81,14 +81,16 @@ void AddToDescriptorArrayTemplate(
|
||||
|
||||
Handle<NameDictionary> DictionaryAddNoUpdateNextEnumerationIndex(
|
||||
Isolate* isolate, Handle<NameDictionary> dictionary, Handle<Name> name,
|
||||
Handle<Object> value, PropertyDetails details, int* entry_out = nullptr) {
|
||||
Handle<Object> value, PropertyDetails details,
|
||||
InternalIndex* entry_out = nullptr) {
|
||||
return NameDictionary::AddNoUpdateNextEnumerationIndex(
|
||||
isolate, dictionary, name, value, details, entry_out);
|
||||
}
|
||||
|
||||
Handle<NumberDictionary> DictionaryAddNoUpdateNextEnumerationIndex(
|
||||
Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t element,
|
||||
Handle<Object> value, PropertyDetails details, int* entry_out = nullptr) {
|
||||
Handle<Object> value, PropertyDetails details,
|
||||
InternalIndex* entry_out = nullptr) {
|
||||
// NumberDictionary does not maintain the enumeration order, so it's
|
||||
// a normal Add().
|
||||
return NumberDictionary::Add(isolate, dictionary, element, value, details,
|
||||
@ -123,9 +125,9 @@ void AddToDictionaryTemplate(Isolate* isolate, Handle<Dictionary> dictionary,
|
||||
Key key, int key_index,
|
||||
ClassBoilerplate::ValueKind value_kind,
|
||||
Object value) {
|
||||
int entry = dictionary->FindEntry(isolate, key);
|
||||
InternalIndex entry = dictionary->FindEntry(isolate, key);
|
||||
|
||||
if (entry == kNotFound) {
|
||||
if (entry.is_not_found()) {
|
||||
// Entry not found, add new one.
|
||||
const bool is_elements_dictionary =
|
||||
std::is_same<Dictionary, NumberDictionary>::value;
|
||||
|
@ -40,8 +40,7 @@ LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
|
||||
receiver_(receiver),
|
||||
initial_holder_(holder),
|
||||
// kMaxUInt32 isn't a valid index.
|
||||
index_(kMaxUInt32),
|
||||
number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
|
||||
index_(kMaxUInt32) {
|
||||
#ifdef DEBUG
|
||||
uint32_t index; // Assert that the name is not an array index.
|
||||
DCHECK(!name->AsArrayIndex(&index));
|
||||
@ -141,10 +140,10 @@ InternalIndex LookupIterator::descriptor_number() const {
|
||||
DCHECK(!IsElement());
|
||||
DCHECK(has_property_);
|
||||
DCHECK(holder_->HasFastProperties(isolate_));
|
||||
return InternalIndex(number_);
|
||||
return number_;
|
||||
}
|
||||
|
||||
int LookupIterator::dictionary_entry() const {
|
||||
InternalIndex LookupIterator::dictionary_entry() const {
|
||||
DCHECK(!IsElement());
|
||||
DCHECK(has_property_);
|
||||
DCHECK(!holder_->HasFastProperties(isolate_));
|
||||
|
@ -95,8 +95,7 @@ LookupIterator::LookupIterator(Isolate* isolate, Handle<Object> receiver,
|
||||
transition_(transition_map),
|
||||
receiver_(receiver),
|
||||
initial_holder_(GetRoot(isolate, receiver)),
|
||||
index_(kMaxUInt32),
|
||||
number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
|
||||
index_(kMaxUInt32) {
|
||||
holder_ = initial_holder_;
|
||||
}
|
||||
|
||||
@ -164,7 +163,7 @@ template <bool is_element>
|
||||
void LookupIterator::RestartInternal(InterceptorState interceptor_state) {
|
||||
interceptor_state_ = interceptor_state;
|
||||
property_details_ = PropertyDetails::Empty();
|
||||
number_ = static_cast<uint32_t>(DescriptorArray::kNotFound);
|
||||
number_ = InternalIndex::NotFound();
|
||||
Start<is_element>();
|
||||
}
|
||||
|
||||
@ -534,7 +533,7 @@ void LookupIterator::ReconfigureDataProperty(Handle<Object> value,
|
||||
DCHECK(attributes != NONE || !holder_obj->HasFastElements(isolate_));
|
||||
Handle<FixedArrayBase> elements(holder_obj->elements(isolate_), isolate());
|
||||
holder_obj->GetElementsAccessor(isolate_)->Reconfigure(
|
||||
holder_obj, elements, InternalIndex(number_), value, attributes);
|
||||
holder_obj, elements, number_, value, attributes);
|
||||
ReloadPropertyInformation<true>();
|
||||
} else if (holder_obj->HasFastProperties(isolate_)) {
|
||||
Handle<Map> old_map(holder_obj->map(isolate_), isolate_);
|
||||
@ -624,9 +623,8 @@ void LookupIterator::PrepareTransitionToDataProperty(
|
||||
if (map->IsJSGlobalObjectMap()) {
|
||||
// Install a property cell.
|
||||
Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(receiver);
|
||||
int entry;
|
||||
Handle<PropertyCell> cell = JSGlobalObject::EnsureEmptyPropertyCell(
|
||||
global, name(), PropertyCellType::kUninitialized, &entry);
|
||||
global, name(), PropertyCellType::kUninitialized, &number_);
|
||||
Handle<GlobalDictionary> dictionary(global->global_dictionary(isolate_),
|
||||
isolate_);
|
||||
DCHECK(cell->value(isolate_).IsTheHole(isolate_));
|
||||
@ -642,7 +640,6 @@ void LookupIterator::PrepareTransitionToDataProperty(
|
||||
PropertyCell::UpdatedType(isolate(), cell, value, property_details_);
|
||||
property_details_ = property_details_.set_cell_type(new_type);
|
||||
cell->set_property_details(property_details_);
|
||||
number_ = entry;
|
||||
has_property_ = true;
|
||||
} else {
|
||||
// Don't set enumeration index (it will be set during value store).
|
||||
@ -699,24 +696,22 @@ void LookupIterator::ApplyTransitionToDataProperty(
|
||||
}
|
||||
|
||||
if (simple_transition) {
|
||||
number_ = transition->LastAdded().as_uint32();
|
||||
number_ = transition->LastAdded();
|
||||
property_details_ = transition->GetLastDescriptorDetails(isolate_);
|
||||
state_ = DATA;
|
||||
} else if (receiver->map(isolate_).is_dictionary_map()) {
|
||||
Handle<NameDictionary> dictionary(receiver->property_dictionary(isolate_),
|
||||
isolate_);
|
||||
int entry;
|
||||
if (receiver->map(isolate_).is_prototype_map() &&
|
||||
receiver->IsJSObject(isolate_)) {
|
||||
JSObject::InvalidatePrototypeChains(receiver->map(isolate_));
|
||||
}
|
||||
dictionary = NameDictionary::Add(isolate(), dictionary, name(),
|
||||
isolate_->factory()->uninitialized_value(),
|
||||
property_details_, &entry);
|
||||
property_details_, &number_);
|
||||
receiver->SetProperties(*dictionary);
|
||||
// Reload details containing proper enumeration index value.
|
||||
property_details_ = dictionary->DetailsAt(entry);
|
||||
number_ = entry;
|
||||
property_details_ = dictionary->DetailsAt(number_);
|
||||
has_property_ = true;
|
||||
state_ = DATA;
|
||||
|
||||
@ -730,7 +725,7 @@ void LookupIterator::Delete() {
|
||||
if (IsElement()) {
|
||||
Handle<JSObject> object = Handle<JSObject>::cast(holder);
|
||||
ElementsAccessor* accessor = object->GetElementsAccessor(isolate_);
|
||||
accessor->Delete(object, InternalIndex(number_));
|
||||
accessor->Delete(object, number_);
|
||||
} else {
|
||||
DCHECK(!name()->IsPrivateName(isolate_));
|
||||
bool is_prototype_map = holder->map(isolate_).is_prototype_map();
|
||||
@ -747,7 +742,7 @@ void LookupIterator::Delete() {
|
||||
mode, 0, "DeletingProperty");
|
||||
ReloadPropertyInformation<false>();
|
||||
}
|
||||
JSReceiver::DeleteNormalizedProperty(holder, number_);
|
||||
JSReceiver::DeleteNormalizedProperty(holder, dictionary_entry());
|
||||
if (holder->IsJSObject(isolate_)) {
|
||||
JSObject::ReoptimizeIfPrototype(Handle<JSObject>::cast(holder));
|
||||
}
|
||||
@ -776,20 +771,18 @@ void LookupIterator::TransitionToAccessorProperty(
|
||||
} else if (state_ == INTERCEPTOR) {
|
||||
LookupInRegularHolder<false>(*old_map, *holder_);
|
||||
}
|
||||
// TODO(jkummerow): {IsFound()} should be enough once {number_} has type
|
||||
// {InternalIndex}.
|
||||
InternalIndex descriptor = (IsFound() && number_ != kMaxUInt32)
|
||||
? InternalIndex(number_)
|
||||
: InternalIndex::NotFound();
|
||||
// The case of IsFound() && number_.is_not_found() can occur for
|
||||
// interceptors.
|
||||
DCHECK_IMPLIES(!IsFound(), number_.is_not_found());
|
||||
|
||||
Handle<Map> new_map = Map::TransitionToAccessorProperty(
|
||||
isolate_, old_map, name_, descriptor, getter, setter, attributes);
|
||||
isolate_, old_map, name_, number_, getter, setter, attributes);
|
||||
bool simple_transition =
|
||||
new_map->GetBackPointer(isolate_) == receiver->map(isolate_);
|
||||
JSObject::MigrateToMap(isolate_, receiver, new_map);
|
||||
|
||||
if (simple_transition) {
|
||||
number_ = new_map->LastAdded().as_uint32();
|
||||
number_ = new_map->LastAdded();
|
||||
property_details_ = new_map->GetLastDescriptorDetails(isolate_);
|
||||
state_ = ACCESSOR;
|
||||
return;
|
||||
@ -845,8 +838,8 @@ void LookupIterator::TransitionToAccessorPair(Handle<Object> pair,
|
||||
if (receiver->HasSlowArgumentsElements(isolate_)) {
|
||||
FixedArray parameter_map = FixedArray::cast(receiver->elements(isolate_));
|
||||
uint32_t length = parameter_map.length() - 2;
|
||||
if (number_ < length) {
|
||||
parameter_map.set(number_ + 2,
|
||||
if (number_.is_found() && number_.as_uint32() < length) {
|
||||
parameter_map.set(number_.as_int() + 2,
|
||||
ReadOnlyRoots(isolate_).the_hole_value());
|
||||
}
|
||||
FixedArray::cast(receiver->elements(isolate_)).set(1, *dictionary);
|
||||
@ -895,10 +888,11 @@ Handle<Object> LookupIterator::FetchValue() const {
|
||||
if (IsElement()) {
|
||||
Handle<JSObject> holder = GetHolder<JSObject>();
|
||||
ElementsAccessor* accessor = holder->GetElementsAccessor(isolate_);
|
||||
return accessor->Get(holder, InternalIndex(number_));
|
||||
return accessor->Get(holder, number_);
|
||||
} else if (holder_->IsJSGlobalObject(isolate_)) {
|
||||
Handle<JSGlobalObject> holder = GetHolder<JSGlobalObject>();
|
||||
result = holder->global_dictionary(isolate_).ValueAt(isolate_, number_);
|
||||
result = holder->global_dictionary(isolate_).ValueAt(isolate_,
|
||||
dictionary_entry());
|
||||
} else if (!holder_->HasFastProperties(isolate_)) {
|
||||
result = holder_->property_dictionary(isolate_).ValueAt(isolate_,
|
||||
dictionary_entry());
|
||||
@ -1031,7 +1025,7 @@ void LookupIterator::WriteDataValue(Handle<Object> value,
|
||||
if (IsElement()) {
|
||||
Handle<JSObject> object = Handle<JSObject>::cast(holder);
|
||||
ElementsAccessor* accessor = object->GetElementsAccessor(isolate_);
|
||||
accessor->Set(object, InternalIndex(number_), *value);
|
||||
accessor->Set(object, number_, *value);
|
||||
} else if (holder->HasFastProperties(isolate_)) {
|
||||
if (property_details_.location() == kField) {
|
||||
// Check that in case of VariableMode::kConst field the existing value is
|
||||
@ -1129,9 +1123,8 @@ LookupIterator::State LookupIterator::LookupInSpecialHolder(
|
||||
if (!is_element && map.IsJSGlobalObjectMap()) {
|
||||
GlobalDictionary dict =
|
||||
JSGlobalObject::cast(holder).global_dictionary(isolate_);
|
||||
int number = dict.FindEntry(isolate(), name_);
|
||||
if (number == GlobalDictionary::kNotFound) return NOT_FOUND;
|
||||
number_ = static_cast<uint32_t>(number);
|
||||
number_ = dict.FindEntry(isolate(), name_);
|
||||
if (number_.is_not_found()) return NOT_FOUND;
|
||||
PropertyCell cell = dict.CellAt(isolate_, number_);
|
||||
if (cell.value(isolate_).IsTheHole(isolate_)) return NOT_FOUND;
|
||||
property_details_ = cell.property_details();
|
||||
@ -1167,15 +1160,13 @@ LookupIterator::State LookupIterator::LookupInRegularHolder(
|
||||
JSObject js_object = JSObject::cast(holder);
|
||||
ElementsAccessor* accessor = js_object.GetElementsAccessor(isolate_);
|
||||
FixedArrayBase backing_store = js_object.elements(isolate_);
|
||||
// TODO(jkummerow): {number_} should have type InternalIndex.
|
||||
InternalIndex entry =
|
||||
number_ =
|
||||
accessor->GetEntryForIndex(isolate_, js_object, backing_store, index_);
|
||||
number_ = entry.is_found() ? entry.as_uint32() : kMaxUInt32;
|
||||
if (number_ == kMaxUInt32) {
|
||||
if (number_.is_not_found()) {
|
||||
return holder.IsJSTypedArray(isolate_) ? INTEGER_INDEXED_EXOTIC
|
||||
: NOT_FOUND;
|
||||
}
|
||||
property_details_ = accessor->GetDetails(js_object, InternalIndex(number_));
|
||||
property_details_ = accessor->GetDetails(js_object, number_);
|
||||
if (map.has_frozen_elements()) {
|
||||
property_details_ = property_details_.CopyAddAttributes(FROZEN);
|
||||
} else if (map.has_sealed_elements()) {
|
||||
@ -1183,16 +1174,14 @@ LookupIterator::State LookupIterator::LookupInRegularHolder(
|
||||
}
|
||||
} else if (!map.is_dictionary_map()) {
|
||||
DescriptorArray descriptors = map.instance_descriptors(isolate_);
|
||||
InternalIndex number = descriptors.SearchWithCache(isolate_, *name_, map);
|
||||
if (number.is_not_found()) return NotFound(holder);
|
||||
number_ = number.as_uint32();
|
||||
property_details_ = descriptors.GetDetails(InternalIndex(number_));
|
||||
number_ = descriptors.SearchWithCache(isolate_, *name_, map);
|
||||
if (number_.is_not_found()) return NotFound(holder);
|
||||
property_details_ = descriptors.GetDetails(number_);
|
||||
} else {
|
||||
DCHECK_IMPLIES(holder.IsJSProxy(isolate_), name()->IsPrivate(isolate_));
|
||||
NameDictionary dict = holder.property_dictionary(isolate_);
|
||||
int number = dict.FindEntry(isolate(), name_);
|
||||
if (number == NameDictionary::kNotFound) return NotFound(holder);
|
||||
number_ = static_cast<uint32_t>(number);
|
||||
number_ = dict.FindEntry(isolate(), name_);
|
||||
if (number_.is_not_found()) return NotFound(holder);
|
||||
property_details_ = dict.DetailsAt(number_);
|
||||
}
|
||||
has_property_ = true;
|
||||
|
@ -69,8 +69,7 @@ class V8_EXPORT_PRIVATE LookupIterator final {
|
||||
isolate_(isolate),
|
||||
receiver_(receiver),
|
||||
initial_holder_(holder),
|
||||
index_(index),
|
||||
number_(static_cast<uint32_t>(DescriptorArray::kNotFound)) {
|
||||
index_(index) {
|
||||
// kMaxUInt32 isn't a valid index.
|
||||
DCHECK_NE(kMaxUInt32, index_);
|
||||
Start<true>();
|
||||
@ -242,7 +241,7 @@ class V8_EXPORT_PRIVATE LookupIterator final {
|
||||
return (configuration_ & kInterceptor) != 0;
|
||||
}
|
||||
inline InternalIndex descriptor_number() const;
|
||||
inline int dictionary_entry() const;
|
||||
inline InternalIndex dictionary_entry() const;
|
||||
|
||||
static inline Configuration ComputeConfiguration(Isolate* isolate,
|
||||
Configuration configuration,
|
||||
@ -270,7 +269,7 @@ class V8_EXPORT_PRIVATE LookupIterator final {
|
||||
Handle<JSReceiver> holder_;
|
||||
const Handle<JSReceiver> initial_holder_;
|
||||
const uint32_t index_;
|
||||
uint32_t number_;
|
||||
InternalIndex number_ = InternalIndex::NotFound();
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -303,7 +303,7 @@ Handle<JSModuleNamespace> Module::GetModuleNamespace(Isolate* isolate,
|
||||
Handle<ObjectHashTable> exports(module->exports(), isolate);
|
||||
ZoneVector<Handle<String>> names(&zone);
|
||||
names.reserve(exports->NumberOfElements());
|
||||
for (int i = 0, n = exports->Capacity(); i < n; ++i) {
|
||||
for (InternalIndex i : exports->IterateEntries()) {
|
||||
Object key;
|
||||
if (!exports->ToKey(roots, i, &key)) continue;
|
||||
names.push_back(handle(String::cast(key), isolate));
|
||||
|
@ -1106,11 +1106,10 @@ class EphemeronHashTable::BodyDescriptor final : public BodyDescriptorBase {
|
||||
EphemeronHashTable::kElementsStartIndex * kTaggedSize;
|
||||
IteratePointers(obj, EphemeronHashTable::kHeaderSize, entries_start, v);
|
||||
EphemeronHashTable table = EphemeronHashTable::unchecked_cast(obj);
|
||||
int entries = table.Capacity();
|
||||
for (int i = 0; i < entries; ++i) {
|
||||
for (InternalIndex i : table.IterateEntries()) {
|
||||
const int key_index = EphemeronHashTable::EntryToIndex(i);
|
||||
const int value_index = EphemeronHashTable::EntryToValueIndex(i);
|
||||
IterateEphemeron(obj, i, OffsetOfElementAt(key_index),
|
||||
IterateEphemeron(obj, i.as_int(), OffsetOfElementAt(key_index),
|
||||
OffsetOfElementAt(value_index), v);
|
||||
}
|
||||
}
|
||||
|
@ -5678,8 +5678,7 @@ void Dictionary<Derived, Shape>::Print(std::ostream& os) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
ReadOnlyRoots roots = this->GetReadOnlyRoots();
|
||||
Derived dictionary = Derived::cast(*this);
|
||||
int capacity = dictionary.Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary.IterateEntries()) {
|
||||
Object k = dictionary.KeyAt(i);
|
||||
if (!dictionary.ToKey(roots, i, &k)) continue;
|
||||
os << "\n ";
|
||||
@ -6442,7 +6441,7 @@ template <typename Derived, typename Shape>
|
||||
Handle<Derived> HashTable<Derived, Shape>::NewInternal(
|
||||
Isolate* isolate, int capacity, AllocationType allocation) {
|
||||
Factory* factory = isolate->factory();
|
||||
int length = EntryToIndex(capacity);
|
||||
int length = EntryToIndex(InternalIndex(capacity));
|
||||
RootIndex map_root_index = Shape::GetMapRootIndex();
|
||||
Handle<FixedArray> array =
|
||||
factory->NewFixedArrayWithMap(map_root_index, length, allocation);
|
||||
@ -6467,8 +6466,7 @@ void HashTable<Derived, Shape>::Rehash(ReadOnlyRoots roots, Derived new_table) {
|
||||
}
|
||||
|
||||
// Rehash the elements.
|
||||
int capacity = this->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : this->IterateEntries()) {
|
||||
uint32_t from_index = EntryToIndex(i);
|
||||
Object k = this->get(from_index);
|
||||
if (!Shape::IsLive(roots, k)) continue;
|
||||
@ -6484,12 +6482,12 @@ void HashTable<Derived, Shape>::Rehash(ReadOnlyRoots roots, Derived new_table) {
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
uint32_t HashTable<Derived, Shape>::EntryForProbe(ReadOnlyRoots roots, Object k,
|
||||
int probe,
|
||||
uint32_t expected) {
|
||||
InternalIndex HashTable<Derived, Shape>::EntryForProbe(ReadOnlyRoots roots,
|
||||
Object k, int probe,
|
||||
InternalIndex expected) {
|
||||
uint32_t hash = Shape::HashForObject(roots, k);
|
||||
uint32_t capacity = this->Capacity();
|
||||
uint32_t entry = FirstProbe(hash, capacity);
|
||||
InternalIndex entry = FirstProbe(hash, capacity);
|
||||
for (int i = 1; i < probe; i++) {
|
||||
if (entry == expected) return expected;
|
||||
entry = NextProbe(entry, i, capacity);
|
||||
@ -6498,7 +6496,7 @@ uint32_t HashTable<Derived, Shape>::EntryForProbe(ReadOnlyRoots roots, Object k,
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
void HashTable<Derived, Shape>::Swap(uint32_t entry1, uint32_t entry2,
|
||||
void HashTable<Derived, Shape>::Swap(InternalIndex entry1, InternalIndex entry2,
|
||||
WriteBarrierMode mode) {
|
||||
int index1 = EntryToIndex(entry1);
|
||||
int index2 = EntryToIndex(entry2);
|
||||
@ -6527,22 +6525,30 @@ void HashTable<Derived, Shape>::Rehash(ReadOnlyRoots roots) {
|
||||
// All elements at entries given by one of the first _probe_ probes
|
||||
// are placed correctly. Other elements might need to be moved.
|
||||
done = true;
|
||||
for (uint32_t current = 0; current < capacity; current++) {
|
||||
for (InternalIndex current(0); current.raw_value() < capacity;
|
||||
/* {current} is advanced manually below, when appropriate.*/) {
|
||||
Object current_key = KeyAt(current);
|
||||
if (!Shape::IsLive(roots, current_key)) continue;
|
||||
uint32_t target = EntryForProbe(roots, current_key, probe, current);
|
||||
if (current == target) continue;
|
||||
if (!Shape::IsLive(roots, current_key)) {
|
||||
++current; // Advance to next entry.
|
||||
continue;
|
||||
}
|
||||
InternalIndex target = EntryForProbe(roots, current_key, probe, current);
|
||||
if (current == target) {
|
||||
++current; // Advance to next entry.
|
||||
continue;
|
||||
}
|
||||
Object target_key = KeyAt(target);
|
||||
if (!Shape::IsLive(roots, target_key) ||
|
||||
EntryForProbe(roots, target_key, probe, target) != target) {
|
||||
// Put the current element into the correct position.
|
||||
Swap(current, target, mode);
|
||||
// The other element will be processed on the next iteration.
|
||||
current--;
|
||||
// The other element will be processed on the next iteration,
|
||||
// so don't advance {current} here!
|
||||
} else {
|
||||
// The place for the current element is occupied. Leave the element
|
||||
// for the next probe.
|
||||
done = false;
|
||||
++current; // Advance to next entry.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6550,7 +6556,7 @@ void HashTable<Derived, Shape>::Rehash(ReadOnlyRoots roots) {
|
||||
Object the_hole = roots.the_hole_value();
|
||||
HeapObject undefined = roots.undefined_value();
|
||||
Derived* self = static_cast<Derived*>(this);
|
||||
for (uint32_t current = 0; current < capacity; current++) {
|
||||
for (InternalIndex current : InternalIndex::Range(capacity)) {
|
||||
if (KeyAt(current) == the_hole) {
|
||||
self->set_key(EntryToIndex(current) + kEntryKeyIndex, undefined,
|
||||
SKIP_WRITE_BARRIER);
|
||||
@ -6630,9 +6636,9 @@ Handle<Derived> HashTable<Derived, Shape>::Shrink(Isolate* isolate,
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
uint32_t HashTable<Derived, Shape>::FindInsertionEntry(uint32_t hash) {
|
||||
InternalIndex HashTable<Derived, Shape>::FindInsertionEntry(uint32_t hash) {
|
||||
uint32_t capacity = Capacity();
|
||||
uint32_t entry = FirstProbe(hash, capacity);
|
||||
InternalIndex entry = FirstProbe(hash, capacity);
|
||||
uint32_t count = 1;
|
||||
// EnsureCapacity will guarantee the hash table is never full.
|
||||
ReadOnlyRoots roots = GetReadOnlyRoots();
|
||||
@ -6690,10 +6696,10 @@ Handle<String> StringTable::LookupString(Isolate* isolate,
|
||||
template <typename StringTableKey>
|
||||
Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {
|
||||
Handle<StringTable> table = isolate->factory()->string_table();
|
||||
int entry = table->FindEntry(isolate, key);
|
||||
InternalIndex entry = table->FindEntry(isolate, key);
|
||||
|
||||
// String already in table.
|
||||
if (entry != kNotFound) {
|
||||
if (entry.is_found()) {
|
||||
return handle(String::cast(table->KeyAt(entry)), isolate);
|
||||
}
|
||||
|
||||
@ -6724,10 +6730,10 @@ Handle<String> StringTable::AddKeyNoResize(Isolate* isolate,
|
||||
// InvalidStringLength error.
|
||||
CHECK(!string.is_null());
|
||||
DCHECK(string->HasHashCode());
|
||||
DCHECK_EQ(table->FindEntry(isolate, key), kNotFound);
|
||||
DCHECK(table->FindEntry(isolate, key).is_not_found());
|
||||
|
||||
// Add the new string and return it along with the string table.
|
||||
int entry = table->FindInsertionEntry(key->hash());
|
||||
InternalIndex entry = table->FindInsertionEntry(key->hash());
|
||||
table->set(EntryToIndex(entry), *string);
|
||||
table->ElementAdded();
|
||||
|
||||
@ -6783,8 +6789,9 @@ Address LookupString(Isolate* isolate, String string, String source,
|
||||
return Smi::FromInt(ResultSentinel::kUnsupported).ptr();
|
||||
}
|
||||
|
||||
int entry = table.FindEntry(ReadOnlyRoots(isolate), &key, key.hash());
|
||||
if (entry == kNotFound) {
|
||||
InternalIndex entry =
|
||||
table.FindEntry(ReadOnlyRoots(isolate), &key, key.hash());
|
||||
if (entry.is_not_found()) {
|
||||
// A string that's not an array index, and not in the string table,
|
||||
// cannot have been used as a property name before.
|
||||
return Smi::FromInt(ResultSentinel::kNotFound).ptr();
|
||||
@ -6842,7 +6849,7 @@ Handle<StringSet> StringSet::Add(Isolate* isolate, Handle<StringSet> stringset,
|
||||
if (!stringset->Has(isolate, name)) {
|
||||
stringset = EnsureCapacity(isolate, stringset, 1);
|
||||
uint32_t hash = ShapeT::Hash(isolate, *name);
|
||||
int entry = stringset->FindInsertionEntry(hash);
|
||||
InternalIndex entry = stringset->FindInsertionEntry(hash);
|
||||
stringset->set(EntryToIndex(entry), *name);
|
||||
stringset->ElementAdded();
|
||||
}
|
||||
@ -6850,7 +6857,7 @@ Handle<StringSet> StringSet::Add(Isolate* isolate, Handle<StringSet> stringset,
|
||||
}
|
||||
|
||||
bool StringSet::Has(Isolate* isolate, Handle<String> name) {
|
||||
return FindEntry(isolate, *name) != kNotFound;
|
||||
return FindEntry(isolate, *name).is_found();
|
||||
}
|
||||
|
||||
Handle<ObjectHashSet> ObjectHashSet::Add(Isolate* isolate,
|
||||
@ -6859,7 +6866,7 @@ Handle<ObjectHashSet> ObjectHashSet::Add(Isolate* isolate,
|
||||
int32_t hash = key->GetOrCreateHash(isolate).value();
|
||||
if (!set->Has(isolate, key, hash)) {
|
||||
set = EnsureCapacity(isolate, set, 1);
|
||||
int entry = set->FindInsertionEntry(hash);
|
||||
InternalIndex entry = set->FindInsertionEntry(hash);
|
||||
set->set(EntryToIndex(entry), *key);
|
||||
set->ElementAdded();
|
||||
}
|
||||
@ -6996,8 +7003,8 @@ MaybeHandle<SharedFunctionInfo> CompilationCacheTable::LookupScript(
|
||||
Isolate* isolate = native_context->GetIsolate();
|
||||
src = String::Flatten(isolate, src);
|
||||
StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
|
||||
int entry = table->FindEntry(isolate, &key);
|
||||
if (entry == kNotFound) return MaybeHandle<SharedFunctionInfo>();
|
||||
InternalIndex entry = table->FindEntry(isolate, &key);
|
||||
if (entry.is_not_found()) return MaybeHandle<SharedFunctionInfo>();
|
||||
int index = EntryToIndex(entry);
|
||||
if (!table->get(index).IsFixedArray()) {
|
||||
return MaybeHandle<SharedFunctionInfo>();
|
||||
@ -7017,14 +7024,14 @@ InfoCellPair CompilationCacheTable::LookupEval(
|
||||
Isolate* isolate = native_context->GetIsolate();
|
||||
src = String::Flatten(isolate, src);
|
||||
StringSharedKey key(src, outer_info, language_mode, position);
|
||||
int entry = table->FindEntry(isolate, &key);
|
||||
if (entry == kNotFound) return empty_result;
|
||||
InternalIndex entry = table->FindEntry(isolate, &key);
|
||||
if (entry.is_not_found()) return empty_result;
|
||||
int index = EntryToIndex(entry);
|
||||
if (!table->get(index).IsFixedArray()) return empty_result;
|
||||
Object obj = table->get(EntryToIndex(entry) + 1);
|
||||
Object obj = table->get(index + 1);
|
||||
if (obj.IsSharedFunctionInfo()) {
|
||||
FeedbackCell feedback_cell =
|
||||
SearchLiteralsMap(*table, EntryToIndex(entry) + 2, *native_context);
|
||||
SearchLiteralsMap(*table, index + 2, *native_context);
|
||||
return InfoCellPair(SharedFunctionInfo::cast(obj), feedback_cell);
|
||||
}
|
||||
return empty_result;
|
||||
@ -7035,8 +7042,8 @@ Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
|
||||
Isolate* isolate = GetIsolate();
|
||||
DisallowHeapAllocation no_allocation;
|
||||
RegExpKey key(src, flags);
|
||||
int entry = FindEntry(isolate, &key);
|
||||
if (entry == kNotFound) return isolate->factory()->undefined_value();
|
||||
InternalIndex entry = FindEntry(isolate, &key);
|
||||
if (entry.is_not_found()) return isolate->factory()->undefined_value();
|
||||
return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
|
||||
}
|
||||
|
||||
@ -7055,7 +7062,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
|
||||
StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
|
||||
Handle<Object> k = key.AsHandle(isolate);
|
||||
cache = EnsureCapacity(isolate, cache, 1);
|
||||
int entry = cache->FindInsertionEntry(key.Hash());
|
||||
InternalIndex entry = cache->FindInsertionEntry(key.Hash());
|
||||
cache->set(EntryToIndex(entry), *k);
|
||||
cache->set(EntryToIndex(entry) + 1, *value);
|
||||
cache->ElementAdded();
|
||||
@ -7072,8 +7079,8 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
|
||||
StringSharedKey key(src, outer_info, value->language_mode(), position);
|
||||
{
|
||||
Handle<Object> k = key.AsHandle(isolate);
|
||||
int entry = cache->FindEntry(isolate, &key);
|
||||
if (entry != kNotFound) {
|
||||
InternalIndex entry = cache->FindEntry(isolate, &key);
|
||||
if (entry.is_found()) {
|
||||
cache->set(EntryToIndex(entry), *k);
|
||||
cache->set(EntryToIndex(entry) + 1, *value);
|
||||
// AddToFeedbackCellsMap may allocate a new sub-array to live in the
|
||||
@ -7087,7 +7094,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
|
||||
}
|
||||
|
||||
cache = EnsureCapacity(isolate, cache, 1);
|
||||
int entry = cache->FindInsertionEntry(key.Hash());
|
||||
InternalIndex entry = cache->FindInsertionEntry(key.Hash());
|
||||
Handle<Object> k =
|
||||
isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
|
||||
cache->set(EntryToIndex(entry), *k);
|
||||
@ -7101,7 +7108,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
|
||||
JSRegExp::Flags flags, Handle<FixedArray> value) {
|
||||
RegExpKey key(src, flags);
|
||||
cache = EnsureCapacity(isolate, cache, 1);
|
||||
int entry = cache->FindInsertionEntry(key.Hash());
|
||||
InternalIndex entry = cache->FindInsertionEntry(key.Hash());
|
||||
// We store the value in the key slot, and compare the search key
|
||||
// to the stored value with a custon IsMatch function during lookups.
|
||||
cache->set(EntryToIndex(entry), *value);
|
||||
@ -7113,7 +7120,7 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
|
||||
void CompilationCacheTable::Age() {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
Object the_hole_value = GetReadOnlyRoots().the_hole_value();
|
||||
for (int entry = 0, size = Capacity(); entry < size; entry++) {
|
||||
for (InternalIndex entry : IterateEntries()) {
|
||||
int entry_index = EntryToIndex(entry);
|
||||
int value_index = entry_index + 1;
|
||||
|
||||
@ -7142,7 +7149,7 @@ void CompilationCacheTable::Age() {
|
||||
void CompilationCacheTable::Remove(Object value) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
Object the_hole_value = GetReadOnlyRoots().the_hole_value();
|
||||
for (int entry = 0, size = Capacity(); entry < size; entry++) {
|
||||
for (InternalIndex entry : IterateEntries()) {
|
||||
int entry_index = EntryToIndex(entry);
|
||||
int value_index = entry_index + 1;
|
||||
if (get(value_index) == value) {
|
||||
@ -7180,7 +7187,7 @@ Handle<Derived> BaseNameDictionary<Derived, Shape>::EnsureCapacity(
|
||||
// Iterate over the dictionary using the enumeration order and update
|
||||
// the dictionary with new enumeration indices.
|
||||
for (int i = 0; i < length; i++) {
|
||||
int index = Smi::ToInt(iteration_order->get(i));
|
||||
InternalIndex index(Smi::ToInt(iteration_order->get(i)));
|
||||
DCHECK(dictionary->IsKey(dictionary->GetReadOnlyRoots(),
|
||||
dictionary->KeyAt(index)));
|
||||
|
||||
@ -7200,7 +7207,7 @@ Handle<Derived> BaseNameDictionary<Derived, Shape>::EnsureCapacity(
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
Handle<Derived> Dictionary<Derived, Shape>::DeleteEntry(
|
||||
Isolate* isolate, Handle<Derived> dictionary, int entry) {
|
||||
Isolate* isolate, Handle<Derived> dictionary, InternalIndex entry) {
|
||||
DCHECK(Shape::kEntrySize != 3 ||
|
||||
dictionary->DetailsAt(entry).IsConfigurable());
|
||||
dictionary->ClearEntry(isolate, entry);
|
||||
@ -7213,10 +7220,10 @@ Handle<Derived> Dictionary<Derived, Shape>::AtPut(Isolate* isolate,
|
||||
Handle<Derived> dictionary,
|
||||
Key key, Handle<Object> value,
|
||||
PropertyDetails details) {
|
||||
int entry = dictionary->FindEntry(isolate, key);
|
||||
InternalIndex entry = dictionary->FindEntry(isolate, key);
|
||||
|
||||
// If the entry is present set the value;
|
||||
if (entry == Dictionary::kNotFound) {
|
||||
if (entry.is_not_found()) {
|
||||
return Derived::Add(isolate, dictionary, key, value, details);
|
||||
}
|
||||
|
||||
@ -7230,8 +7237,8 @@ template <typename Derived, typename Shape>
|
||||
Handle<Derived>
|
||||
BaseNameDictionary<Derived, Shape>::AddNoUpdateNextEnumerationIndex(
|
||||
Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
|
||||
PropertyDetails details, int* entry_out) {
|
||||
// Insert element at empty or deleted entry
|
||||
PropertyDetails details, InternalIndex* entry_out) {
|
||||
// Insert element at empty or deleted entry.
|
||||
return Dictionary<Derived, Shape>::Add(isolate, dictionary, key, value,
|
||||
details, entry_out);
|
||||
}
|
||||
@ -7239,7 +7246,7 @@ BaseNameDictionary<Derived, Shape>::AddNoUpdateNextEnumerationIndex(
|
||||
template <typename Derived, typename Shape>
|
||||
Handle<Derived> BaseNameDictionary<Derived, Shape>::Add(
|
||||
Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
|
||||
PropertyDetails details, int* entry_out) {
|
||||
PropertyDetails details, InternalIndex* entry_out) {
|
||||
// Insert element at empty or deleted entry
|
||||
DCHECK_EQ(0, details.dictionary_index());
|
||||
// Assign an enumeration index to the property and update
|
||||
@ -7259,17 +7266,17 @@ Handle<Derived> Dictionary<Derived, Shape>::Add(Isolate* isolate,
|
||||
Handle<Derived> dictionary,
|
||||
Key key, Handle<Object> value,
|
||||
PropertyDetails details,
|
||||
int* entry_out) {
|
||||
InternalIndex* entry_out) {
|
||||
uint32_t hash = Shape::Hash(isolate, key);
|
||||
// Valdate key is absent.
|
||||
SLOW_DCHECK((dictionary->FindEntry(isolate, key) == Dictionary::kNotFound));
|
||||
// Validate that the key is absent.
|
||||
SLOW_DCHECK(dictionary->FindEntry(isolate, key).is_not_found());
|
||||
// Check whether the dictionary should be extended.
|
||||
dictionary = Derived::EnsureCapacity(isolate, dictionary, 1);
|
||||
|
||||
// Compute the key object.
|
||||
Handle<Object> k = Shape::AsHandle(isolate, key);
|
||||
|
||||
uint32_t entry = dictionary->FindInsertionEntry(hash);
|
||||
InternalIndex entry = dictionary->FindInsertionEntry(hash);
|
||||
dictionary->SetEntry(isolate, entry, *k, *value, details);
|
||||
DCHECK(dictionary->KeyAt(entry).IsNumber() ||
|
||||
Shape::Unwrap(dictionary->KeyAt(entry)).IsUniqueName());
|
||||
@ -7324,10 +7331,9 @@ Handle<NumberDictionary> NumberDictionary::Set(
|
||||
void NumberDictionary::CopyValuesTo(FixedArray elements) {
|
||||
ReadOnlyRoots roots = GetReadOnlyRoots();
|
||||
int pos = 0;
|
||||
int capacity = this->Capacity();
|
||||
DisallowHeapAllocation no_gc;
|
||||
WriteBarrierMode mode = elements.GetWriteBarrierMode(no_gc);
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : this->IterateEntries()) {
|
||||
Object k;
|
||||
if (this->ToKey(roots, i, &k)) {
|
||||
elements.set(pos++, this->ValueAt(i), mode);
|
||||
@ -7339,9 +7345,8 @@ void NumberDictionary::CopyValuesTo(FixedArray elements) {
|
||||
template <typename Derived, typename Shape>
|
||||
int Dictionary<Derived, Shape>::NumberOfEnumerableProperties() {
|
||||
ReadOnlyRoots roots = this->GetReadOnlyRoots();
|
||||
int capacity = this->Capacity();
|
||||
int result = 0;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : this->IterateEntries()) {
|
||||
Object k;
|
||||
if (!this->ToKey(roots, i, &k)) continue;
|
||||
if (k.FilterKey(ENUMERABLE_STRINGS)) continue;
|
||||
@ -7356,8 +7361,10 @@ template <typename Dictionary>
|
||||
struct EnumIndexComparator {
|
||||
explicit EnumIndexComparator(Dictionary dict) : dict(dict) {}
|
||||
bool operator()(Tagged_t a, Tagged_t b) {
|
||||
PropertyDetails da(dict.DetailsAt(Smi(static_cast<Address>(a)).value()));
|
||||
PropertyDetails db(dict.DetailsAt(Smi(static_cast<Address>(b)).value()));
|
||||
PropertyDetails da(
|
||||
dict.DetailsAt(InternalIndex(Smi(static_cast<Address>(a)).value())));
|
||||
PropertyDetails db(
|
||||
dict.DetailsAt(InternalIndex(Smi(static_cast<Address>(b)).value())));
|
||||
return da.dictionary_index() < db.dictionary_index();
|
||||
}
|
||||
Dictionary dict;
|
||||
@ -7369,10 +7376,9 @@ void BaseNameDictionary<Derived, Shape>::CopyEnumKeysTo(
|
||||
KeyCollectionMode mode, KeyAccumulator* accumulator) {
|
||||
DCHECK_IMPLIES(mode != KeyCollectionMode::kOwnOnly, accumulator != nullptr);
|
||||
int length = storage->length();
|
||||
int capacity = dictionary->Capacity();
|
||||
int properties = 0;
|
||||
ReadOnlyRoots roots(isolate);
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary->IterateEntries()) {
|
||||
Object key;
|
||||
if (!dictionary->ToKey(roots, i, &key)) continue;
|
||||
bool is_shadowing_key = false;
|
||||
@ -7389,7 +7395,7 @@ void BaseNameDictionary<Derived, Shape>::CopyEnumKeysTo(
|
||||
accumulator->AddShadowingKey(key);
|
||||
continue;
|
||||
} else {
|
||||
storage->set(properties, Smi::FromInt(i));
|
||||
storage->set(properties, Smi::FromInt(i.as_int()));
|
||||
}
|
||||
properties++;
|
||||
if (mode == KeyCollectionMode::kOwnOnly && properties == length) break;
|
||||
@ -7405,7 +7411,7 @@ void BaseNameDictionary<Derived, Shape>::CopyEnumKeysTo(
|
||||
AtomicSlot start(storage->GetFirstElementAddress());
|
||||
std::sort(start, start + length, cmp);
|
||||
for (int i = 0; i < length; i++) {
|
||||
int index = Smi::ToInt(raw_storage.get(i));
|
||||
InternalIndex index(Smi::ToInt(raw_storage.get(i)));
|
||||
raw_storage.set(i, raw_dictionary.NameAt(index));
|
||||
}
|
||||
}
|
||||
@ -7413,7 +7419,6 @@ void BaseNameDictionary<Derived, Shape>::CopyEnumKeysTo(
|
||||
template <typename Derived, typename Shape>
|
||||
Handle<FixedArray> BaseNameDictionary<Derived, Shape>::IterationIndices(
|
||||
Isolate* isolate, Handle<Derived> dictionary) {
|
||||
int capacity = dictionary->Capacity();
|
||||
int length = dictionary->NumberOfElements();
|
||||
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
|
||||
ReadOnlyRoots roots(isolate);
|
||||
@ -7421,10 +7426,10 @@ Handle<FixedArray> BaseNameDictionary<Derived, Shape>::IterationIndices(
|
||||
{
|
||||
DisallowHeapAllocation no_gc;
|
||||
Derived raw_dictionary = *dictionary;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary->IterateEntries()) {
|
||||
Object k;
|
||||
if (!raw_dictionary.ToKey(roots, i, &k)) continue;
|
||||
array->set(array_size++, Smi::FromInt(i));
|
||||
array->set(array_size++, Smi::FromInt(i.as_int()));
|
||||
}
|
||||
|
||||
DCHECK_EQ(array_size, length);
|
||||
@ -7443,7 +7448,7 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
|
||||
Handle<Derived> dictionary, KeyAccumulator* keys) {
|
||||
Isolate* isolate = keys->isolate();
|
||||
ReadOnlyRoots roots(isolate);
|
||||
int capacity = dictionary->Capacity();
|
||||
// TODO(jkummerow): Consider using a std::unique_ptr<InternalIndex[]> instead.
|
||||
Handle<FixedArray> array =
|
||||
isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
|
||||
int array_size = 0;
|
||||
@ -7451,7 +7456,7 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
|
||||
{
|
||||
DisallowHeapAllocation no_gc;
|
||||
Derived raw_dictionary = *dictionary;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary->IterateEntries()) {
|
||||
Object k;
|
||||
if (!raw_dictionary.ToKey(roots, i, &k)) continue;
|
||||
if (k.FilterKey(filter)) continue;
|
||||
@ -7466,7 +7471,7 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
|
||||
if (!accessors.IsAccessorInfo()) continue;
|
||||
if (!AccessorInfo::cast(accessors).all_can_read()) continue;
|
||||
}
|
||||
array->set(array_size++, Smi::FromInt(i));
|
||||
array->set(array_size++, Smi::FromInt(i.as_int()));
|
||||
}
|
||||
|
||||
EnumIndexComparator<Derived> cmp(raw_dictionary);
|
||||
@ -7478,7 +7483,7 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
|
||||
|
||||
bool has_seen_symbol = false;
|
||||
for (int i = 0; i < array_size; i++) {
|
||||
int index = Smi::ToInt(array->get(i));
|
||||
InternalIndex index(Smi::ToInt(array->get(i)));
|
||||
Object key = dictionary->NameAt(index);
|
||||
if (key.IsSymbol()) {
|
||||
has_seen_symbol = true;
|
||||
@ -7489,7 +7494,7 @@ ExceptionStatus BaseNameDictionary<Derived, Shape>::CollectKeysTo(
|
||||
}
|
||||
if (has_seen_symbol) {
|
||||
for (int i = 0; i < array_size; i++) {
|
||||
int index = Smi::ToInt(array->get(i));
|
||||
InternalIndex index(Smi::ToInt(array->get(i)));
|
||||
Object key = dictionary->NameAt(index);
|
||||
if (!key.IsSymbol()) continue;
|
||||
ExceptionStatus status = keys->AddKey(key, DO_NOT_CONVERT);
|
||||
@ -7504,8 +7509,7 @@ template <typename Derived, typename Shape>
|
||||
Object Dictionary<Derived, Shape>::SlowReverseLookup(Object value) {
|
||||
Derived dictionary = Derived::cast(*this);
|
||||
ReadOnlyRoots roots = dictionary.GetReadOnlyRoots();
|
||||
int capacity = dictionary.Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary.IterateEntries()) {
|
||||
Object k;
|
||||
if (!dictionary.ToKey(roots, i, &k)) continue;
|
||||
Object e = dictionary.ValueAt(i);
|
||||
@ -7518,7 +7522,7 @@ template <typename Derived, typename Shape>
|
||||
void ObjectHashTableBase<Derived, Shape>::FillEntriesWithHoles(
|
||||
Handle<Derived> table) {
|
||||
int length = table->length();
|
||||
for (int i = Derived::EntryToIndex(0); i < length; i++) {
|
||||
for (int i = Derived::EntryToIndex(InternalIndex(0)); i < length; i++) {
|
||||
table->set_the_hole(i);
|
||||
}
|
||||
}
|
||||
@ -7530,8 +7534,8 @@ Object ObjectHashTableBase<Derived, Shape>::Lookup(ReadOnlyRoots roots,
|
||||
DisallowHeapAllocation no_gc;
|
||||
DCHECK(this->IsKey(roots, *key));
|
||||
|
||||
int entry = this->FindEntry(roots, key, hash);
|
||||
if (entry == kNotFound) return roots.the_hole_value();
|
||||
InternalIndex entry = this->FindEntry(roots, key, hash);
|
||||
if (entry.is_not_found()) return roots.the_hole_value();
|
||||
return this->get(Derived::EntryToIndex(entry) + 1);
|
||||
}
|
||||
|
||||
@ -7557,7 +7561,7 @@ Object ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key,
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
Object ObjectHashTableBase<Derived, Shape>::ValueAt(int entry) {
|
||||
Object ObjectHashTableBase<Derived, Shape>::ValueAt(InternalIndex entry) {
|
||||
return this->get(EntryToValueIndex(entry));
|
||||
}
|
||||
|
||||
@ -7586,10 +7590,10 @@ Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Isolate* isolate,
|
||||
DCHECK(table->IsKey(roots, *key));
|
||||
DCHECK(!value->IsTheHole(roots));
|
||||
|
||||
int entry = table->FindEntry(roots, key, hash);
|
||||
InternalIndex entry = table->FindEntry(roots, key, hash);
|
||||
|
||||
// Key is already in table, just overwrite value.
|
||||
if (entry != kNotFound) {
|
||||
if (entry.is_found()) {
|
||||
table->set(Derived::EntryToValueIndex(entry), *value);
|
||||
return table;
|
||||
}
|
||||
@ -7641,8 +7645,8 @@ Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
|
||||
ReadOnlyRoots roots = table->GetReadOnlyRoots();
|
||||
DCHECK(table->IsKey(roots, *key));
|
||||
|
||||
int entry = table->FindEntry(roots, key, hash);
|
||||
if (entry == kNotFound) {
|
||||
InternalIndex entry = table->FindEntry(roots, key, hash);
|
||||
if (entry.is_not_found()) {
|
||||
*was_present = false;
|
||||
return table;
|
||||
}
|
||||
@ -7653,8 +7657,8 @@ Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
void ObjectHashTableBase<Derived, Shape>::AddEntry(int entry, Object key,
|
||||
Object value) {
|
||||
void ObjectHashTableBase<Derived, Shape>::AddEntry(InternalIndex entry,
|
||||
Object key, Object value) {
|
||||
Derived* self = static_cast<Derived*>(this);
|
||||
self->set_key(Derived::EntryToIndex(entry), key);
|
||||
self->set(Derived::EntryToValueIndex(entry), value);
|
||||
@ -7662,7 +7666,7 @@ void ObjectHashTableBase<Derived, Shape>::AddEntry(int entry, Object key,
|
||||
}
|
||||
|
||||
template <typename Derived, typename Shape>
|
||||
void ObjectHashTableBase<Derived, Shape>::RemoveEntry(int entry) {
|
||||
void ObjectHashTableBase<Derived, Shape>::RemoveEntry(InternalIndex entry) {
|
||||
this->set_the_hole(Derived::EntryToIndex(entry));
|
||||
this->set_the_hole(Derived::EntryToValueIndex(entry));
|
||||
this->ElementRemoved();
|
||||
@ -7754,7 +7758,7 @@ Handle<JSArray> JSWeakCollection::GetEntries(Handle<JSWeakCollection> holder,
|
||||
for (int i = 0;
|
||||
count / values_per_entry < max_entries && i < table->Capacity(); i++) {
|
||||
Object key;
|
||||
if (table->ToKey(roots, i, &key)) {
|
||||
if (table->ToKey(roots, InternalIndex(i), &key)) {
|
||||
entries->set(count++, key);
|
||||
if (values_per_entry > 1) {
|
||||
Object value = table->Lookup(handle(key, isolate));
|
||||
@ -7768,7 +7772,8 @@ Handle<JSArray> JSWeakCollection::GetEntries(Handle<JSWeakCollection> holder,
|
||||
}
|
||||
|
||||
Handle<PropertyCell> PropertyCell::InvalidateEntry(
|
||||
Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry) {
|
||||
Isolate* isolate, Handle<GlobalDictionary> dictionary,
|
||||
InternalIndex entry) {
|
||||
// Swap with a copy.
|
||||
Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
|
||||
Handle<Name> name(cell->name(), isolate);
|
||||
@ -7848,7 +7853,7 @@ PropertyCellType PropertyCell::UpdatedType(Isolate* isolate,
|
||||
}
|
||||
|
||||
Handle<PropertyCell> PropertyCell::PrepareForValue(
|
||||
Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry,
|
||||
Isolate* isolate, Handle<GlobalDictionary> dictionary, InternalIndex entry,
|
||||
Handle<Object> value, PropertyDetails details) {
|
||||
DCHECK(!value->IsTheHole(isolate));
|
||||
Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
|
||||
|
@ -41,11 +41,12 @@ class PropertyCell : public HeapObject {
|
||||
// As a result the old cell could be invalidated and/or dependent code could
|
||||
// be deoptimized. Returns the prepared property cell.
|
||||
static Handle<PropertyCell> PrepareForValue(
|
||||
Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry,
|
||||
Handle<Object> value, PropertyDetails details);
|
||||
Isolate* isolate, Handle<GlobalDictionary> dictionary,
|
||||
InternalIndex entry, Handle<Object> value, PropertyDetails details);
|
||||
|
||||
static Handle<PropertyCell> InvalidateEntry(
|
||||
Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry);
|
||||
Isolate* isolate, Handle<GlobalDictionary> dictionary,
|
||||
InternalIndex entry);
|
||||
|
||||
static void SetValueWithInvalidation(Isolate* isolate, const char* cell_name,
|
||||
Handle<PropertyCell> cell,
|
||||
|
@ -536,7 +536,7 @@ void SourceTextModule::FetchStarExports(Isolate* isolate,
|
||||
// the name to undefined instead of a Cell.
|
||||
Handle<ObjectHashTable> requested_exports(requested_module->exports(),
|
||||
isolate);
|
||||
for (int i = 0, n = requested_exports->Capacity(); i < n; ++i) {
|
||||
for (InternalIndex i : requested_exports->IterateEntries()) {
|
||||
Object key;
|
||||
if (!requested_exports->ToKey(roots, i, &key)) continue;
|
||||
Handle<String> name(String::cast(key), isolate);
|
||||
|
@ -69,7 +69,7 @@ class StringTable : public HashTable<StringTable, StringTableShape> {
|
||||
static Handle<String> LookupKey(Isolate* isolate, StringTableKey* key);
|
||||
static Handle<String> AddKeyNoResize(Isolate* isolate, StringTableKey* key);
|
||||
|
||||
// Shink the StringTable if it's very empty (kMaxEmptyFactor) to avoid the
|
||||
// Shrink the StringTable if it's very empty (kMaxEmptyFactor) to avoid the
|
||||
// performance overhead of re-allocating the StringTable over and over again.
|
||||
static Handle<StringTable> CautiousShrink(Isolate* isolate,
|
||||
Handle<StringTable> table);
|
||||
|
@ -1814,8 +1814,8 @@ MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadTransferredJSArrayBuffer() {
|
||||
!array_buffer_transfer_map_.ToHandle(&transfer_map)) {
|
||||
return MaybeHandle<JSArrayBuffer>();
|
||||
}
|
||||
int index = transfer_map->FindEntry(isolate_, transfer_id);
|
||||
if (index == SimpleNumberDictionary::kNotFound) {
|
||||
InternalIndex index = transfer_map->FindEntry(isolate_, transfer_id);
|
||||
if (index.is_not_found()) {
|
||||
return MaybeHandle<JSArrayBuffer>();
|
||||
}
|
||||
Handle<JSArrayBuffer> array_buffer(
|
||||
|
@ -930,7 +930,7 @@ void V8HeapExplorer::ExtractJSWeakCollectionReferences(HeapEntry* entry,
|
||||
|
||||
void V8HeapExplorer::ExtractEphemeronHashTableReferences(
|
||||
HeapEntry* entry, EphemeronHashTable table) {
|
||||
for (int i = 0, capacity = table.Capacity(); i < capacity; ++i) {
|
||||
for (InternalIndex i : table.IterateEntries()) {
|
||||
int key_index = EphemeronHashTable::EntryToIndex(i) +
|
||||
EphemeronHashTable::kEntryKeyIndex;
|
||||
int value_index = EphemeronHashTable::EntryToValueIndex(i);
|
||||
@ -1333,9 +1333,8 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject js_obj,
|
||||
// We assume that global objects can only have slow properties.
|
||||
GlobalDictionary dictionary =
|
||||
JSGlobalObject::cast(js_obj).global_dictionary();
|
||||
int length = dictionary.Capacity();
|
||||
ReadOnlyRoots roots(isolate);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
for (InternalIndex i : dictionary.IterateEntries()) {
|
||||
if (!dictionary.IsKey(roots, dictionary.KeyAt(i))) continue;
|
||||
PropertyCell cell = dictionary.CellAt(i);
|
||||
Name name = cell.name();
|
||||
@ -1345,9 +1344,8 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject js_obj,
|
||||
}
|
||||
} else {
|
||||
NameDictionary dictionary = js_obj.property_dictionary();
|
||||
int length = dictionary.Capacity();
|
||||
ReadOnlyRoots roots(isolate);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
for (InternalIndex i : dictionary.IterateEntries()) {
|
||||
Object k = dictionary.KeyAt(i);
|
||||
if (!dictionary.IsKey(roots, k)) continue;
|
||||
Object value = dictionary.ValueAt(i);
|
||||
@ -1388,8 +1386,7 @@ void V8HeapExplorer::ExtractElementReferences(JSObject js_obj,
|
||||
}
|
||||
} else if (js_obj.HasDictionaryElements()) {
|
||||
NumberDictionary dictionary = js_obj.element_dictionary();
|
||||
int length = dictionary.Capacity();
|
||||
for (int i = 0; i < length; ++i) {
|
||||
for (InternalIndex i : dictionary.IterateEntries()) {
|
||||
Object k = dictionary.KeyAt(i);
|
||||
if (!dictionary.IsKey(roots, k)) continue;
|
||||
DCHECK(k.IsNumber());
|
||||
|
@ -215,8 +215,7 @@ Handle<Dictionary> ShallowCopyDictionaryTemplate(
|
||||
Handle<Dictionary>::cast(isolate->factory()->CopyFixedArrayWithMap(
|
||||
dictionary_template, dictionary_map));
|
||||
// Clone all AccessorPairs in the dictionary.
|
||||
int capacity = dictionary->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary->IterateEntries()) {
|
||||
Object value = dictionary->ValueAt(i);
|
||||
if (value.IsAccessorPair()) {
|
||||
Handle<AccessorPair> pair(AccessorPair::cast(value), isolate);
|
||||
@ -235,9 +234,8 @@ bool SubstituteValues(Isolate* isolate, Handle<Dictionary> dictionary,
|
||||
Handle<Name> name_string = isolate->factory()->name_string();
|
||||
|
||||
// Replace all indices with proper methods.
|
||||
int capacity = dictionary->Capacity();
|
||||
ReadOnlyRoots roots(isolate);
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dictionary->IterateEntries()) {
|
||||
Object maybe_key = dictionary->KeyAt(i);
|
||||
if (!Dictionary::IsKey(roots, maybe_key)) continue;
|
||||
if (install_name_accessor && *install_name_accessor &&
|
||||
|
@ -133,8 +133,7 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
||||
}
|
||||
} else {
|
||||
Handle<NameDictionary> dict(copy->property_dictionary(isolate), isolate);
|
||||
int capacity = dict->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : dict->IterateEntries()) {
|
||||
Object raw = dict->ValueAt(isolate, i);
|
||||
if (!raw.IsJSObject(isolate)) continue;
|
||||
DCHECK(dict->KeyAt(isolate, i).IsName());
|
||||
@ -183,8 +182,7 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
||||
case DICTIONARY_ELEMENTS: {
|
||||
Handle<NumberDictionary> element_dictionary(
|
||||
copy->element_dictionary(isolate), isolate);
|
||||
int capacity = element_dictionary->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
for (InternalIndex i : element_dictionary->IterateEntries()) {
|
||||
Object raw = element_dictionary->ValueAt(isolate, i);
|
||||
if (!raw.IsJSObject(isolate)) continue;
|
||||
Handle<JSObject> value(JSObject::cast(raw), isolate);
|
||||
|
@ -617,8 +617,8 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
|
||||
// Attempt dictionary lookup.
|
||||
GlobalDictionary dictionary =
|
||||
JSGlobalObject::cast(*receiver).global_dictionary();
|
||||
int entry = dictionary.FindEntry(isolate, key);
|
||||
if (entry != GlobalDictionary::kNotFound) {
|
||||
InternalIndex entry = dictionary.FindEntry(isolate, key);
|
||||
if (entry.is_found()) {
|
||||
PropertyCell cell = dictionary.CellAt(entry);
|
||||
if (cell.property_details().kind() == kData) {
|
||||
Object value = cell.value();
|
||||
@ -629,8 +629,8 @@ RUNTIME_FUNCTION(Runtime_GetProperty) {
|
||||
} else if (!receiver->HasFastProperties()) {
|
||||
// Attempt dictionary lookup.
|
||||
NameDictionary dictionary = receiver->property_dictionary();
|
||||
int entry = dictionary.FindEntry(isolate, key);
|
||||
if ((entry != NameDictionary::kNotFound) &&
|
||||
InternalIndex entry = dictionary.FindEntry(isolate, key);
|
||||
if ((entry.is_found()) &&
|
||||
(dictionary.DetailsAt(entry).kind() == kData)) {
|
||||
return dictionary.ValueAt(entry);
|
||||
}
|
||||
|
@ -191,8 +191,8 @@ namespace {
|
||||
|
||||
String ForwardStringIfExists(Isolate* isolate, StringTableInsertionKey* key) {
|
||||
StringTable table = isolate->heap()->string_table();
|
||||
int entry = table.FindEntry(isolate, key);
|
||||
if (entry == kNotFound) return String();
|
||||
InternalIndex entry = table.FindEntry(isolate, key);
|
||||
if (entry.is_not_found()) return String();
|
||||
|
||||
String canonical = String::cast(table.KeyAt(entry));
|
||||
DCHECK_NE(canonical, key->string());
|
||||
|
@ -679,7 +679,8 @@ void TestEntryToIndex() {
|
||||
entry = entry * 1.01 + 1) {
|
||||
Handle<Object> result =
|
||||
ft.Call(handle(Smi::FromInt(entry), isolate)).ToHandleChecked();
|
||||
CHECK_EQ(Dictionary::EntryToIndex(entry), Smi::ToInt(*result));
|
||||
CHECK_EQ(Dictionary::EntryToIndex(InternalIndex(entry)),
|
||||
Smi::ToInt(*result));
|
||||
}
|
||||
}
|
||||
|
||||
@ -759,10 +760,10 @@ void TestNameDictionaryLookup() {
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < arraysize(keys); i++) {
|
||||
int entry = dictionary->FindEntry(isolate, keys[i]);
|
||||
InternalIndex entry = dictionary->FindEntry(isolate, keys[i]);
|
||||
int name_index =
|
||||
Dictionary::EntryToIndex(entry) + Dictionary::kEntryKeyIndex;
|
||||
CHECK_NE(Dictionary::kNotFound, entry);
|
||||
CHECK(entry.is_found());
|
||||
|
||||
Handle<Object> expected_name_index(Smi::FromInt(name_index), isolate);
|
||||
ft.CheckTrue(dictionary, keys[i], expect_found, expected_name_index);
|
||||
@ -781,8 +782,8 @@ void TestNameDictionaryLookup() {
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < arraysize(non_existing_keys); i++) {
|
||||
int entry = dictionary->FindEntry(isolate, non_existing_keys[i]);
|
||||
CHECK_EQ(Dictionary::kNotFound, entry);
|
||||
InternalIndex entry = dictionary->FindEntry(isolate, non_existing_keys[i]);
|
||||
CHECK(entry.is_not_found());
|
||||
|
||||
ft.CheckTrue(dictionary, non_existing_keys[i], expect_not_found);
|
||||
}
|
||||
@ -851,8 +852,7 @@ TEST(NumberDictionaryLookup) {
|
||||
for (int i = 0; i < kKeysCount; i++) {
|
||||
int random_key = rand_gen.NextInt(Smi::kMaxValue);
|
||||
keys[i] = static_cast<uint32_t>(random_key);
|
||||
if (dictionary->FindEntry(isolate, keys[i]) != NumberDictionary::kNotFound)
|
||||
continue;
|
||||
if (dictionary->FindEntry(isolate, keys[i]).is_found()) continue;
|
||||
|
||||
dictionary = NumberDictionary::Add(isolate, dictionary, keys[i], fake_value,
|
||||
fake_details);
|
||||
@ -860,19 +860,19 @@ TEST(NumberDictionaryLookup) {
|
||||
|
||||
// Now try querying existing keys.
|
||||
for (int i = 0; i < kKeysCount; i++) {
|
||||
int entry = dictionary->FindEntry(isolate, keys[i]);
|
||||
CHECK_NE(NumberDictionary::kNotFound, entry);
|
||||
InternalIndex entry = dictionary->FindEntry(isolate, keys[i]);
|
||||
CHECK(entry.is_found());
|
||||
|
||||
Handle<Object> key(Smi::FromInt(keys[i]), isolate);
|
||||
Handle<Object> expected_entry(Smi::FromInt(entry), isolate);
|
||||
Handle<Object> expected_entry(Smi::FromInt(entry.as_int()), isolate);
|
||||
ft.CheckTrue(dictionary, key, expect_found, expected_entry);
|
||||
}
|
||||
|
||||
// Now try querying random keys which do not exist in the dictionary.
|
||||
for (int i = 0; i < kKeysCount;) {
|
||||
int random_key = rand_gen.NextInt(Smi::kMaxValue);
|
||||
int entry = dictionary->FindEntry(isolate, random_key);
|
||||
if (entry != NumberDictionary::kNotFound) continue;
|
||||
InternalIndex entry = dictionary->FindEntry(isolate, random_key);
|
||||
if (entry.is_found()) continue;
|
||||
i++;
|
||||
|
||||
Handle<Object> key(Smi::FromInt(random_key), isolate);
|
||||
|
@ -84,7 +84,7 @@ static void TestHashMap(Handle<HashMap> table) {
|
||||
Handle<JSObject> value = factory->NewJSArray(11);
|
||||
table = HashMap::Put(table, key, value);
|
||||
CHECK_EQ(table->NumberOfElements(), i + 1);
|
||||
CHECK_NE(table->FindEntry(isolate, key), HashMap::kNotFound);
|
||||
CHECK(table->FindEntry(isolate, key).is_found());
|
||||
CHECK_EQ(table->Lookup(key), *value);
|
||||
CHECK(key->GetIdentityHash().IsSmi());
|
||||
}
|
||||
@ -94,7 +94,7 @@ static void TestHashMap(Handle<HashMap> table) {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
Handle<JSReceiver> key = factory->NewJSArray(7);
|
||||
CHECK(key->GetOrCreateIdentityHash(isolate).IsSmi());
|
||||
CHECK_EQ(table->FindEntry(isolate, key), HashMap::kNotFound);
|
||||
CHECK(table->FindEntry(isolate, key).is_not_found());
|
||||
CHECK_EQ(table->Lookup(key), roots.the_hole_value());
|
||||
CHECK(key->GetIdentityHash().IsSmi());
|
||||
}
|
||||
@ -189,9 +189,8 @@ TEST(HashSet) {
|
||||
class ObjectHashTableTest: public ObjectHashTable {
|
||||
public:
|
||||
explicit ObjectHashTableTest(ObjectHashTable o) : ObjectHashTable(o) {}
|
||||
ObjectHashTableTest* operator->() { return this; }
|
||||
|
||||
void insert(int entry, int key, int value) {
|
||||
void insert(InternalIndex entry, int key, int value) {
|
||||
set(EntryToIndex(entry), Smi::FromInt(key));
|
||||
set(EntryToIndex(entry) + 1, Smi::FromInt(value));
|
||||
}
|
||||
@ -217,7 +216,7 @@ TEST(HashTableRehash) {
|
||||
ObjectHashTableTest t(*table);
|
||||
int capacity = t.capacity();
|
||||
for (int i = 0; i < capacity - 1; i++) {
|
||||
t.insert(i, i * i, i);
|
||||
t.insert(InternalIndex(i), i * i, i);
|
||||
}
|
||||
t.Rehash(ReadOnlyRoots(isolate));
|
||||
for (int i = 0; i < capacity - 1; i++) {
|
||||
@ -230,7 +229,7 @@ TEST(HashTableRehash) {
|
||||
ObjectHashTableTest t(*table);
|
||||
int capacity = t.capacity();
|
||||
for (int i = 0; i < capacity / 2; i++) {
|
||||
t.insert(i, i * i, i);
|
||||
t.insert(InternalIndex(i), i * i, i);
|
||||
}
|
||||
t.Rehash(ReadOnlyRoots(isolate));
|
||||
for (int i = 0; i < capacity / 2; i++) {
|
||||
@ -308,7 +307,8 @@ TEST(MaximumClonedShallowObjectProperties) {
|
||||
// not in large-object space.
|
||||
const int max_capacity = NameDictionary::ComputeCapacity(
|
||||
ConstructorBuiltins::kMaximumClonedShallowObjectProperties);
|
||||
const int max_literal_entry = max_capacity / NameDictionary::kEntrySize;
|
||||
const InternalIndex max_literal_entry(max_capacity /
|
||||
NameDictionary::kEntrySize);
|
||||
const int max_literal_index = NameDictionary::EntryToIndex(max_literal_entry);
|
||||
CHECK_LE(NameDictionary::OffsetOfElementAt(max_literal_index),
|
||||
kMaxRegularHeapObjectSize);
|
||||
|
@ -150,7 +150,7 @@ TEST(Shrinking) {
|
||||
|
||||
namespace {
|
||||
bool EphemeronHashTableContainsKey(EphemeronHashTable table, HeapObject key) {
|
||||
for (int i = 0; i < table.Capacity(); ++i) {
|
||||
for (InternalIndex i : table.IterateEntries()) {
|
||||
if (table.KeyAt(i) == key) return true;
|
||||
}
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user