Revision: 2584
Author: [email protected]
Date: Thu Jul 30 02:13:48 2009
Log: Avoid dictionary expansion during bootstrapping.

Allocate the code stubs dictionary and non monomorphic cache dictionary  
with an initial size which avoids these dictionaries to be expanded during  
bootstrapping. This gets rid of 9 dictionary expansions during  
bootstrapping.

Preallocate the dictionary when normalizing an object to a size sufficient  
for holding the number of properties which is expected to be added to the  
object. This is used when ceating an object from an object literal  
boilerplate where multiple properties are known to be added.  This gets rid  
of 10 dictionary expansions during bootstrapping.

There are now 3 dictionary expansions left during bootstrapping.
Review URL: http://codereview.chromium.org/160382
http://code.google.com/p/v8/source/detail?r=2584

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

=======================================
--- /branches/bleeding_edge/src/handles.cc      Tue Jul 28 01:43:51 2009
+++ /branches/bleeding_edge/src/handles.cc      Thu Jul 30 02:13:48 2009
@@ -164,8 +164,11 @@


  void NormalizeProperties(Handle<JSObject> object,
-                         PropertyNormalizationMode mode) {
-  CALL_HEAP_FUNCTION_VOID(object->NormalizeProperties(mode));
+                         PropertyNormalizationMode mode,
+                         int expected_additional_properties) {
+  CALL_HEAP_FUNCTION_VOID(object->NormalizeProperties(
+      mode,
+      expected_additional_properties));
  }


@@ -651,13 +654,17 @@

  OptimizedObjectForAddingMultipleProperties::
  OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
+                                           int  
expected_additional_properties,
                                             bool condition) {
    object_ = object;
    if (condition && object_->HasFastProperties()) {
      // Normalize the properties of object to avoid n^2 behavior
-    // when extending the object multiple properties.
+    // when extending the object multiple properties. Indicate the number  
of
+    // properties to be added.
      unused_property_fields_ = object->map()->unused_property_fields();
-    NormalizeProperties(object_, KEEP_INOBJECT_PROPERTIES);
+    NormalizeProperties(object_,
+                        KEEP_INOBJECT_PROPERTIES,
+                        expected_additional_properties);
      has_been_transformed_ = true;

    } else {
=======================================
--- /branches/bleeding_edge/src/handles.h       Tue Jul  7 04:41:21 2009
+++ /branches/bleeding_edge/src/handles.h       Thu Jul 30 02:13:48 2009
@@ -181,7 +181,8 @@
  // of space or encountering an internal error.

  void NormalizeProperties(Handle<JSObject> object,
-                         PropertyNormalizationMode mode);
+                         PropertyNormalizationMode mode,
+                         int expected_additional_properties);
  void NormalizeElements(Handle<JSObject> object);
  void TransformToFastProperties(Handle<JSObject> object,
                                 int unused_property_fields);
@@ -336,6 +337,7 @@
  class OptimizedObjectForAddingMultipleProperties BASE_EMBEDDED {
   public:
    OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
+                                             int expected_property_count,
                                               bool condition = true);
    ~OptimizedObjectForAddingMultipleProperties();
   private:
=======================================
--- /branches/bleeding_edge/src/heap.cc Thu Jul 30 00:33:05 2009
+++ /branches/bleeding_edge/src/heap.cc Thu Jul 30 02:13:48 2009
@@ -1443,13 +1443,15 @@
    if (obj->IsFailure()) return false;
    set_prototype_accessors(Proxy::cast(obj));

-  // Allocate the code_stubs dictionary.
-  obj = NumberDictionary::Allocate(4);
+  // Allocate the code_stubs dictionary. The initial size is set to avoid
+  // expanding the dictionary during bootstrapping.
+  obj = NumberDictionary::Allocate(128);
    if (obj->IsFailure()) return false;
    set_code_stubs(NumberDictionary::cast(obj));

-  // Allocate the non_monomorphic_cache used in stub-cache.cc
-  obj = NumberDictionary::Allocate(4);
+  // Allocate the non_monomorphic_cache used in stub-cache.cc. The initial  
size
+  // is set to avoid expanding the dictionary during bootstrapping.
+  obj = NumberDictionary::Allocate(64);
    if (obj->IsFailure()) return false;
    set_non_monomorphic_cache(NumberDictionary::cast(obj));

=======================================
--- /branches/bleeding_edge/src/objects.cc      Thu Jul 30 00:33:05 2009
+++ /branches/bleeding_edge/src/objects.cc      Thu Jul 30 02:13:48 2009
@@ -1244,7 +1244,7 @@
    // hidden symbols) and is not a real identifier.
    StringInputBuffer buffer(name);
    if (!Scanner::IsIdentifier(&buffer) && name != Heap::hidden_symbol()) {
-    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
      if (obj->IsFailure()) return obj;
      return AddSlowProperty(name, value, attributes);
    }
@@ -1282,7 +1282,7 @@

    if (map()->unused_property_fields() == 0) {
      if (properties()->length() > kMaxFastProperties) {
-      Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+      Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
        if (obj->IsFailure()) return obj;
        return AddSlowProperty(name, value, attributes);
      }
@@ -1403,7 +1403,7 @@
      } else {
        // Normalize the object to prevent very large instance descriptors.
        // This eliminates unwanted N^2 allocation and lookup behavior.
-      Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+      Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
        if (obj->IsFailure()) return obj;
      }
    }
@@ -1473,7 +1473,7 @@
                                             PropertyAttributes attributes) {
    if (map()->unused_property_fields() == 0 &&
        properties()->length() > kMaxFastProperties) {
-    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
      if (obj->IsFailure()) return obj;
      return ReplaceSlowProperty(name, new_value, attributes);
    }
@@ -2124,15 +2124,22 @@
  }


-Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode) {
+Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
+                                      int expected_additional_properties) {
    if (!HasFastProperties()) return this;

    // The global object is always normalized.
    ASSERT(!IsGlobalObject());

    // Allocate new content.
+  int property_count = map()->NumberOfDescribedProperties();
+  if (expected_additional_properties > 0) {
+    property_count += expected_additional_properties;
+  } else {
+    property_count += 2;  // Make space for two more properties.
+  }
    Object* obj =
-      StringDictionary::Allocate(map()->NumberOfDescribedProperties() * 2  
+ 4);
+      StringDictionary::Allocate(property_count * 2);
    if (obj->IsFailure()) return obj;
    StringDictionary* dictionary = StringDictionary::cast(obj);

@@ -2272,7 +2279,7 @@
    if (!result.IsValid()) return Heap::true_value();

    // Normalize object if needed.
-  Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+  Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
    if (obj->IsFailure()) return obj;

    return DeleteNormalizedProperty(name, mode);
@@ -2469,7 +2476,7 @@
                                                        mode);
      }
      // Normalize object if needed.
-    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+    Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
      if (obj->IsFailure()) return obj;
      // Make sure the properties are normalized before removing the entry.
      return DeleteNormalizedProperty(name, mode);
@@ -2802,7 +2809,7 @@
      set_elements(NumberDictionary::cast(dict));
    } else {
      // Normalize object to make this operation simple.
-    Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+    Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
      if (ok->IsFailure()) return ok;

      // For the global object allocate a new map to invalidate the global  
inline
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Jul 30 00:31:54 2009
+++ /branches/bleeding_edge/src/objects.h       Thu Jul 30 02:13:48 2009
@@ -1584,8 +1584,11 @@
                        PropertyAttributes attributes);

    // Convert the object to use the canonical dictionary
-  // representation.
-  Object* NormalizeProperties(PropertyNormalizationMode mode);
+  // representation. If the object is expected to have additional  
properties
+  // added this number can be indicated to have the backing store  
allocated to
+  // an initial capacity for holding these properties.
+  Object* NormalizeProperties(PropertyNormalizationMode mode,
+                              int expected_additional_properties);
    Object* NormalizeElements();

    // Transform slow named properties to fast variants.
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Jul 28 02:05:05 2009
+++ /branches/bleeding_edge/src/runtime.cc      Thu Jul 30 02:13:48 2009
@@ -268,6 +268,7 @@
    {  // Add the constant properties to the boilerplate.
      int length = constant_properties->length();
      OptimizedObjectForAddingMultipleProperties opt(boilerplate,
+                                                   length / 2,
                                                     !is_result_from_cache);
      for (int index = 0; index < length; index +=2) {
        Handle<Object> key(constant_properties->get(index+0));
@@ -3033,7 +3034,7 @@
    Handle<Object> object = args.at<Object>(0);
    if (object->IsJSObject()) {
      Handle<JSObject> js_object = Handle<JSObject>::cast(object);
-    js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
+    js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
    }
    return *object;
  }

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to