Revision: 19894
Author:   [email protected]
Date:     Thu Mar 13 12:45:12 2014 UTC
Log: Simplify GetEnumPropertyKeys and avoid trimming fixed arrays in large object space.

BUG=352070
LOG=N
[email protected]

Review URL: https://codereview.chromium.org/198943002
http://code.google.com/p/v8/source/detail?r=19894

Modified:
 /branches/bleeding_edge/src/handles.cc
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h

=======================================
--- /branches/bleeding_edge/src/handles.cc      Tue Mar 11 14:41:22 2014 UTC
+++ /branches/bleeding_edge/src/handles.cc      Thu Mar 13 12:45:12 2014 UTC
@@ -712,35 +712,12 @@
     return ReduceFixedArrayTo(storage, enum_size);
   } else {
     Handle<NameDictionary> dictionary(object->property_dictionary());
-
-    int length = dictionary->NumberOfElements();
+    int length = dictionary->NumberOfEnumElements();
     if (length == 0) {
       return Handle<FixedArray>(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<FixedArray> storage =
-        isolate->factory()->NewFixedArray(next_enumeration);
-
-    storage = Handle<FixedArray>(dictionary->CopyEnumKeysTo(*storage));
- ASSERT(storage->length() == object->NumberOfLocalProperties(DONT_SHOW));
+    Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
+    dictionary->CopyEnumKeysTo(*storage);
     return storage;
   }
 }
=======================================
--- /branches/bleeding_edge/src/objects.cc      Thu Mar 13 11:55:31 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc      Thu Mar 13 12:45:12 2014 UTC
@@ -15511,7 +15511,7 @@
 template<typename Shape, typename Key>
 int Dictionary<Shape, Key>::NumberOfEnumElements() {
   return NumberOfElementsFilterAttributes(
-      static_cast<PropertyAttributes>(DONT_ENUM));
+      static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC));
 }


@@ -15539,45 +15539,38 @@
 }


-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<FROM_MUTATOR>(heap, storage, length - properties);
+  EnumIndexComparator cmp(this);
+  Smi** start = reinterpret_cast<Smi**>(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;
 }


=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Mar 13 11:55:31 2014 UTC
+++ /branches/bleeding_edge/src/objects.h       Thu Mar 13 12:45:12 2014 UTC
@@ -4036,7 +4036,7 @@
   }

   // Copies enumerable keys to preallocated fixed array.
-  FixedArray* CopyEnumKeysTo(FixedArray* storage);
+  void CopyEnumKeysTo(FixedArray* storage);
   static void DoGenerateNewEnumerationIndices(
       Handle<NameDictionary> dictionary);

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to