Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 1b8e5d20028be7391ae3e7c18adfd9a4fcb49bb7..f961e0794ddcc7009bde8431c87adb64ed2735ec 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -514,11 +514,11 @@ MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { |
// map change to invalidate any ICs that think they can load |
// from the DontDelete cell without checking if it contains |
// the hole value. |
- Object* new_map; |
+ Map* new_map; |
{ MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); |
- if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
+ if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
} |
- set_map(Map::cast(new_map)); |
+ set_map(new_map); |
} |
JSGlobalPropertyCell* cell = |
JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); |
@@ -1526,13 +1526,18 @@ MaybeObject* JSObject::AddFastProperty(String* name, |
PropertyAttributes attributes, |
StoreFromKeyed store_mode) { |
ASSERT(!IsJSGlobalProxy()); |
+ ASSERT(map()->instance_descriptors()->Search(name) == |
+ DescriptorArray::kNotFound); |
// Normalize the object if the name is an actual string (not the |
// hidden symbols) and is not a real identifier. |
+ // Normalize the object if it will have too many fast properties. |
Isolate* isolate = GetHeap()->isolate(); |
StringInputBuffer buffer(name); |
- if (!IsIdentifier(isolate->unicode_cache(), &buffer) |
- && name != isolate->heap()->hidden_symbol()) { |
+ if ((!IsIdentifier(isolate->unicode_cache(), &buffer) |
+ && name != isolate->heap()->hidden_symbol()) || |
+ (map()->unused_property_fields() == 0 && |
+ TooManyFastProperties(properties()->length(), store_mode))) { |
Object* obj; |
{ MaybeObject* maybe_obj = |
NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
@@ -1559,51 +1564,45 @@ MaybeObject* JSObject::AddFastProperty(String* name, |
bool allow_map_transition = |
(isolate->context()->global_context()->object_function()->map() != map()); |
- ASSERT(old_descriptors->Search(name) == DescriptorArray::kNotFound); |
ASSERT(index < map()->inobject_properties() || |
(index - map()->inobject_properties()) < properties()->length() || |
map()->unused_property_fields() == 0); |
+ |
danno
2012/07/11 14:17:52
nit: one space
|
+ |
// Allocate a new map for the object. |
- Object* r; |
- { MaybeObject* maybe_r = map()->CopyDropDescriptors(); |
- if (!maybe_r->ToObject(&r)) return maybe_r; |
+ Map* new_map; |
+ { MaybeObject* maybe_r = map()->CopyReplaceDescriptors(new_descriptors); |
+ if (!maybe_r->To(&new_map)) return maybe_r; |
} |
- Map* new_map = Map::cast(r); |
TransitionArray* new_transitions = NULL; |
if (allow_map_transition) { |
- MaybeObject* maybe_new_transitions = map()->AddTransition(name, new_map); |
- if (!maybe_new_transitions->To(&new_transitions)) { |
- return maybe_new_transitions; |
+ { MaybeObject* maybe_new_transitions = map()->AddTransition(name, new_map); |
danno
2012/07/11 14:17:52
Please remove
|
+ if (!maybe_new_transitions->To(&new_transitions)) { |
+ return maybe_new_transitions; |
+ } |
} |
} |
if (map()->unused_property_fields() == 0) { |
- if (TooManyFastProperties(properties()->length(), store_mode)) { |
- Object* obj; |
- { MaybeObject* maybe_obj = |
- NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
- if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
- } |
- return AddSlowProperty(name, value, attributes); |
- } |
// Make room for the new value |
- Object* values; |
+ FixedArray* values; |
{ MaybeObject* maybe_values = |
properties()->CopySize(properties()->length() + kFieldsAdded); |
- if (!maybe_values->ToObject(&values)) return maybe_values; |
+ if (!maybe_values->To(&values)) return maybe_values; |
} |
- set_properties(FixedArray::cast(values)); |
+ set_properties(values); |
new_map->set_unused_property_fields(kFieldsAdded - 1); |
} else { |
new_map->set_unused_property_fields(map()->unused_property_fields() - 1); |
} |
+ |
// Apply all changes at once, so they are atomic. |
if (allow_map_transition) { |
MaybeObject* transition_added = map()->set_transitions(new_transitions); |
if (transition_added->IsFailure()) return transition_added; |
} |
- new_map->set_instance_descriptors(new_descriptors); |
+ |
new_map->SetBackPointer(map()); |
set_map(new_map); |
return FastPropertyAtPut(index, value); |
@@ -1626,11 +1625,10 @@ MaybeObject* JSObject::AddConstantFunctionProperty( |
// Allocate a new map for the object. |
Map* new_map; |
- { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); |
+ { MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(new_descriptors); |
if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
} |
- new_map->set_instance_descriptors(new_descriptors); |
Map* old_map = map(); |
set_map(new_map); |
@@ -1860,25 +1858,17 @@ MaybeObject* JSObject::ConvertDescriptorToField(String* name, |
int index = map()->NextFreePropertyIndex(); |
FieldDescriptor new_field(name, index, attributes, 0); |
// Make a new DescriptorArray replacing an entry with FieldDescriptor. |
- Object* descriptors_unchecked; |
- { MaybeObject* maybe_descriptors_unchecked = |
+ DescriptorArray* new_descriptors; |
+ { MaybeObject* maybe_descriptors = |
map()->instance_descriptors()->CopyInsert(&new_field); |
- if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { |
- return maybe_descriptors_unchecked; |
- } |
+ if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
} |
- DescriptorArray* new_descriptors = |
- DescriptorArray::cast(descriptors_unchecked); |
// Make a new map for the object. |
- Object* new_map_unchecked; |
- { MaybeObject* maybe_new_map_unchecked = map()->CopyDropDescriptors(); |
- if (!maybe_new_map_unchecked->ToObject(&new_map_unchecked)) { |
- return maybe_new_map_unchecked; |
- } |
+ Map* new_map; |
+ { MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(new_descriptors); |
+ if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
} |
- Map* new_map = Map::cast(new_map_unchecked); |
- new_map->set_instance_descriptors(new_descriptors); |
// Make new properties array if necessary. |
FixedArray* new_properties = 0; // Will always be NULL or a valid pointer. |
@@ -4612,10 +4602,9 @@ static MaybeObject* CreateFreshAccessor(JSObject* obj, |
// step 3: create a new map with the new descriptors |
Map* map2; |
- { MaybeObject* maybe_map2 = map1->CopyDropDescriptors(); |
+ { MaybeObject* maybe_map2 = map1->CopyReplaceDescriptors(descriptors2); |
if (!maybe_map2->To(&map2)) return maybe_map2; |
} |
- map2->set_instance_descriptors(descriptors2); |
// step 4: create a new getter/setter pair with a transition to the new map |
AccessorPair* accessors1; |
@@ -4649,9 +4638,9 @@ static bool TransitionToSameAccessor(Object* map, |
AccessorComponent component, |
Object* accessor, |
PropertyAttributes attributes ) { |
- DescriptorArray* descs = Map::cast(map)->instance_descriptors(); |
+ Map* transitioned_map = Map::cast(map); |
+ DescriptorArray* descs = transitioned_map->instance_descriptors(); |
int number = descs->LastAdded(); |
- ASSERT(number != DescriptorArray::kNotFound); |
Object* target_accessor = |
AccessorPair::cast(descs->GetCallbacksObject(number))->get(component); |
PropertyAttributes target_attributes = descs->GetDetails(number).attributes(); |
@@ -4683,10 +4672,9 @@ static MaybeObject* NewCallbackTransition(JSObject* obj, |
// step 3: create a new map with the new descriptors |
Map* map3; |
- { MaybeObject* maybe_map3 = map2->CopyDropDescriptors(); |
+ { MaybeObject* maybe_map3 = map2->CopyReplaceDescriptors(descriptors3); |
if (!maybe_map3->To(&map3)) return maybe_map3; |
} |
- map3->set_instance_descriptors(descriptors3); |
// step 4: add a new transition to the new map |
TransitionArray* new_transitions; |
@@ -4909,41 +4897,18 @@ Object* JSObject::SlowReverseLookup(Object* value) { |
} |
-MaybeObject* Map::CopyDropDescriptors() { |
- Heap* heap = GetHeap(); |
- Object* result; |
+MaybeObject* Map::RawCopy(int instance_size) { |
+ Map* result; |
{ MaybeObject* maybe_result = |
- heap->AllocateMap(instance_type(), instance_size()); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
+ GetHeap()->AllocateMap(instance_type(), instance_size); |
+ if (!maybe_result->To(&result)) return maybe_result; |
} |
- Map::cast(result)->set_prototype(prototype()); |
- Map::cast(result)->set_constructor(constructor()); |
- |
- // Please note instance_type and instance_size are set when allocated. |
- Map::cast(result)->set_inobject_properties(inobject_properties()); |
- Map::cast(result)->set_unused_property_fields(unused_property_fields()); |
- // If the map has pre-allocated properties always start out with a descriptor |
- // array describing these properties. |
- if (pre_allocated_property_fields() > 0) { |
- ASSERT(constructor()->IsJSFunction()); |
- JSFunction* ctor = JSFunction::cast(constructor()); |
- Object* descriptors; |
- { MaybeObject* maybe_descriptors = |
- ctor->initial_map()->instance_descriptors()->Copy( |
- DescriptorArray::MAY_BE_SHARED); |
- if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; |
- } |
- Map::cast(result)->set_instance_descriptors( |
- DescriptorArray::cast(descriptors)); |
- Map::cast(result)->set_pre_allocated_property_fields( |
- pre_allocated_property_fields()); |
- } |
- Map::cast(result)->set_bit_field(bit_field()); |
- Map::cast(result)->set_bit_field2(bit_field2()); |
- Map::cast(result)->set_bit_field3(bit_field3()); |
- Map::cast(result)->set_is_shared(false); |
- Map::cast(result)->ClearCodeCache(heap); |
+ result->set_prototype(prototype()); |
+ result->set_constructor(constructor()); |
+ result->set_bit_field(bit_field()); |
+ result->set_bit_field2(bit_field2()); |
+ result->set_bit_field3(bit_field3()); |
return result; |
} |
@@ -4955,29 +4920,21 @@ MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, |
new_instance_size -= inobject_properties() * kPointerSize; |
} |
- Object* result; |
- { MaybeObject* maybe_result = |
- GetHeap()->AllocateMap(instance_type(), new_instance_size); |
- if (!maybe_result->ToObject(&result)) return maybe_result; |
+ Map* result; |
+ { MaybeObject* maybe_result = RawCopy(new_instance_size); |
+ if (!maybe_result->To(&result)) return maybe_result; |
} |
if (mode != CLEAR_INOBJECT_PROPERTIES) { |
- Map::cast(result)->set_inobject_properties(inobject_properties()); |
+ result->set_inobject_properties(inobject_properties()); |
} |
- Map::cast(result)->set_prototype(prototype()); |
- Map::cast(result)->set_constructor(constructor()); |
- |
- Map::cast(result)->set_bit_field(bit_field()); |
- Map::cast(result)->set_bit_field2(bit_field2()); |
- Map::cast(result)->set_bit_field3(bit_field3()); |
- Map::cast(result)->set_code_cache(code_cache()); |
- |
- Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP); |
+ result->set_code_cache(code_cache()); |
+ result->set_is_shared(sharing == SHARED_NORMALIZED_MAP); |
#ifdef DEBUG |
if (FLAG_verify_heap && Map::cast(result)->is_shared()) { |
- Map::cast(result)->SharedMapVerify(); |
+ result->SharedMapVerify(); |
} |
#endif |
@@ -4985,19 +4942,56 @@ MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, |
} |
-MaybeObject* Map::CopyDropTransitions( |
- DescriptorArray::SharedMode shared_mode) { |
- Object* new_map; |
- { MaybeObject* maybe_new_map = CopyDropDescriptors(); |
- if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
+MaybeObject* Map::CopyDropDescriptors() { |
+ Map* result; |
+ { MaybeObject* maybe_result = RawCopy(instance_size()); |
+ if (!maybe_result->To(&result)) return maybe_result; |
} |
- Object* descriptors; |
+ |
+ // Please note instance_type and instance_size are set when allocated. |
+ result->set_inobject_properties(inobject_properties()); |
+ result->set_unused_property_fields(unused_property_fields()); |
+ |
+ result->set_pre_allocated_property_fields(pre_allocated_property_fields()); |
+ result->set_is_shared(false); |
+ result->ClearCodeCache(GetHeap()); |
+ return result; |
+} |
+ |
+ |
+MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors) { |
+ Map* result; |
+ { MaybeObject* maybe_result = CopyDropDescriptors(); |
+ if (!maybe_result->To(&result)) return maybe_result; |
+ } |
+ result->set_instance_descriptors(descriptors); |
+ return result; |
+} |
+ |
+ |
+MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() { |
+ if (pre_allocated_property_fields() == 0) return CopyDropDescriptors(); |
+ |
+ // If the map has pre-allocated properties always start out with a descriptor |
+ // array describing these properties. |
+ ASSERT(constructor()->IsJSFunction()); |
+ JSFunction* ctor = JSFunction::cast(constructor()); |
+ DescriptorArray* descriptors; |
{ MaybeObject* maybe_descriptors = |
- instance_descriptors()->Copy(shared_mode); |
- if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; |
+ ctor->initial_map()->instance_descriptors()->Copy( |
+ DescriptorArray::MAY_BE_SHARED); |
+ if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
} |
- cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); |
- return new_map; |
+ return CopyReplaceDescriptors(descriptors); |
+} |
+ |
+ |
+MaybeObject* Map::CopyDropTransitions(DescriptorArray::SharedMode shared_mode) { |
+ DescriptorArray* descriptors; |
+ { MaybeObject* maybe_descriptors = instance_descriptors()->Copy(shared_mode); |
+ if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors; |
+ } |
+ return CopyReplaceDescriptors(descriptors); |
} |
@@ -5928,6 +5922,7 @@ MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor) { |
ASSERT(insertion_index < new_descriptors->number_of_descriptors()); |
new_descriptors->Set(insertion_index, descriptor, witness); |
+ |
if (!replacing) { |
new_descriptors->SetLastAdded(insertion_index); |
} else { |
@@ -12765,15 +12760,16 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
descriptors->Sort(witness); |
// Allocate new map. |
- Object* new_map; |
- { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors(); |
- if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
+ Map* new_map; |
+ { MaybeObject* maybe_new_map = |
+ obj->map()->CopyReplaceDescriptors(descriptors); |
+ if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
} |
+ new_map->set_unused_property_fields(unused_property_fields); |
+ |
// Transform the object. |
- obj->set_map(Map::cast(new_map)); |
- obj->map()->set_instance_descriptors(descriptors); |
- obj->map()->set_unused_property_fields(unused_property_fields); |
+ obj->set_map(new_map); |
obj->set_properties(FixedArray::cast(fields)); |
ASSERT(obj->IsJSObject()); |