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