Revision: 11732
Author:   [email protected]
Date:     Thu Jun  7 05:08:07 2012
Log: Use the syntax of a property addition as a hint for controlling the fast-mode vs. dictionary mode heursitics on objects.
Review URL: https://chromiumcodereview.appspot.com/10537050
http://code.google.com/p/v8/source/detail?r=11732

Added:
 /branches/bleeding_edge/test/mjsunit/fast-non-keyed.js
Modified:
 /branches/bleeding_edge/src/ic.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/fast-non-keyed.js Thu Jun 7 05:08:07 2012
@@ -0,0 +1,76 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+// Check that keyed stores make things go dict mode faster than non-keyed
+// stores.
+
+function AddProps(obj) {
+  for (var i = 0; i < 26; i++) {
+    obj["x" + i] = 0;
+  }
+}
+
+
+function AddPropsNonKeyed(obj) {
+  obj.x0 = 0;
+  obj.x1 = 0;
+  obj.x2 = 0;
+  obj.x3 = 0;
+  obj.x4 = 0;
+  obj.x5 = 0;
+  obj.x6 = 0;
+  obj.x7 = 0;
+  obj.x8 = 0;
+  obj.x9 = 0;
+  obj.x10 = 0;
+  obj.x11 = 0;
+  obj.x12 = 0;
+  obj.x13 = 0;
+  obj.x14 = 0;
+  obj.x15 = 0;
+  obj.x16 = 0;
+  obj.x17 = 0;
+  obj.x18 = 0;
+  obj.x19 = 0;
+  obj.x20 = 0;
+  obj.x21 = 0;
+  obj.x22 = 0;
+  obj.x23 = 0;
+  obj.x24 = 0;
+  obj.x25 = 0;
+}
+
+
+var keyed = {};
+AddProps(keyed);
+assertFalse(%HasFastProperties(keyed));
+
+var non_keyed = {};
+AddPropsNonKeyed(non_keyed);
+assertTrue(%HasFastProperties(non_keyed));
=======================================
--- /branches/bleeding_edge/src/ic.cc   Wed May 23 07:24:29 2012
+++ /branches/bleeding_edge/src/ic.cc   Thu Jun  7 05:08:07 2012
@@ -1408,7 +1408,11 @@
   }

   // Set the property.
-  return receiver->SetProperty(*name, *value, NONE, strict_mode);
+  return receiver->SetProperty(*name,
+                               *value,
+                               NONE,
+                               strict_mode,
+                               JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
 }


=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Wed Jun  6 03:17:26 2012
+++ /branches/bleeding_edge/src/objects-inl.h   Thu Jun  7 05:08:07 2012
@@ -1611,7 +1611,8 @@
 }


-bool JSObject::TooManyFastProperties(int properties) {
+bool JSObject::TooManyFastProperties(int properties,
+                                     JSObject::StoreFromKeyed store_mode) {
   // Allow extra fast properties if the object has more than
   // kFastPropertiesSoftLimit in-object properties. When this is the case,
   // it is very unlikely that the object is being used as a dictionary
@@ -1620,7 +1621,8 @@
   int inobject = map()->inobject_properties();

   int limit;
-  if (map()->used_for_prototype()) {
+  if (store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ||
+      map()->used_for_prototype()) {
     limit = Max(inobject, kMaxFastProperties);
   } else {
     limit = Max(inobject, kFastPropertiesSoftLimit);
=======================================
--- /branches/bleeding_edge/src/objects.cc      Wed Jun  6 03:17:26 2012
+++ /branches/bleeding_edge/src/objects.cc      Thu Jun  7 05:08:07 2012
@@ -1514,7 +1514,8 @@

 MaybeObject* JSObject::AddFastProperty(String* name,
                                        Object* value,
-                                       PropertyAttributes attributes) {
+                                       PropertyAttributes attributes,
+                                       StoreFromKeyed store_mode) {
   ASSERT(!IsJSGlobalProxy());

   // Normalize the object if the name is an actual string (not the
@@ -1580,7 +1581,7 @@
   }

   if (map()->unused_property_fields() == 0) {
-    if (TooManyFastProperties(properties()->length())) {
+    if (TooManyFastProperties(properties()->length(), store_mode)) {
       Object* obj;
       { MaybeObject* maybe_obj =
             NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
@@ -1710,7 +1711,8 @@
 MaybeObject* JSObject::AddProperty(String* name,
                                    Object* value,
                                    PropertyAttributes attributes,
-                                   StrictModeFlag strict_mode) {
+                                   StrictModeFlag strict_mode,
+                                   JSReceiver::StoreFromKeyed store_mode) {
   ASSERT(!IsJSGlobalProxy());
   Map* map_of_this = map();
   Heap* heap = GetHeap();
@@ -1733,7 +1735,7 @@
                                            JSFunction::cast(value),
                                            attributes);
       } else {
-        return AddFastProperty(name, value, attributes);
+        return AddFastProperty(name, value, attributes, store_mode);
       }
     } else {
       // Normalize the object to prevent very large instance descriptors.
@@ -1830,7 +1832,7 @@
                                                 Object* new_value,
PropertyAttributes attributes) {
   if (map()->unused_property_fields() == 0 &&
-      TooManyFastProperties(properties()->length())) {
+ TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) {
     Object* obj;
     { MaybeObject* maybe_obj =
           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
@@ -1945,10 +1947,11 @@
 MaybeObject* JSReceiver::SetProperty(String* name,
                                      Object* value,
                                      PropertyAttributes attributes,
-                                     StrictModeFlag strict_mode) {
+                                     StrictModeFlag strict_mode,
+ JSReceiver::StoreFromKeyed store_mode) {
   LookupResult result(GetIsolate());
   LocalLookup(name, &result);
-  return SetProperty(&result, name, value, attributes, strict_mode);
+ return SetProperty(&result, name, value, attributes, strict_mode, store_mode);
 }


@@ -2619,13 +2622,14 @@
                                      String* key,
                                      Object* value,
                                      PropertyAttributes attributes,
-                                     StrictModeFlag strict_mode) {
+                                     StrictModeFlag strict_mode,
+ JSReceiver::StoreFromKeyed store_mode) {
   if (result->IsFound() && result->type() == HANDLER) {
     return result->proxy()->SetPropertyWithHandler(
         this, key, value, attributes, strict_mode);
   } else {
     return JSObject::cast(this)->SetPropertyForResult(
-        result, key, value, attributes, strict_mode);
+        result, key, value, attributes, strict_mode, store_mode);
   }
 }

@@ -2908,7 +2912,8 @@
                                             String* name,
                                             Object* value,
                                             PropertyAttributes attributes,
-                                            StrictModeFlag strict_mode) {
+                                            StrictModeFlag strict_mode,
+                                            StoreFromKeyed store_mode) {
   Heap* heap = GetHeap();
   // Make sure that the top context does not change when doing callbacks or
   // interceptor calls.
@@ -2939,7 +2944,7 @@
     if (proto->IsNull()) return value;
     ASSERT(proto->IsJSGlobalObject());
     return JSObject::cast(proto)->SetPropertyForResult(
-        result, name, value, attributes, strict_mode);
+        result, name, value, attributes, strict_mode, store_mode);
   }

   if (!result->IsProperty() && !IsJSContextExtensionObject()) {
@@ -2951,7 +2956,7 @@

   if (!result->IsFound()) {
     // Neither properties nor transitions found.
-    return AddProperty(name, value, attributes, strict_mode);
+    return AddProperty(name, value, attributes, strict_mode, store_mode);
   }
   if (result->IsReadOnly() && result->IsProperty()) {
     if (strict_mode == kStrictMode) {
=======================================
--- /branches/bleeding_edge/src/objects.h       Wed Jun  6 03:17:26 2012
+++ /branches/bleeding_edge/src/objects.h       Thu Jun  7 05:08:07 2012
@@ -1353,6 +1353,13 @@
     FORCE_DELETION
   };

+  // A non-keyed store is of the form a.x = foo or a["x"] = foo whereas
+  // a keyed store is of the form a[expression] = foo.
+  enum StoreFromKeyed {
+    MAY_BE_STORE_FROM_KEYED,
+    CERTAINLY_NOT_STORE_FROM_KEYED
+  };
+
   // Casting.
   static inline JSReceiver* cast(Object* obj);

@@ -1362,15 +1369,19 @@
                                     PropertyAttributes attributes,
                                     StrictModeFlag strict_mode);
   // Can cause GC.
-  MUST_USE_RESULT MaybeObject* SetProperty(String* key,
-                                           Object* value,
-                                           PropertyAttributes attributes,
-                                           StrictModeFlag strict_mode);
-  MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result,
-                                           String* key,
-                                           Object* value,
-                                           PropertyAttributes attributes,
-                                           StrictModeFlag strict_mode);
+  MUST_USE_RESULT MaybeObject* SetProperty(
+      String* key,
+      Object* value,
+      PropertyAttributes attributes,
+      StrictModeFlag strict_mode,
+      StoreFromKeyed store_from_keyed = MAY_BE_STORE_FROM_KEYED);
+  MUST_USE_RESULT MaybeObject* SetProperty(
+      LookupResult* result,
+      String* key,
+      Object* value,
+      PropertyAttributes attributes,
+      StrictModeFlag strict_mode,
+      StoreFromKeyed store_from_keyed = MAY_BE_STORE_FROM_KEYED);
MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSReceiver* setter,
                                                             Object* value);

@@ -1524,7 +1535,8 @@
                                            String* key,
                                            Object* value,
                                            PropertyAttributes attributes,
-                                           StrictModeFlag strict_mode);
+                                           StrictModeFlag strict_mode,
+                                           StoreFromKeyed store_mode);
   MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
       LookupResult* result,
       String* name,
@@ -1921,9 +1933,11 @@
       PropertyAttributes attributes);

   // Add a property to a fast-case object.
-  MUST_USE_RESULT MaybeObject* AddFastProperty(String* name,
-                                               Object* value,
- PropertyAttributes attributes);
+  MUST_USE_RESULT MaybeObject* AddFastProperty(
+      String* name,
+      Object* value,
+      PropertyAttributes attributes,
+      StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);

   // Add a property to a slow-case object.
   MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
@@ -1931,10 +1945,12 @@
PropertyAttributes attributes);

   // Add a property to an object.
-  MUST_USE_RESULT MaybeObject* AddProperty(String* name,
-                                           Object* value,
-                                           PropertyAttributes attributes,
-                                           StrictModeFlag strict_mode);
+  MUST_USE_RESULT MaybeObject* AddProperty(
+      String* name,
+      Object* value,
+      PropertyAttributes attributes,
+      StrictModeFlag strict_mode,
+      StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);

   // Convert the object to use the canonical dictionary
// representation. If the object is expected to have additional properties
@@ -2054,7 +2070,7 @@
   // Maximal number of fast properties for the JSObject. Used to
   // restrict the number of map transitions to avoid an explosion in
   // the number of maps for objects used as dictionaries.
-  inline bool TooManyFastProperties(int properties);
+ inline bool TooManyFastProperties(int properties, StoreFromKeyed store_mode);

   // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
   // Also maximal value of JSArray's length property.
@@ -2077,7 +2093,7 @@

   static const int kInitialMaxFastElementArray = 100000;
   static const int kFastPropertiesSoftLimit = 12;
-  static const int kMaxFastProperties = 32;
+  static const int kMaxFastProperties = 64;
   static const int kMaxInstanceSize = 255 * kPointerSize;
   // When extending the backing storage for property values, we increase
// its size by more than the 1 entry necessary, so sequentially adding fields

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

Reply via email to