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:
Jakob Kummerow 2019-10-16 14:24:54 +02:00 committed by Commit Bot
parent 38301e7bb9
commit 0b9f10532a
44 changed files with 398 additions and 413 deletions

View File

@ -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);
}

View File

@ -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());

View File

@ -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());

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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";

View File

@ -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);

View File

@ -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));

View File

@ -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());

View File

@ -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,

View File

@ -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));

View File

@ -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()) {

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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());

View File

@ -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(

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {

View File

@ -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>);
};

View File

@ -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_);
}

View File

@ -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();

View File

@ -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)

View File

@ -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;

View File

@ -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_));

View File

@ -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;

View File

@ -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

View File

@ -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));

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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(

View File

@ -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());

View File

@ -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 &&

View File

@ -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);

View File

@ -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);
}

View File

@ -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());

View File

@ -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);

View File

@ -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);

View File

@ -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;