Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index da751477338fefbb40ac95ab22a8e658fd21a687..3c05985a66f5f9636e460d50eb68f2c64e728d8f 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -1282,12 +1282,23 @@ MaybeObject* JSObject::AddFastProperty(String* name, |
| } |
| } |
| - // Only allow map transition if the object's map is NOT equal to the |
| - // global object_function's map and there is not a transition for name. |
| + // Only allow map transition if the object isn't the global object and there |
| + // is not a transition for the name, or there's a transition for the name but |
| + // it's unrelated to properties. |
| + int descriptor_index = old_descriptors->Search(name); |
| + |
| + // External array transitions are stored in the descriptor for property "", |
| + // which is not a identifier and should have forced a switch to slow |
| + // properties above. |
| + ASSERT( |
|
Mads Ager (chromium)
2011/03/22 18:57:25
Move fist disjunct of the assert to the first line
danno
2011/03/23 09:56:52
Done.
|
| + descriptor_index == DescriptorArray::kNotFound || |
| + old_descriptors->GetType(descriptor_index) != EXTERNAL_ARRAY_TRANSITION); |
| + bool can_insert_transition = |
| + (descriptor_index == DescriptorArray::kNotFound || |
| + old_descriptors->GetType(descriptor_index) == EXTERNAL_ARRAY_TRANSITION); |
| bool allow_map_transition = |
| - !old_descriptors->Contains(name) && |
| - (isolate->context()->global_context()->object_function()-> |
| - map() != map()); |
| + can_insert_transition && |
| + (isolate->context()->global_context()->object_function()->map() != map()); |
| ASSERT(index < map()->inobject_properties() || |
| (index - map()->inobject_properties()) < properties()->length() || |
| @@ -1819,6 +1830,78 @@ void Map::LookupInDescriptors(JSObject* holder, |
| } |
| +MaybeObject* Map::GetExternalArrayElementsMap(ExternalArrayType array_type, |
| + bool safe_to_add_transition) { |
| + DescriptorArray* descriptors = instance_descriptors(); |
| + String* external_array_sentinel_name = HEAP->empty_symbol(); |
|
Mads Ager (chromium)
2011/03/22 18:57:25
Let's replace HEAP with GetIsolate()->heap() here
danno
2011/03/23 09:56:52
Done.
|
| + |
| + if (safe_to_add_transition) { |
| + // It's only safe to manipulate the descriptor array if it would be |
| + // safe to add a transition. |
| + |
| + ASSERT(!is_shared()); // no transitions can be added to shared maps. |
| + // Check if the external array transition already exists. |
| + DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache(); |
| + int index = cache->Lookup(descriptors, external_array_sentinel_name); |
| + if (index == DescriptorLookupCache::kAbsent) { |
| + index = descriptors->Search(external_array_sentinel_name); |
| + cache->Update(descriptors, |
| + external_array_sentinel_name, |
| + index); |
| + } |
| + |
| + // If the transition already exists, check the type. If there is a match, |
| + // return it. |
| + if (index != DescriptorArray::kNotFound) { |
| + PropertyDetails details(PropertyDetails(descriptors->GetDetails(index))); |
| + if (details.type() == EXTERNAL_ARRAY_TRANSITION && |
| + details.array_type() == array_type) { |
| + return descriptors->GetValue(index); |
| + } else { |
| + safe_to_add_transition = false; |
| + } |
| + } |
| + } |
| + |
| + // No transition to an existing external array map. Make a new one. |
| + Object* obj; |
| + { MaybeObject* maybe_map = CopyDropTransitions(); |
| + if (!maybe_map->ToObject(&obj)) return maybe_map; |
| + } |
| + Map* new_map = Map::cast(obj); |
| + |
| + new_map->set_has_fast_elements(false); |
| + new_map->set_has_external_array_elements(true); |
| + COUNTERS->map_to_external_array_elements()->Increment(); |
|
Mads Ager (chromium)
2011/03/22 18:57:25
GetIsolate()->counters() instead of COUNTERS.
danno
2011/03/23 09:56:52
Done.
|
| + |
| + // Only remember the map transition if the object's map is NOT equal to the |
| + // global object_function's map and there is not an already existing |
| + // non-matching external array transition. |
| + Heap* heap = GetHeap(); |
| + bool allow_map_transition = |
| + safe_to_add_transition && |
| + (heap->isolate()->context()->global_context()->object_function()->map() != |
|
Mads Ager (chromium)
2011/03/22 18:57:25
Instead of getting the heap and using heap->isolat
danno
2011/03/23 09:56:52
Done.
|
| + map()); |
| + if (allow_map_transition) { |
| + // Allocate new instance descriptors for the old map with map transition. |
| + ExternalArrayTransitionDescriptor desc(external_array_sentinel_name, |
| + Map::cast(new_map), |
| + array_type); |
| + Object* new_descriptors; |
| + MaybeObject* maybe_new_descriptors = descriptors->CopyInsert( |
| + &desc, |
| + KEEP_TRANSITIONS); |
| + if (!maybe_new_descriptors->ToObject(&new_descriptors)) { |
| + return maybe_new_descriptors; |
| + } |
| + descriptors = DescriptorArray::cast(new_descriptors); |
| + set_instance_descriptors(descriptors); |
| + } |
| + |
| + return new_map; |
| +} |
| + |
| + |
| void JSObject::LocalLookupRealNamedProperty(String* name, |
| LookupResult* result) { |
| if (IsJSGlobalProxy()) { |
| @@ -2051,6 +2134,7 @@ MaybeObject* JSObject::SetProperty(LookupResult* result, |
| return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
| } |
| case NULL_DESCRIPTOR: |
| + case EXTERNAL_ARRAY_TRANSITION: |
| return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
| default: |
| UNREACHABLE(); |
| @@ -2130,6 +2214,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( |
| // if the value is a function. |
| return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
| case NULL_DESCRIPTOR: |
| + case EXTERNAL_ARRAY_TRANSITION: |
| return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
| default: |
| UNREACHABLE(); |
| @@ -5486,6 +5571,7 @@ void Map::CreateBackPointers() { |
| DescriptorArray* descriptors = instance_descriptors(); |
| for (int i = 0; i < descriptors->number_of_descriptors(); i++) { |
| if (descriptors->GetType(i) == MAP_TRANSITION || |
| + descriptors->GetType(i) == EXTERNAL_ARRAY_TRANSITION || |
| descriptors->GetType(i) == CONSTANT_TRANSITION) { |
| // Get target. |
| Map* target = Map::cast(descriptors->GetValue(i)); |
| @@ -5528,6 +5614,7 @@ void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) { |
| // non-live object. |
| PropertyDetails details(Smi::cast(contents->get(i + 1))); |
| if (details.type() == MAP_TRANSITION || |
| + details.type() == EXTERNAL_ARRAY_TRANSITION || |
| details.type() == CONSTANT_TRANSITION) { |
| Map* target = reinterpret_cast<Map*>(contents->get(i)); |
| ASSERT(target->IsHeapObject()); |
| @@ -6401,6 +6488,7 @@ const char* Code::PropertyType2String(PropertyType type) { |
| case CALLBACKS: return "CALLBACKS"; |
| case INTERCEPTOR: return "INTERCEPTOR"; |
| case MAP_TRANSITION: return "MAP_TRANSITION"; |
| + case EXTERNAL_ARRAY_TRANSITION: return "EXTERNAL_ARRAY_TRANSITION"; |
| case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION"; |
| case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR"; |
| } |