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