From: ulan@chromium.org Date: Thu, 13 Mar 2014 12:45:12 +0000 (+0000) Subject: Simplify GetEnumPropertyKeys and avoid trimming fixed arrays in large object space. X-Git-Tag: upstream/4.7.83~10303 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=66c8130b8a94e5899504b308830455d632d28275;p=platform%2Fupstream%2Fv8.git Simplify GetEnumPropertyKeys and avoid trimming fixed arrays in large object space. BUG=352070 LOG=N R=verwaest@chromium.org Review URL: https://codereview.chromium.org/198943002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19894 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/handles.cc b/src/handles.cc index 899f9bf..398a682 100644 --- a/src/handles.cc +++ b/src/handles.cc @@ -712,35 +712,12 @@ Handle GetEnumPropertyKeys(Handle object, return ReduceFixedArrayTo(storage, enum_size); } else { Handle dictionary(object->property_dictionary()); - - int length = dictionary->NumberOfElements(); + int length = dictionary->NumberOfEnumElements(); if (length == 0) { return Handle(isolate->heap()->empty_fixed_array()); } - - // The enumeration array is generated by allocating an array big enough to - // hold all properties that have been seen, whether they are are deleted or - // not. Subsequently all visible properties are added to the array. If some - // properties were not visible, the array is trimmed so it only contains - // visible properties. This improves over adding elements and sorting by - // index by having linear complexity rather than n*log(n). - - // By comparing the monotonous NextEnumerationIndex to the NumberOfElements, - // we can predict the number of holes in the final array. If there will be - // more than 50% holes, regenerate the enumeration indices to reduce the - // number of holes to a minimum. This avoids allocating a large array if - // many properties were added but subsequently deleted. - int next_enumeration = dictionary->NextEnumerationIndex(); - if (!object->IsGlobalObject() && next_enumeration > (length * 3) / 2) { - NameDictionary::DoGenerateNewEnumerationIndices(dictionary); - next_enumeration = dictionary->NextEnumerationIndex(); - } - - Handle storage = - isolate->factory()->NewFixedArray(next_enumeration); - - storage = Handle(dictionary->CopyEnumKeysTo(*storage)); - ASSERT(storage->length() == object->NumberOfLocalProperties(DONT_SHOW)); + Handle storage = isolate->factory()->NewFixedArray(length); + dictionary->CopyEnumKeysTo(*storage); return storage; } } diff --git a/src/objects.cc b/src/objects.cc index b03c39e..492f752 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -15511,7 +15511,7 @@ int Dictionary::NumberOfElementsFilterAttributes( template int Dictionary::NumberOfEnumElements() { return NumberOfElementsFilterAttributes( - static_cast(DONT_ENUM)); + static_cast(DONT_ENUM | SYMBOLIC)); } @@ -15539,45 +15539,38 @@ void Dictionary::CopyKeysTo( } -FixedArray* NameDictionary::CopyEnumKeysTo(FixedArray* storage) { +struct EnumIndexComparator { + explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { } + bool operator() (Smi* a, Smi* b) { + PropertyDetails da(dict->DetailsAt(a->value())); + PropertyDetails db(dict->DetailsAt(b->value())); + return da.dictionary_index() < db.dictionary_index(); + } + NameDictionary* dict; +}; + + +void NameDictionary::CopyEnumKeysTo(FixedArray* storage) { int length = storage->length(); - ASSERT(length >= NumberOfEnumElements()); - Heap* heap = GetHeap(); - Object* undefined_value = heap->undefined_value(); int capacity = Capacity(); int properties = 0; - - // Fill in the enumeration array by assigning enumerable keys at their - // enumeration index. This will leave holes in the array if there are keys - // that are deleted or not enumerable. for (int i = 0; i < capacity; i++) { Object* k = KeyAt(i); if (IsKey(k) && !k->IsSymbol()) { PropertyDetails details = DetailsAt(i); if (details.IsDeleted() || details.IsDontEnum()) continue; + storage->set(properties, Smi::FromInt(i)); properties++; - storage->set(details.dictionary_index() - 1, k); if (properties == length) break; } } - - // There are holes in the enumeration array if less properties were assigned - // than the length of the array. If so, crunch all the existing properties - // together by shifting them to the left (maintaining the enumeration order), - // and trimming of the right side of the array. - if (properties < length) { - if (properties == 0) return heap->empty_fixed_array(); - properties = 0; - for (int i = 0; i < length; ++i) { - Object* value = storage->get(i); - if (value != undefined_value) { - storage->set(properties, value); - ++properties; - } - } - RightTrimFixedArray(heap, storage, length - properties); + EnumIndexComparator cmp(this); + Smi** start = reinterpret_cast(storage->GetFirstElementAddress()); + std::sort(start, start + length, cmp); + for (int i = 0; i < length; i++) { + int index = Smi::cast(storage->get(i))->value(); + storage->set(i, KeyAt(index)); } - return storage; } diff --git a/src/objects.h b/src/objects.h index 8b0cd41..c772578 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4036,7 +4036,7 @@ class NameDictionary: public Dictionary { } // Copies enumerable keys to preallocated fixed array. - FixedArray* CopyEnumKeysTo(FixedArray* storage); + void CopyEnumKeysTo(FixedArray* storage); static void DoGenerateNewEnumerationIndices( Handle dictionary);