| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index 76105599a81bd4bd732d403b671ddfe911ae851c..3d176aef8033433615fa428fd6298533ac8bf34b 100644
|
| --- a/src/elements.cc
|
| +++ b/src/elements.cc
|
| @@ -1192,12 +1192,16 @@ class DictionaryElementsAccessor
|
|
|
| static bool HasAccessorsImpl(JSObject* holder,
|
| FixedArrayBase* backing_store) {
|
| + DisallowHeapAllocation no_gc;
|
| SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store);
|
| if (!dict->requires_slow_elements()) return false;
|
| int capacity = dict->Capacity();
|
| + Heap* heap = holder->GetHeap();
|
| + Object* undefined = heap->undefined_value();
|
| + Object* the_hole = heap->the_hole_value();
|
| for (int i = 0; i < capacity; i++) {
|
| Object* key = dict->KeyAt(i);
|
| - if (!dict->IsKey(key)) continue;
|
| + if (key == the_hole || key == undefined) continue;
|
| DCHECK(!dict->IsDeleted(i));
|
| PropertyDetails details = dict->DetailsAt(i);
|
| if (details.type() == ACCESSOR_CONSTANT) return true;
|
| @@ -1296,11 +1300,8 @@ class DictionaryElementsAccessor
|
| return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry);
|
| }
|
|
|
| - static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary,
|
| - int entry, PropertyFilter filter) {
|
| - DisallowHeapAllocation no_gc;
|
| - Object* raw_key = dictionary->KeyAt(entry);
|
| - if (!dictionary->IsKey(raw_key)) return kMaxUInt32;
|
| + static uint32_t FilterKey(Handle<SeededNumberDictionary> dictionary,
|
| + int entry, Object* raw_key, PropertyFilter filter) {
|
| DCHECK(!dictionary->IsDeleted(entry));
|
| DCHECK(raw_key->IsNumber());
|
| DCHECK_LE(raw_key->Number(), kMaxUInt32);
|
| @@ -1310,17 +1311,41 @@ class DictionaryElementsAccessor
|
| return static_cast<uint32_t>(raw_key->Number());
|
| }
|
|
|
| + static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary,
|
| + int entry, PropertyFilter filter) {
|
| + DisallowHeapAllocation no_gc;
|
| + Object* raw_key = dictionary->KeyAt(entry);
|
| + if (!dictionary->IsKey(raw_key)) return kMaxUInt32;
|
| + return FilterKey(dictionary, entry, raw_key, filter);
|
| + }
|
| +
|
| + static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary,
|
| + int entry, PropertyFilter filter,
|
| + Object* undefined, Object* the_hole) {
|
| + DisallowHeapAllocation no_gc;
|
| + Object* raw_key = dictionary->KeyAt(entry);
|
| + // Replace the IsKey check with a direct comparison which is much faster.
|
| + if (raw_key == undefined || raw_key == the_hole) {
|
| + return kMaxUInt32;
|
| + }
|
| + return FilterKey(dictionary, entry, raw_key, filter);
|
| + }
|
| +
|
| static void CollectElementIndicesImpl(Handle<JSObject> object,
|
| Handle<FixedArrayBase> backing_store,
|
| KeyAccumulator* keys, uint32_t range,
|
| PropertyFilter filter,
|
| uint32_t offset) {
|
| if (filter & SKIP_STRINGS) return;
|
| + Isolate* isolate = keys->isolate();
|
| + Handle<Object> undefined = isolate->factory()->undefined_value();
|
| + Handle<Object> the_hole = isolate->factory()->the_hole_value();
|
| Handle<SeededNumberDictionary> dictionary =
|
| Handle<SeededNumberDictionary>::cast(backing_store);
|
| int capacity = dictionary->Capacity();
|
| for (int i = 0; i < capacity; i++) {
|
| - uint32_t key = GetKeyForEntryImpl(dictionary, i, filter);
|
| + uint32_t key =
|
| + GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole);
|
| if (key == kMaxUInt32) continue;
|
| keys->AddKey(key);
|
| }
|
| @@ -1335,11 +1360,15 @@ class DictionaryElementsAccessor
|
| uint32_t insertion_index = 0) {
|
| if (filter & SKIP_STRINGS) return list;
|
| if (filter & ONLY_ALL_CAN_READ) return list;
|
| +
|
| + Handle<Object> undefined = isolate->factory()->undefined_value();
|
| + Handle<Object> the_hole = isolate->factory()->the_hole_value();
|
| Handle<SeededNumberDictionary> dictionary =
|
| Handle<SeededNumberDictionary>::cast(backing_store);
|
| uint32_t capacity = dictionary->Capacity();
|
| for (uint32_t i = 0; i < capacity; i++) {
|
| - uint32_t key = GetKeyForEntryImpl(dictionary, i, filter);
|
| + uint32_t key =
|
| + GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole);
|
| if (key == kMaxUInt32) continue;
|
| Handle<Object> index = isolate->factory()->NewNumberFromUint(key);
|
| list->set(insertion_index, *index);
|
| @@ -1352,12 +1381,16 @@ class DictionaryElementsAccessor
|
| static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
|
| KeyAccumulator* accumulator,
|
| AddKeyConversion convert) {
|
| + Isolate* isolate = accumulator->isolate();
|
| + Handle<Object> undefined = isolate->factory()->undefined_value();
|
| + Handle<Object> the_hole = isolate->factory()->the_hole_value();
|
| SeededNumberDictionary* dictionary =
|
| SeededNumberDictionary::cast(receiver->elements());
|
| int capacity = dictionary->Capacity();
|
| for (int i = 0; i < capacity; i++) {
|
| Object* k = dictionary->KeyAt(i);
|
| - if (!dictionary->IsKey(k)) continue;
|
| + if (k == *undefined) continue;
|
| + if (k == *the_hole) continue;
|
| if (dictionary->IsDeleted(i)) continue;
|
| Object* value = dictionary->ValueAt(i);
|
| DCHECK(!value->IsTheHole());
|
|
|