Commit 657422c2 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Use the syntax of a property addition as a hint for controlling the fast-mode...

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11732 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5e8cc58b
...@@ -1408,7 +1408,11 @@ MaybeObject* StoreIC::Store(State state, ...@@ -1408,7 +1408,11 @@ MaybeObject* StoreIC::Store(State state,
} }
// Set the property. // 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);
} }
......
...@@ -1611,7 +1611,8 @@ bool JSObject::HasFastProperties() { ...@@ -1611,7 +1611,8 @@ bool JSObject::HasFastProperties() {
} }
bool JSObject::TooManyFastProperties(int properties) { bool JSObject::TooManyFastProperties(int properties,
JSObject::StoreFromKeyed store_mode) {
// Allow extra fast properties if the object has more than // Allow extra fast properties if the object has more than
// kFastPropertiesSoftLimit in-object properties. When this is the case, // kFastPropertiesSoftLimit in-object properties. When this is the case,
// it is very unlikely that the object is being used as a dictionary // it is very unlikely that the object is being used as a dictionary
...@@ -1620,7 +1621,8 @@ bool JSObject::TooManyFastProperties(int properties) { ...@@ -1620,7 +1621,8 @@ bool JSObject::TooManyFastProperties(int properties) {
int inobject = map()->inobject_properties(); int inobject = map()->inobject_properties();
int limit; int limit;
if (map()->used_for_prototype()) { if (store_mode == CERTAINLY_NOT_STORE_FROM_KEYED ||
map()->used_for_prototype()) {
limit = Max(inobject, kMaxFastProperties); limit = Max(inobject, kMaxFastProperties);
} else { } else {
limit = Max(inobject, kFastPropertiesSoftLimit); limit = Max(inobject, kFastPropertiesSoftLimit);
......
...@@ -1514,7 +1514,8 @@ static bool IsIdentifier(UnicodeCache* cache, ...@@ -1514,7 +1514,8 @@ static bool IsIdentifier(UnicodeCache* cache,
MaybeObject* JSObject::AddFastProperty(String* name, MaybeObject* JSObject::AddFastProperty(String* name,
Object* value, Object* value,
PropertyAttributes attributes) { PropertyAttributes attributes,
StoreFromKeyed store_mode) {
ASSERT(!IsJSGlobalProxy()); ASSERT(!IsJSGlobalProxy());
// Normalize the object if the name is an actual string (not the // Normalize the object if the name is an actual string (not the
...@@ -1580,7 +1581,7 @@ MaybeObject* JSObject::AddFastProperty(String* name, ...@@ -1580,7 +1581,7 @@ MaybeObject* JSObject::AddFastProperty(String* name,
} }
if (map()->unused_property_fields() == 0) { if (map()->unused_property_fields() == 0) {
if (TooManyFastProperties(properties()->length())) { if (TooManyFastProperties(properties()->length(), store_mode)) {
Object* obj; Object* obj;
{ MaybeObject* maybe_obj = { MaybeObject* maybe_obj =
NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
...@@ -1710,7 +1711,8 @@ MaybeObject* JSObject::AddSlowProperty(String* name, ...@@ -1710,7 +1711,8 @@ MaybeObject* JSObject::AddSlowProperty(String* name,
MaybeObject* JSObject::AddProperty(String* name, MaybeObject* JSObject::AddProperty(String* name,
Object* value, Object* value,
PropertyAttributes attributes, PropertyAttributes attributes,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode,
JSReceiver::StoreFromKeyed store_mode) {
ASSERT(!IsJSGlobalProxy()); ASSERT(!IsJSGlobalProxy());
Map* map_of_this = map(); Map* map_of_this = map();
Heap* heap = GetHeap(); Heap* heap = GetHeap();
...@@ -1733,7 +1735,7 @@ MaybeObject* JSObject::AddProperty(String* name, ...@@ -1733,7 +1735,7 @@ MaybeObject* JSObject::AddProperty(String* name,
JSFunction::cast(value), JSFunction::cast(value),
attributes); attributes);
} else { } else {
return AddFastProperty(name, value, attributes); return AddFastProperty(name, value, attributes, store_mode);
} }
} else { } else {
// Normalize the object to prevent very large instance descriptors. // Normalize the object to prevent very large instance descriptors.
...@@ -1830,7 +1832,7 @@ MaybeObject* JSObject::ConvertDescriptorToField(String* name, ...@@ -1830,7 +1832,7 @@ MaybeObject* JSObject::ConvertDescriptorToField(String* name,
Object* new_value, Object* new_value,
PropertyAttributes attributes) { PropertyAttributes attributes) {
if (map()->unused_property_fields() == 0 && if (map()->unused_property_fields() == 0 &&
TooManyFastProperties(properties()->length())) { TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) {
Object* obj; Object* obj;
{ MaybeObject* maybe_obj = { MaybeObject* maybe_obj =
NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
...@@ -1945,10 +1947,11 @@ Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, ...@@ -1945,10 +1947,11 @@ Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
MaybeObject* JSReceiver::SetProperty(String* name, MaybeObject* JSReceiver::SetProperty(String* name,
Object* value, Object* value,
PropertyAttributes attributes, PropertyAttributes attributes,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode,
JSReceiver::StoreFromKeyed store_mode) {
LookupResult result(GetIsolate()); LookupResult result(GetIsolate());
LocalLookup(name, &result); 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 @@ MaybeObject* JSReceiver::SetProperty(LookupResult* result, ...@@ -2619,13 +2622,14 @@ MaybeObject* JSReceiver::SetProperty(LookupResult* result,
String* key, String* key,
Object* value, Object* value,
PropertyAttributes attributes, PropertyAttributes attributes,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode,
JSReceiver::StoreFromKeyed store_mode) {
if (result->IsFound() && result->type() == HANDLER) { if (result->IsFound() && result->type() == HANDLER) {
return result->proxy()->SetPropertyWithHandler( return result->proxy()->SetPropertyWithHandler(
this, key, value, attributes, strict_mode); this, key, value, attributes, strict_mode);
} else { } else {
return JSObject::cast(this)->SetPropertyForResult( return JSObject::cast(this)->SetPropertyForResult(
result, key, value, attributes, strict_mode); result, key, value, attributes, strict_mode, store_mode);
} }
} }
...@@ -2908,7 +2912,8 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, ...@@ -2908,7 +2912,8 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
String* name, String* name,
Object* value, Object* value,
PropertyAttributes attributes, PropertyAttributes attributes,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode,
StoreFromKeyed store_mode) {
Heap* heap = GetHeap(); Heap* heap = GetHeap();
// Make sure that the top context does not change when doing callbacks or // Make sure that the top context does not change when doing callbacks or
// interceptor calls. // interceptor calls.
...@@ -2939,7 +2944,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, ...@@ -2939,7 +2944,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
if (proto->IsNull()) return value; if (proto->IsNull()) return value;
ASSERT(proto->IsJSGlobalObject()); ASSERT(proto->IsJSGlobalObject());
return JSObject::cast(proto)->SetPropertyForResult( return JSObject::cast(proto)->SetPropertyForResult(
result, name, value, attributes, strict_mode); result, name, value, attributes, strict_mode, store_mode);
} }
if (!result->IsProperty() && !IsJSContextExtensionObject()) { if (!result->IsProperty() && !IsJSContextExtensionObject()) {
...@@ -2951,7 +2956,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, ...@@ -2951,7 +2956,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
if (!result->IsFound()) { if (!result->IsFound()) {
// Neither properties nor transitions found. // 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 (result->IsReadOnly() && result->IsProperty()) {
if (strict_mode == kStrictMode) { if (strict_mode == kStrictMode) {
......
...@@ -1353,6 +1353,13 @@ class JSReceiver: public HeapObject { ...@@ -1353,6 +1353,13 @@ class JSReceiver: public HeapObject {
FORCE_DELETION 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. // Casting.
static inline JSReceiver* cast(Object* obj); static inline JSReceiver* cast(Object* obj);
...@@ -1362,15 +1369,19 @@ class JSReceiver: public HeapObject { ...@@ -1362,15 +1369,19 @@ class JSReceiver: public HeapObject {
PropertyAttributes attributes, PropertyAttributes attributes,
StrictModeFlag strict_mode); StrictModeFlag strict_mode);
// Can cause GC. // Can cause GC.
MUST_USE_RESULT MaybeObject* SetProperty(String* key, MUST_USE_RESULT MaybeObject* SetProperty(
Object* value, String* key,
PropertyAttributes attributes, Object* value,
StrictModeFlag strict_mode); PropertyAttributes attributes,
MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result, StrictModeFlag strict_mode,
String* key, StoreFromKeyed store_from_keyed = MAY_BE_STORE_FROM_KEYED);
Object* value, MUST_USE_RESULT MaybeObject* SetProperty(
PropertyAttributes attributes, LookupResult* result,
StrictModeFlag strict_mode); 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, MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSReceiver* setter,
Object* value); Object* value);
...@@ -1524,7 +1535,8 @@ class JSObject: public JSReceiver { ...@@ -1524,7 +1535,8 @@ class JSObject: public JSReceiver {
String* key, String* key,
Object* value, Object* value,
PropertyAttributes attributes, PropertyAttributes attributes,
StrictModeFlag strict_mode); StrictModeFlag strict_mode,
StoreFromKeyed store_mode);
MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck( MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
LookupResult* result, LookupResult* result,
String* name, String* name,
...@@ -1921,9 +1933,11 @@ class JSObject: public JSReceiver { ...@@ -1921,9 +1933,11 @@ class JSObject: public JSReceiver {
PropertyAttributes attributes); PropertyAttributes attributes);
// Add a property to a fast-case object. // Add a property to a fast-case object.
MUST_USE_RESULT MaybeObject* AddFastProperty(String* name, MUST_USE_RESULT MaybeObject* AddFastProperty(
Object* value, String* name,
PropertyAttributes attributes); Object* value,
PropertyAttributes attributes,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
// Add a property to a slow-case object. // Add a property to a slow-case object.
MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name, MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
...@@ -1931,10 +1945,12 @@ class JSObject: public JSReceiver { ...@@ -1931,10 +1945,12 @@ class JSObject: public JSReceiver {
PropertyAttributes attributes); PropertyAttributes attributes);
// Add a property to an object. // Add a property to an object.
MUST_USE_RESULT MaybeObject* AddProperty(String* name, MUST_USE_RESULT MaybeObject* AddProperty(
Object* value, String* name,
PropertyAttributes attributes, Object* value,
StrictModeFlag strict_mode); PropertyAttributes attributes,
StrictModeFlag strict_mode,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
// Convert the object to use the canonical dictionary // Convert the object to use the canonical dictionary
// representation. If the object is expected to have additional properties // representation. If the object is expected to have additional properties
...@@ -2054,7 +2070,7 @@ class JSObject: public JSReceiver { ...@@ -2054,7 +2070,7 @@ class JSObject: public JSReceiver {
// Maximal number of fast properties for the JSObject. Used to // Maximal number of fast properties for the JSObject. Used to
// restrict the number of map transitions to avoid an explosion in // restrict the number of map transitions to avoid an explosion in
// the number of maps for objects used as dictionaries. // 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). // Maximal number of elements (numbered 0 .. kMaxElementCount - 1).
// Also maximal value of JSArray's length property. // Also maximal value of JSArray's length property.
...@@ -2077,7 +2093,7 @@ class JSObject: public JSReceiver { ...@@ -2077,7 +2093,7 @@ class JSObject: public JSReceiver {
static const int kInitialMaxFastElementArray = 100000; static const int kInitialMaxFastElementArray = 100000;
static const int kFastPropertiesSoftLimit = 12; static const int kFastPropertiesSoftLimit = 12;
static const int kMaxFastProperties = 32; static const int kMaxFastProperties = 64;
static const int kMaxInstanceSize = 255 * kPointerSize; static const int kMaxInstanceSize = 255 * kPointerSize;
// When extending the backing storage for property values, we increase // When extending the backing storage for property values, we increase
// its size by more than the 1 entry necessary, so sequentially adding fields // its size by more than the 1 entry necessary, so sequentially adding fields
......
// 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));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment