Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 5a1daa2fc201301b311fc25f3ae28bcbf5784075..263e29111f05f87c2909bc547a09a32579a4de5c 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -1824,48 +1824,98 @@ String* JSReceiver::constructor_name() { |
} |
-void JSObject::AddFastProperty(Handle<JSObject> object, |
- Handle<Name> name, |
- Handle<Object> value, |
- PropertyAttributes attributes, |
- StoreFromKeyed store_mode, |
- ValueType value_type, |
- TransitionFlag flag) { |
- ASSERT(!object->IsJSGlobalProxy()); |
+MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, |
+ Handle<Name> name, |
+ Handle<HeapType> type, |
+ PropertyAttributes attributes, |
+ Representation representation, |
+ TransitionFlag flag) { |
ASSERT(DescriptorArray::kNotFound == |
- object->map()->instance_descriptors()->Search( |
- *name, object->map()->NumberOfOwnDescriptors())); |
+ map->instance_descriptors()->Search( |
+ *name, map->NumberOfOwnDescriptors())); |
+ |
+ // Ensure the descriptor array does not get too big. |
+ if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) { |
+ return MaybeHandle<Map>(); |
+ } |
// Normalize the object if the name is an actual name (not the |
// hidden strings) and is not a real identifier. |
// Normalize the object if it will have too many fast properties. |
- Isolate* isolate = object->GetIsolate(); |
- if (!name->IsCacheable(isolate) || |
- object->TooManyFastProperties(store_mode)) { |
- NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
- AddSlowProperty(object, name, value, attributes); |
- return; |
- } |
- |
- // Allocate new instance descriptors with (name, index) added |
- if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; |
- Representation representation = value->OptimalRepresentation(value_type); |
+ Isolate* isolate = map->GetIsolate(); |
+ if (!name->IsCacheable(isolate)) return MaybeHandle<Map>(); |
// Compute the new index for new field. |
- int index = object->map()->NextFreePropertyIndex(); |
+ int index = map->NextFreePropertyIndex(); |
+ |
+ if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) { |
+ representation = Representation::Tagged(); |
+ type = HeapType::Any(isolate); |
+ } |
- Handle<HeapType> type = value->OptimalType(isolate, representation); |
FieldDescriptor new_field_desc(name, index, type, attributes, representation); |
- Handle<Map> new_map = Map::CopyAddDescriptor( |
- handle(object->map()), &new_field_desc, flag); |
+ Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag); |
int unused_property_fields = new_map->unused_property_fields() - 1; |
if (unused_property_fields < 0) { |
unused_property_fields += JSObject::kFieldsAdded; |
} |
new_map->set_unused_property_fields(unused_property_fields); |
+ return new_map; |
+} |
+ |
+ |
+MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map, |
+ Handle<Name> name, |
+ Handle<Object> constant, |
+ PropertyAttributes attributes, |
+ TransitionFlag flag) { |
+ // Ensure the descriptor array does not get too big. |
+ if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) { |
+ return MaybeHandle<Map>(); |
+ } |
+ |
+ // Allocate new instance descriptors with (name, constant) added. |
+ ConstantDescriptor new_constant_desc(name, constant, attributes); |
+ return Map::CopyAddDescriptor(map, &new_constant_desc, flag); |
+} |
+ |
+ |
+void JSObject::AddFastProperty(Handle<JSObject> object, |
+ Handle<Name> name, |
+ Handle<Object> value, |
+ PropertyAttributes attributes, |
+ StoreFromKeyed store_mode, |
+ ValueType value_type, |
+ TransitionFlag flag) { |
+ ASSERT(!object->IsJSGlobalProxy()); |
+ |
+ MaybeHandle<Map> maybe_map; |
+ if (value->IsJSFunction()) { |
+ maybe_map = Map::CopyWithConstant( |
+ handle(object->map()), name, value, attributes, flag); |
+ } else if (!object->TooManyFastProperties(store_mode)) { |
+ Isolate* isolate = object->GetIsolate(); |
+ Representation representation = value->OptimalRepresentation(value_type); |
+ maybe_map = Map::CopyWithField( |
+ handle(object->map(), isolate), name, |
+ value->OptimalType(isolate, representation), |
+ attributes, representation, flag); |
+ } |
+ |
+ Handle<Map> new_map; |
+ if (!maybe_map.ToHandle(&new_map)) { |
+ NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
+ return; |
+ } |
JSObject::MigrateToMap(object, new_map); |
+ PropertyDetails details = new_map->GetLastDescriptorDetails(); |
+ if (details.type() != FIELD) return; |
+ |
+ Representation representation = details.representation(); |
+ int index = details.field_index(); |
+ |
if (representation.IsDouble()) { |
// Nothing more to be done. |
if (value->IsUninitialized()) return; |
@@ -1877,24 +1927,6 @@ void JSObject::AddFastProperty(Handle<JSObject> object, |
} |
-void JSObject::AddConstantProperty(Handle<JSObject> object, |
- Handle<Name> name, |
- Handle<Object> constant, |
- PropertyAttributes attributes, |
- TransitionFlag initial_flag) { |
- ASSERT(!object->IsGlobalObject()); |
- // Don't add transitions to special properties with non-trivial attributes. |
- TransitionFlag flag = attributes != NONE ? OMIT_TRANSITION : initial_flag; |
- |
- // Allocate new instance descriptors with (name, constant) added. |
- ConstantDescriptor new_constant_desc(name, constant, attributes); |
- Handle<Map> new_map = Map::CopyAddDescriptor( |
- handle(object->map()), &new_constant_desc, flag); |
- |
- JSObject::MigrateToMap(object, new_map); |
-} |
- |
- |
void JSObject::AddSlowProperty(Handle<JSObject> object, |
Handle<Name> name, |
Handle<Object> value, |
@@ -1959,25 +1991,11 @@ MaybeHandle<Object> JSObject::AddProperty( |
} |
if (object->HasFastProperties()) { |
- // Ensure the descriptor array does not get too big. |
- if (object->map()->NumberOfOwnDescriptors() <= kMaxNumberOfDescriptors) { |
- // TODO(verwaest): Support other constants. |
- // if (mode == ALLOW_AS_CONSTANT && |
- // !value->IsTheHole() && |
- // !value->IsConsString()) { |
- if (value->IsJSFunction()) { |
- AddConstantProperty(object, name, value, attributes, transition_flag); |
- } else { |
- AddFastProperty(object, name, value, attributes, store_mode, |
- value_type, transition_flag); |
- } |
- } else { |
- // Normalize the object to prevent very large instance descriptors. |
- // This eliminates unwanted N^2 allocation and lookup behavior. |
- NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
- AddSlowProperty(object, name, value, attributes); |
- } |
- } else { |
+ AddFastProperty(object, name, value, attributes, store_mode, |
+ value_type, transition_flag); |
+ } |
+ |
+ if (!object->HasFastProperties()) { |
AddSlowProperty(object, name, value, attributes); |
} |
@@ -6613,15 +6631,6 @@ static bool TryAccessorTransition(Handle<JSObject> self, |
} |
-static Handle<Map> CopyInsertDescriptor(Handle<Map> map, |
- Handle<Name> name, |
- Handle<AccessorPair> accessors, |
- PropertyAttributes attributes) { |
- CallbacksDescriptor new_accessors_desc(name, accessors, attributes); |
- return Map::CopyInsertDescriptor(map, &new_accessors_desc, INSERT_TRANSITION); |
-} |
- |
- |
bool JSObject::DefineFastAccessor(Handle<JSObject> object, |
Handle<Name> name, |
AccessorComponent component, |
@@ -6686,8 +6695,11 @@ bool JSObject::DefineFastAccessor(Handle<JSObject> object, |
? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) |
: isolate->factory()->NewAccessorPair(); |
accessors->set(component, *accessor); |
- Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()), |
- name, accessors, attributes); |
+ |
+ CallbacksDescriptor new_accessors_desc(name, accessors, attributes); |
+ Handle<Map> new_map = Map::CopyInsertDescriptor( |
+ handle(object->map()), &new_accessors_desc, INSERT_TRANSITION); |
+ |
JSObject::MigrateToMap(object, new_map); |
return true; |
} |