Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 2bf5b4a4a0bc760ba695038e247406497a9b9725..3f6560eebf543c556a7852f85c7974729687a53d 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2548,8 +2548,7 @@ Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, |
new_map->NumberOfFields(), |
attributes, |
Representation::Tagged()); |
- d.SetSortedKeyIndex(details.pointer()); |
- descriptors->Set(modify_index, &d); |
+ descriptors->Replace(modify_index, &d); |
int unused_property_fields = new_map->unused_property_fields() - 1; |
if (unused_property_fields < 0) { |
unused_property_fields += JSObject::kFieldsAdded; |
@@ -3121,16 +3120,40 @@ MaybeHandle<Object> JSObject::SetPropertyViaPrototypes( |
void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) { |
+ // Only supports adding slack to owned descriptors. |
+ ASSERT(map->owns_descriptors()); |
+ |
Handle<DescriptorArray> descriptors(map->instance_descriptors()); |
+ int old_size = map->NumberOfOwnDescriptors(); |
if (slack <= descriptors->NumberOfSlackDescriptors()) return; |
- int number_of_descriptors = descriptors->number_of_descriptors(); |
- Isolate* isolate = map->GetIsolate(); |
- Handle<DescriptorArray> new_descriptors = |
- isolate->factory()->NewDescriptorArray(number_of_descriptors, slack); |
- DescriptorArray::WhitenessWitness witness(*new_descriptors); |
- for (int i = 0; i < number_of_descriptors; ++i) { |
- new_descriptors->CopyFrom(i, *descriptors, i, witness); |
+ Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( |
+ descriptors, old_size, slack); |
+ |
+ if (old_size == 0) { |
+ map->set_instance_descriptors(*new_descriptors); |
+ return; |
+ } |
+ |
+ // If the source descriptors had an enum cache we copy it. This ensures |
+ // that the maps to which we push the new descriptor array back can rely |
+ // on a cache always being available once it is set. If the map has more |
+ // enumerated descriptors than available in the original cache, the cache |
+ // will be lazily replaced by the extended cache when needed. |
+ if (descriptors->HasEnumCache()) { |
+ new_descriptors->CopyEnumCacheFrom(*descriptors); |
+ } |
+ |
+ // Replace descriptors by new_descriptors in all maps that share it. |
+ map->GetHeap()->incremental_marking()->RecordWrites(*descriptors); |
+ |
+ Map* walk_map; |
+ for (Object* current = map->GetBackPointer(); |
+ !current->IsUndefined(); |
+ current = walk_map->GetBackPointer()) { |
+ walk_map = Map::cast(current); |
+ if (walk_map->instance_descriptors() != *descriptors) break; |
+ walk_map->set_instance_descriptors(*new_descriptors); |
} |
map->set_instance_descriptors(*new_descriptors); |
@@ -6840,62 +6863,29 @@ Handle<Map> Map::ShareDescriptor(Handle<Map> map, |
// descriptors in the descriptor array. |
ASSERT(map->NumberOfOwnDescriptors() == |
map->instance_descriptors()->number_of_descriptors()); |
- Handle<Map> result = Map::CopyDropDescriptors(map); |
+ Handle<Map> result = Map::CopyDropDescriptors(map); |
Handle<Name> name = descriptor->GetKey(); |
- |
Handle<TransitionArray> transitions = |
Map::AddTransition(map, name, result, SIMPLE_TRANSITION); |
- if (descriptors->NumberOfSlackDescriptors() > 0) { |
- descriptors->Append(descriptor); |
- result->SetBackPointer(*map); |
- result->InitializeDescriptors(*descriptors); |
- } else { |
+ // Ensure there's space for the new descriptor in the shared descriptor array. |
+ if (descriptors->NumberOfSlackDescriptors() == 0) { |
int old_size = descriptors->number_of_descriptors(); |
- // Descriptor arrays grow by 50%. |
- Handle<DescriptorArray> new_descriptors = |
- map->GetIsolate()->factory()->NewDescriptorArray( |
- old_size, old_size < 4 ? 1 : old_size / 2); |
- |
- DisallowHeapAllocation no_gc; |
- DescriptorArray::WhitenessWitness witness(*new_descriptors); |
- |
- // Copy the descriptors, inserting a descriptor. |
- for (int i = 0; i < old_size; ++i) { |
- new_descriptors->CopyFrom(i, *descriptors, i, witness); |
+ if (old_size == 0) { |
+ descriptors = map->GetIsolate()->factory()->NewDescriptorArray(0, 1); |
+ } else { |
+ Map::EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2); |
+ descriptors = handle(map->instance_descriptors()); |
} |
+ } |
- new_descriptors->Append(descriptor, witness); |
- |
- if (old_size > 0) { |
- // If the source descriptors had an enum cache we copy it. This ensures |
- // that the maps to which we push the new descriptor array back can rely |
- // on a cache always being available once it is set. If the map has more |
- // enumerated descriptors than available in the original cache, the cache |
- // will be lazily replaced by the extended cache when needed. |
- if (descriptors->HasEnumCache()) { |
- new_descriptors->CopyEnumCacheFrom(*descriptors); |
- } |
- |
- Map* walk_map; |
- // Replace descriptors by new_descriptors in all maps that share it. |
- |
- map->GetHeap()->incremental_marking()->RecordWrites(*descriptors); |
- for (Object* current = map->GetBackPointer(); |
- !current->IsUndefined(); |
- current = walk_map->GetBackPointer()) { |
- walk_map = Map::cast(current); |
- if (walk_map->instance_descriptors() != *descriptors) break; |
- walk_map->set_instance_descriptors(*new_descriptors); |
- } |
- |
- map->set_instance_descriptors(*new_descriptors); |
- } |
+ // Commit the state atomically. |
+ DisallowHeapAllocation no_gc; |
- result->SetBackPointer(*map); |
- result->InitializeDescriptors(*new_descriptors); |
- } |
+ descriptors->Append(descriptor); |
+ result->SetBackPointer(*map); |
+ result->InitializeDescriptors(*descriptors); |
ASSERT(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); |
@@ -7098,36 +7088,18 @@ Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, |
// Ensure the key is unique. |
descriptor->KeyToUniqueName(); |
- int old_size = map->NumberOfOwnDescriptors(); |
- int new_size = old_size + 1; |
- |
if (flag == INSERT_TRANSITION && |
map->owns_descriptors() && |
map->CanHaveMoreTransitions()) { |
return Map::ShareDescriptor(map, descriptors, descriptor); |
} |
- Handle<DescriptorArray> new_descriptors = |
- map->GetIsolate()->factory()->NewDescriptorArray(old_size, 1); |
- |
- DescriptorArray::WhitenessWitness witness(*new_descriptors); |
- |
- // Copy the descriptors, inserting a descriptor. |
- for (int i = 0; i < old_size; ++i) { |
- new_descriptors->CopyFrom(i, *descriptors, i, witness); |
- } |
- |
- if (old_size != descriptors->number_of_descriptors()) { |
- new_descriptors->SetNumberOfDescriptors(new_size); |
- new_descriptors->Set(old_size, descriptor, witness); |
- new_descriptors->Sort(); |
- } else { |
- new_descriptors->Append(descriptor, witness); |
- } |
+ Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( |
+ descriptors, map->NumberOfOwnDescriptors(), 1); |
+ new_descriptors->Append(descriptor); |
- Handle<Name> key = descriptor->GetKey(); |
return Map::CopyReplaceDescriptors( |
- map, new_descriptors, flag, key, SIMPLE_TRANSITION); |
+ map, new_descriptors, flag, descriptor->GetKey(), SIMPLE_TRANSITION); |
} |
@@ -7151,25 +7123,26 @@ Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map, |
Handle<DescriptorArray> DescriptorArray::CopyUpTo( |
Handle<DescriptorArray> desc, |
- int enumeration_index) { |
- return DescriptorArray::CopyUpToAddAttributes(desc, |
- enumeration_index, |
- NONE); |
+ int enumeration_index, |
+ int slack) { |
+ return DescriptorArray::CopyUpToAddAttributes( |
+ desc, enumeration_index, NONE, slack); |
} |
Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes( |
Handle<DescriptorArray> desc, |
int enumeration_index, |
- PropertyAttributes attributes) { |
- if (enumeration_index == 0) { |
+ PropertyAttributes attributes, |
+ int slack) { |
+ if (enumeration_index + slack == 0) { |
return desc->GetIsolate()->factory()->empty_descriptor_array(); |
} |
int size = enumeration_index; |
Handle<DescriptorArray> descriptors = |
- desc->GetIsolate()->factory()->NewDescriptorArray(size); |
+ desc->GetIsolate()->factory()->NewDescriptorArray(size, slack); |
DescriptorArray::WhitenessWitness witness(*descriptors); |
if (attributes != NONE) { |
@@ -7190,7 +7163,7 @@ Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes( |
} |
} else { |
for (int i = 0; i < size; ++i) { |
- descriptors->CopyFrom(i, *desc, i, witness); |
+ descriptors->CopyFrom(i, *desc, witness); |
} |
} |
@@ -7211,24 +7184,10 @@ Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map, |
Handle<Name> key = descriptor->GetKey(); |
ASSERT(*key == descriptors->GetKey(insertion_index)); |
- int new_size = map->NumberOfOwnDescriptors(); |
- ASSERT(0 <= insertion_index && insertion_index < new_size); |
- |
- ASSERT_LT(insertion_index, new_size); |
- |
- Handle<DescriptorArray> new_descriptors = |
- map->GetIsolate()->factory()->NewDescriptorArray(new_size); |
- DescriptorArray::WhitenessWitness witness(*new_descriptors); |
- |
- for (int i = 0; i < new_size; ++i) { |
- if (i == insertion_index) { |
- new_descriptors->Set(i, descriptor, witness); |
- } else { |
- new_descriptors->CopyFrom(i, *descriptors, i, witness); |
- } |
- } |
+ Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo( |
+ descriptors, map->NumberOfOwnDescriptors()); |
- new_descriptors->Sort(); |
+ new_descriptors->Replace(insertion_index, descriptor); |
SimpleTransitionFlag simple_flag = |
(insertion_index == descriptors->number_of_descriptors() - 1) |
@@ -8058,6 +8017,12 @@ void DescriptorArray::ClearEnumCache() { |
} |
+void DescriptorArray::Replace(int index, Descriptor* descriptor) { |
+ descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index)); |
+ Set(index, descriptor); |
+} |
+ |
+ |
void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
FixedArray* new_cache, |
Object* new_index_cache) { |
@@ -8073,16 +8038,15 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
} |
-void DescriptorArray::CopyFrom(int dst_index, |
+void DescriptorArray::CopyFrom(int index, |
DescriptorArray* src, |
- int src_index, |
const WhitenessWitness& witness) { |
- Object* value = src->GetValue(src_index); |
- PropertyDetails details = src->GetDetails(src_index); |
- Descriptor desc(handle(src->GetKey(src_index)), |
+ Object* value = src->GetValue(index); |
+ PropertyDetails details = src->GetDetails(index); |
+ Descriptor desc(handle(src->GetKey(index)), |
handle(value, src->GetIsolate()), |
details); |
- Set(dst_index, &desc, witness); |
+ Set(index, &desc, witness); |
} |