Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 520e181b59be7042546a6f8893431a6042aac036..e95ff10a4287445b8088d8fa865fa5c37ef49656 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -1950,7 +1950,7 @@ bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields, |
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); |
+ ConnectTransition(parent, child, name, SPECIAL_TRANSITION); |
} |
@@ -2208,9 +2208,9 @@ Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map, |
Handle<LayoutDescriptor> new_layout_descriptor( |
LayoutDescriptor::FastPointerLayout(), isolate); |
- Handle<Map> new_map = |
- CopyReplaceDescriptors(map, descriptors, new_layout_descriptor, |
- OMIT_TRANSITION, MaybeHandle<Name>(), reason); |
+ Handle<Map> new_map = CopyReplaceDescriptors( |
+ map, descriptors, new_layout_descriptor, OMIT_TRANSITION, |
+ MaybeHandle<Name>(), reason, SPECIAL_TRANSITION); |
// Unless the instance is being migrated, ensure that modify_index is a field. |
PropertyDetails details = descriptors->GetDetails(modify_index); |
@@ -2278,12 +2278,14 @@ void Map::DeprecateTransitionTree() { |
// the current instance_descriptors to ensure proper sharing of descriptor |
// arrays. |
// Returns true if the transition target at given key was deprecated. |
-bool Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors, |
+bool Map::DeprecateTarget(PropertyType type, Name* key, |
+ PropertyAttributes attributes, |
+ DescriptorArray* new_descriptors, |
LayoutDescriptor* new_layout_descriptor) { |
bool transition_target_deprecated = false; |
if (HasTransitionArray()) { |
TransitionArray* transitions = this->transitions(); |
- int transition = transitions->Search(key); |
+ int transition = transitions->Search(type, key, attributes); |
if (transition != TransitionArray::kNotFound) { |
transitions->GetTarget(transition)->DeprecateTransitionTree(); |
transition_target_deprecated = true; |
@@ -2332,14 +2334,15 @@ Map* Map::FindLastMatchMap(int verbatim, |
for (int i = verbatim; i < length; i++) { |
if (!current->HasTransitionArray()) break; |
Name* name = descriptors->GetKey(i); |
+ PropertyDetails details = descriptors->GetDetails(i); |
TransitionArray* transitions = current->transitions(); |
- int transition = transitions->Search(name); |
+ int transition = |
+ transitions->Search(details.type(), name, details.attributes()); |
if (transition == TransitionArray::kNotFound) break; |
Map* next = transitions->GetTarget(transition); |
DescriptorArray* next_descriptors = next->instance_descriptors(); |
- PropertyDetails details = descriptors->GetDetails(i); |
PropertyDetails next_details = next_descriptors->GetDetails(i); |
if (details.type() != next_details.type()) break; |
if (details.attributes() != next_details.attributes()) break; |
@@ -2543,21 +2546,23 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
Handle<Map> target_map = root_map; |
for (int i = root_nof; i < old_nof; ++i) { |
- int j = target_map->SearchTransition(old_descriptors->GetKey(i)); |
+ PropertyDetails old_details = old_descriptors->GetDetails(i); |
+ int j = target_map->SearchTransition(old_details.type(), |
+ old_descriptors->GetKey(i), |
+ old_details.attributes()); |
if (j == TransitionArray::kNotFound) break; |
Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
Handle<DescriptorArray> tmp_descriptors = handle( |
tmp_map->instance_descriptors(), isolate); |
// Check if target map is incompatible. |
- PropertyDetails old_details = old_descriptors->GetDetails(i); |
PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
PropertyType old_type = old_details.type(); |
PropertyType tmp_type = tmp_details.type(); |
- if (tmp_details.attributes() != old_details.attributes() || |
- ((tmp_type == CALLBACKS || old_type == CALLBACKS) && |
- (tmp_type != old_type || |
- tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) { |
+ DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); |
+ if ((tmp_type == CALLBACKS || old_type == CALLBACKS) && |
+ (tmp_type != old_type || |
+ tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { |
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
"GenAll_Incompatible"); |
} |
@@ -2609,19 +2614,21 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
// Find the last compatible target map in the transition tree. |
for (int i = target_nof; i < old_nof; ++i) { |
- int j = target_map->SearchTransition(old_descriptors->GetKey(i)); |
+ PropertyDetails old_details = old_descriptors->GetDetails(i); |
+ int j = target_map->SearchTransition(old_details.type(), |
+ old_descriptors->GetKey(i), |
+ old_details.attributes()); |
if (j == TransitionArray::kNotFound) break; |
Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
Handle<DescriptorArray> tmp_descriptors( |
tmp_map->instance_descriptors(), isolate); |
// Check if target map is compatible. |
- PropertyDetails old_details = old_descriptors->GetDetails(i); |
PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
- if (tmp_details.attributes() != old_details.attributes() || |
- ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) && |
- (tmp_details.type() != old_details.type() || |
- tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i)))) { |
+ DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); |
+ if ((tmp_details.type() == CALLBACKS || old_details.type() == CALLBACKS) && |
+ (tmp_details.type() != old_details.type() || |
+ tmp_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { |
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
"GenAll_Incompatible"); |
} |
@@ -2753,9 +2760,11 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
Handle<LayoutDescriptor> new_layout_descriptor = |
LayoutDescriptor::New(split_map, new_descriptors, old_nof); |
- bool transition_target_deprecated = |
- split_map->DeprecateTarget(old_descriptors->GetKey(split_nof), |
- *new_descriptors, *new_layout_descriptor); |
+ PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof); |
+ bool transition_target_deprecated = split_map->DeprecateTarget( |
+ split_prop_details.type(), old_descriptors->GetKey(split_nof), |
+ split_prop_details.attributes(), *new_descriptors, |
+ *new_layout_descriptor); |
// If |transition_target_deprecated| is true then the transition array |
// already contains entry for given descriptor. This means that the transition |
@@ -2849,13 +2858,15 @@ MaybeHandle<Map> Map::TryUpdateInternal(Handle<Map> old_map) { |
Map* new_map = root_map; |
for (int i = root_nof; i < old_nof; ++i) { |
- int j = new_map->SearchTransition(old_descriptors->GetKey(i)); |
+ PropertyDetails old_details = old_descriptors->GetDetails(i); |
+ int j = new_map->SearchTransition(old_details.type(), |
+ old_descriptors->GetKey(i), |
+ old_details.attributes()); |
if (j == TransitionArray::kNotFound) return MaybeHandle<Map>(); |
new_map = new_map->GetTransition(j); |
DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
PropertyDetails new_details = new_descriptors->GetDetails(i); |
- PropertyDetails old_details = old_descriptors->GetDetails(i); |
if (old_details.attributes() != new_details.attributes() || |
!old_details.representation().fits_into(new_details.representation())) { |
return MaybeHandle<Map>(); |
@@ -5496,7 +5507,7 @@ MaybeHandle<Object> JSObject::Freeze(Handle<JSObject> object) { |
Handle<Map> old_map(object->map(), isolate); |
int transition_index = |
- old_map->SearchTransition(isolate->heap()->frozen_symbol()); |
+ old_map->SearchSpecialTransition(isolate->heap()->frozen_symbol()); |
if (transition_index != TransitionArray::kNotFound) { |
Handle<Map> transition_map(old_map->GetTransition(transition_index)); |
DCHECK(transition_map->has_dictionary_elements()); |
@@ -5549,7 +5560,7 @@ void JSObject::SetObserved(Handle<JSObject> object) { |
Handle<Map> old_map(object->map(), isolate); |
DCHECK(!old_map->is_observed()); |
int transition_index = |
- old_map->SearchTransition(isolate->heap()->observed_symbol()); |
+ old_map->SearchSpecialTransition(isolate->heap()->observed_symbol()); |
if (transition_index != TransitionArray::kNotFound) { |
new_map = handle(old_map->GetTransition(transition_index), isolate); |
DCHECK(new_map->is_observed()); |
@@ -6759,7 +6770,7 @@ Handle<Map> Map::ShareDescriptor(Handle<Map> map, |
} |
DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1); |
- ConnectTransition(map, result, name, SIMPLE_TRANSITION); |
+ ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); |
return result; |
} |
@@ -6892,7 +6903,7 @@ Handle<Map> Map::CopyInstallDescriptors( |
} |
Handle<Name> name = handle(descriptors->GetKey(new_descriptor)); |
- ConnectTransition(map, result, name, SIMPLE_TRANSITION); |
+ ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION); |
return result; |
} |
@@ -6970,7 +6981,7 @@ Handle<Map> Map::CopyForObserved(Handle<Map> map) { |
if (map->CanHaveMoreTransitions()) { |
Handle<Name> name = isolate->factory()->observed_symbol(); |
- ConnectTransition(map, new_map, name, FULL_TRANSITION); |
+ ConnectTransition(map, new_map, name, SPECIAL_TRANSITION); |
} |
return new_map; |
} |
@@ -6984,7 +6995,8 @@ Handle<Map> Map::Copy(Handle<Map> map, const char* reason) { |
Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(), |
map->GetIsolate()); |
return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor, |
- OMIT_TRANSITION, MaybeHandle<Name>(), reason); |
+ OMIT_TRANSITION, MaybeHandle<Name>(), reason, |
+ SPECIAL_TRANSITION); |
} |
@@ -7023,7 +7035,7 @@ Handle<Map> Map::CopyForFreeze(Handle<Map> map) { |
isolate); |
Handle<Map> new_map = CopyReplaceDescriptors( |
map, new_desc, new_layout_descriptor, INSERT_TRANSITION, |
- isolate->factory()->frozen_symbol(), "CopyForFreeze"); |
+ isolate->factory()->frozen_symbol(), "CopyForFreeze", SPECIAL_TRANSITION); |
new_map->freeze(); |
new_map->set_is_extensible(false); |
new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
@@ -7083,17 +7095,14 @@ Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name, |
// Migrate to the newest map before storing the property. |
map = Update(map); |
- int index = map->SearchTransition(*name); |
+ int index = map->SearchTransition(FIELD, *name, attributes); |
if (index != TransitionArray::kNotFound) { |
Handle<Map> transition(map->GetTransition(index)); |
int descriptor = transition->LastAdded(); |
- // TODO(verwaest): Handle attributes better. |
- DescriptorArray* descriptors = transition->instance_descriptors(); |
- if (descriptors->GetDetails(descriptor).attributes() != attributes) { |
- return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, |
- "IncompatibleAttributes"); |
- } |
+ DCHECK_EQ(attributes, transition->instance_descriptors() |
+ ->GetDetails(descriptor) |
+ .attributes()); |
return Map::PrepareForDataProperty(transition, descriptor, value); |
} |
@@ -7163,26 +7172,15 @@ Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map, |
? KEEP_INOBJECT_PROPERTIES |
: CLEAR_INOBJECT_PROPERTIES; |
- int index = map->SearchTransition(*name); |
+ int index = map->SearchTransition(CALLBACKS, *name, attributes); |
if (index != TransitionArray::kNotFound) { |
Handle<Map> transition(map->GetTransition(index)); |
DescriptorArray* descriptors = transition->instance_descriptors(); |
- // Fast path, assume that we're modifying the last added descriptor. |
int descriptor = transition->LastAdded(); |
- if (descriptors->GetKey(descriptor) != *name) { |
- // If not, search for the descriptor. |
- descriptor = descriptors->SearchWithCache(*name, *transition); |
- } |
- |
- if (descriptors->GetDetails(descriptor).type() != CALLBACKS) { |
- return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair"); |
- } |
+ DCHECK(descriptors->GetKey(descriptor)->Equals(*name)); |
- // TODO(verwaest): Handle attributes better. |
- if (descriptors->GetDetails(descriptor).attributes() != attributes) { |
- return Map::Normalize(map, mode, |
- "TransitionToAccessorDifferentAttributes"); |
- } |
+ DCHECK_EQ(CALLBACKS, descriptors->GetDetails(descriptor).type()); |
+ DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes()); |
Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate); |
if (!maybe_pair->IsAccessorPair()) { |
@@ -7201,6 +7199,9 @@ Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map, |
DescriptorArray* old_descriptors = map->instance_descriptors(); |
int descriptor = old_descriptors->SearchWithCache(*name, *map); |
if (descriptor != DescriptorArray::kNotFound) { |
+ if (descriptor != map->LastAdded()) { |
+ return Map::Normalize(map, mode, "AccessorsOverwritingNonLast"); |
+ } |
PropertyDetails old_details = old_descriptors->GetDetails(descriptor); |
if (old_details.type() != CALLBACKS) { |
return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors"); |
@@ -7262,7 +7263,7 @@ Handle<Map> Map::CopyAddDescriptor(Handle<Map> map, |
return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor, |
flag, descriptor->GetKey(), "CopyAddDescriptor", |
- SIMPLE_TRANSITION); |
+ SIMPLE_PROPERTY_TRANSITION); |
} |
@@ -7358,8 +7359,8 @@ Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map, |
SimpleTransitionFlag simple_flag = |
(insertion_index == descriptors->number_of_descriptors() - 1) |
- ? SIMPLE_TRANSITION |
- : FULL_TRANSITION; |
+ ? SIMPLE_PROPERTY_TRANSITION |
+ : PROPERTY_TRANSITION; |
return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor, |
flag, key, "CopyReplaceDescriptor", |
simple_flag); |