Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 802a4342884138667e1d0c9aa579515a44e7a02c..6fe947bb92c13378c28019bf6950c6bca9eaa568 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2074,15 +2074,10 @@ bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields, |
} |
-Handle<TransitionArray> Map::SetElementsTransitionMap( |
- Handle<Map> map, Handle<Map> transitioned_map) { |
- Handle<TransitionArray> transitions = TransitionArray::CopyInsert( |
- map, |
- map->GetIsolate()->factory()->elements_transition_symbol(), |
- transitioned_map, |
- FULL_TRANSITION); |
- map->set_transitions(*transitions); |
- return transitions; |
+void Map::ConnectElementsTransition(Handle<Map> parent, Handle<Map> child) { |
+ Isolate* isolate = parent->GetIsolate(); |
+ Handle<Name> name = isolate->factory()->elements_transition_symbol(); |
+ ConnectTransition(parent, child, name, FULL_TRANSITION); |
} |
@@ -2090,7 +2085,17 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) { |
if (object->map() == *new_map) return; |
if (object->HasFastProperties()) { |
if (!new_map->is_dictionary_map()) { |
+ Handle<Map> old_map(object->map()); |
MigrateFastToFast(object, new_map); |
+ if (old_map->is_prototype_map()) { |
+ // Clear out the old descriptor array to avoid problems to sharing |
+ // the descriptor array without using an explicit. |
+ old_map->InitializeDescriptors( |
+ old_map->GetHeap()->empty_descriptor_array()); |
+ // Ensure that no transition was inserted for prototype migrations. |
+ DCHECK(!old_map->HasTransitionArray()); |
+ DCHECK(new_map->GetBackPointer()->IsUndefined()); |
+ } |
} else { |
MigrateFastToSlow(object, new_map, 0); |
} |
@@ -3459,10 +3464,12 @@ static Handle<Map> AddMissingElementsTransitions(Handle<Map> map, |
Handle<Map> current_map = map; |
ElementsKind kind = map->elements_kind(); |
- while (kind != to_kind && !IsTerminalElementsKind(kind)) { |
- kind = GetNextTransitionElementsKind(kind); |
- current_map = Map::CopyAsElementsKind( |
- current_map, kind, INSERT_TRANSITION); |
+ if (!map->is_prototype_map()) { |
+ while (kind != to_kind && !IsTerminalElementsKind(kind)) { |
+ kind = GetNextTransitionElementsKind(kind); |
+ current_map = |
+ Map::CopyAsElementsKind(current_map, kind, INSERT_TRANSITION); |
+ } |
} |
// In case we are exiting the fast elements kind system, just add the map in |
@@ -5708,7 +5715,7 @@ MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) { |
Handle<Map> new_map = Map::CopyForFreeze(old_map); |
JSObject::MigrateToMap(object, new_map); |
} else { |
- ASSERT(!old_map->is_prototype_map()); |
+ DCHECK(!old_map->is_prototype_map()); |
// Slow path: need to normalize properties for safety |
NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
@@ -7110,8 +7117,6 @@ Handle<Map> Map::ShareDescriptor(Handle<Map> map, |
Handle<Map> result = CopyDropDescriptors(map); |
Handle<Name> name = descriptor->GetKey(); |
- Handle<TransitionArray> transitions = |
- TransitionArray::CopyInsert(map, name, result, SIMPLE_TRANSITION); |
// Ensure there's space for the new descriptor in the shared descriptor array. |
if (descriptors->NumberOfSlackDescriptors() == 0) { |
@@ -7124,22 +7129,33 @@ Handle<Map> Map::ShareDescriptor(Handle<Map> map, |
} |
} |
- // Commit the state atomically. |
- DisallowHeapAllocation no_gc; |
- |
- descriptors->Append(descriptor); |
- result->SetBackPointer(*map); |
- result->InitializeDescriptors(*descriptors); |
+ { |
+ DisallowHeapAllocation no_gc; |
+ descriptors->Append(descriptor); |
+ result->InitializeDescriptors(*descriptors); |
+ } |
DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); |
- |
- map->set_transitions(*transitions); |
- map->set_owns_descriptors(false); |
+ ConnectTransition(map, result, name, SIMPLE_TRANSITION); |
return result; |
} |
+void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child, |
+ Handle<Name> name, SimpleTransitionFlag flag) { |
+ parent->set_owns_descriptors(false); |
+ if (parent->is_prototype_map()) { |
+ DCHECK(child->is_prototype_map()); |
+ } else { |
+ Handle<TransitionArray> transitions = |
+ TransitionArray::CopyInsert(parent, name, child, flag); |
+ parent->set_transitions(*transitions); |
+ child->SetBackPointer(*parent); |
+ } |
+} |
+ |
+ |
Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, |
Handle<DescriptorArray> descriptors, |
TransitionFlag flag, |
@@ -7150,19 +7166,18 @@ Handle<Map> Map::CopyReplaceDescriptors(Handle<Map> map, |
Handle<Map> result = CopyDropDescriptors(map); |
result->InitializeDescriptors(*descriptors); |
- if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { |
- Handle<Name> name; |
- CHECK(maybe_name.ToHandle(&name)); |
- Handle<TransitionArray> transitions = TransitionArray::CopyInsert( |
- map, name, result, simple_flag); |
- map->set_transitions(*transitions); |
- result->SetBackPointer(*map); |
- } else { |
- int length = descriptors->number_of_descriptors(); |
- for (int i = 0; i < length; i++) { |
- descriptors->SetRepresentation(i, Representation::Tagged()); |
- if (descriptors->GetDetails(i).type() == FIELD) { |
- descriptors->SetValue(i, HeapType::Any()); |
+ if (!map->is_prototype_map()) { |
+ if (flag == INSERT_TRANSITION && map->CanHaveMoreTransitions()) { |
+ Handle<Name> name; |
+ CHECK(maybe_name.ToHandle(&name)); |
+ ConnectTransition(map, result, name, simple_flag); |
+ } else { |
+ int length = descriptors->number_of_descriptors(); |
+ for (int i = 0; i < length; i++) { |
+ descriptors->SetRepresentation(i, Representation::Tagged()); |
+ if (descriptors->GetDetails(i).type() == FIELD) { |
+ descriptors->SetValue(i, HeapType::Any()); |
+ } |
} |
} |
} |
@@ -7195,11 +7210,7 @@ Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map, |
result->set_owns_descriptors(false); |
Igor Sheludko
2014/08/04 14:25:55
This is going to be done again in ConnectTransitio
|
Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); |
- Handle<TransitionArray> transitions = TransitionArray::CopyInsert( |
- map, name, result, SIMPLE_TRANSITION); |
- |
- map->set_transitions(*transitions); |
- result->SetBackPointer(*map); |
+ ConnectTransition(map, result, name, SIMPLE_TRANSITION); |
return result; |
} |
@@ -7228,12 +7239,10 @@ Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, |
// transfer ownership to the new map. |
Handle<Map> new_map = CopyDropDescriptors(map); |
- SetElementsTransitionMap(map, new_map); |
+ ConnectElementsTransition(map, new_map); |
new_map->set_elements_kind(kind); |
new_map->InitializeDescriptors(map->instance_descriptors()); |
- new_map->SetBackPointer(*map); |
- map->set_owns_descriptors(false); |
return new_map; |
} |
@@ -7245,8 +7254,7 @@ Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind, |
new_map->set_elements_kind(kind); |
if (insert_transition) { |
- SetElementsTransitionMap(map, new_map); |
- new_map->SetBackPointer(*map); |
+ ConnectElementsTransition(map, new_map); |
} |
return new_map; |
@@ -7264,22 +7272,18 @@ Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
if (map->owns_descriptors()) { |
new_map = CopyDropDescriptors(map); |
} else { |
+ DCHECK(!map->is_prototype_map()); |
new_map = Copy(map); |
} |
- Handle<TransitionArray> transitions = TransitionArray::CopyInsert( |
- map, isolate->factory()->observed_symbol(), new_map, FULL_TRANSITION); |
- |
- map->set_transitions(*transitions); |
- |
new_map->set_is_observed(); |
- |
if (map->owns_descriptors()) { |
new_map->InitializeDescriptors(map->instance_descriptors()); |
- map->set_owns_descriptors(false); |
} |
- new_map->SetBackPointer(*map); |
+ Handle<Name> name = isolate->factory()->observed_symbol(); |
+ ConnectTransition(map, new_map, name, FULL_TRANSITION); |
+ |
return new_map; |
} |
@@ -11923,7 +11927,9 @@ Handle<Map> Map::PutPrototypeTransition(Handle<Map> map, |
Handle<Map> target_map) { |
DCHECK(target_map->IsMap()); |
DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); |
- // Don't cache prototype transition if this map is shared. |
+ // Don't cache prototype transition if this map is either shared, or a map of |
+ // a prototype. |
+ if (map->is_prototype_map()) return map; |
if (map->is_shared() || !FLAG_cache_prototype_transitions) return map; |
const int step = kProtoTransitionElementsPerEntry; |