Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 98e043671175e6e1f3708d478fa651ae4ac89842..21ed836cce1a21af3dace2c0cee605fb95db818d 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2425,43 +2425,6 @@ Map* Map::FindRootMap() { |
} |
-// Returns NULL if the updated map is incompatible. |
-Map* Map::FindUpdatedMap(int verbatim, |
- int length, |
- DescriptorArray* descriptors) { |
- DisallowHeapAllocation no_allocation; |
- |
- // This can only be called on roots of transition trees. |
- ASSERT(GetBackPointer()->IsUndefined()); |
- |
- Map* current = this; |
- |
- for (int i = verbatim; i < length; i++) { |
- if (!current->HasTransitionArray()) break; |
- Name* name = descriptors->GetKey(i); |
- TransitionArray* transitions = current->transitions(); |
- int transition = transitions->Search(name); |
- if (transition == TransitionArray::kNotFound) break; |
- current = transitions->GetTarget(transition); |
- PropertyDetails details = descriptors->GetDetails(i); |
- PropertyDetails target_details = |
- current->instance_descriptors()->GetDetails(i); |
- if (details.attributes() != target_details.attributes()) return NULL; |
- if (details.type() == CALLBACKS) { |
- if (target_details.type() != CALLBACKS) return NULL; |
- if (descriptors->GetValue(i) != |
- current->instance_descriptors()->GetValue(i)) { |
- return NULL; |
- } |
- } else if (target_details.type() == CALLBACKS) { |
- return NULL; |
- } |
- } |
- |
- return current; |
-} |
- |
- |
Map* Map::FindLastMatchMap(int verbatim, |
int length, |
DescriptorArray* descriptors) { |
@@ -2552,13 +2515,10 @@ void Map::GeneralizeFieldType(Handle<Map> map, |
int modify_index, |
Handle<HeapType> new_field_type) { |
Isolate* isolate = map->GetIsolate(); |
- Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); |
- Handle<DescriptorArray> descriptors( |
- field_owner->instance_descriptors(), isolate); |
// Check if we actually need to generalize the field type at all. |
Handle<HeapType> old_field_type( |
- descriptors->GetFieldType(modify_index), isolate); |
+ map->instance_descriptors()->GetFieldType(modify_index), isolate); |
if (new_field_type->NowIs(old_field_type)) { |
ASSERT(Map::GeneralizeFieldType(old_field_type, |
new_field_type, |
@@ -2566,6 +2526,12 @@ void Map::GeneralizeFieldType(Handle<Map> map, |
return; |
} |
+ // Determine the field owner. |
+ Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate); |
+ Handle<DescriptorArray> descriptors( |
+ field_owner->instance_descriptors(), isolate); |
+ ASSERT_EQ(*old_field_type, descriptors->GetFieldType(modify_index)); |
+ |
// Determine the generalized new field type. |
new_field_type = Map::GeneralizeFieldType( |
old_field_type, new_field_type, isolate); |
@@ -2598,23 +2564,28 @@ void Map::GeneralizeFieldType(Handle<Map> map, |
// (partial) version of the type in the transition tree. |
// To do this, on each rewrite: |
// - Search the root of the transition tree using FindRootMap. |
-// - Find |updated|, the newest matching version of this map using |
-// FindUpdatedMap. This uses the keys in the own map's descriptor array to |
-// walk the transition tree. |
-// - Merge/generalize the descriptor array of the current map and |updated|. |
-// - Generalize the |modify_index| descriptor using |new_representation|. |
-// - Walk the tree again starting from the root towards |updated|. Stop at |
+// - Find |target_map|, the newest matching version of this map using the keys |
+// in the |old_map|'s descriptor array to walk the transition tree. |
+// - Merge/generalize the descriptor array of the |old_map| and |target_map|. |
+// - Generalize the |modify_index| descriptor using |new_representation| and |
+// |new_field_type|. |
+// - Walk the tree again starting from the root towards |target_map|. Stop at |
// |split_map|, the first map who's descriptor array does not match the merged |
// descriptor array. |
-// - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
-// - Otherwise, invalidate the outdated transition target from |updated|, and |
+// - If |target_map| == |split_map|, |target_map| is in the expected state. |
+// Return it. |
+// - Otherwise, invalidate the outdated transition target from |target_map|, and |
// replace its transition tree with a new branch for the updated descriptors. |
Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
int modify_index, |
Representation new_representation, |
Handle<HeapType> new_field_type, |
StoreMode store_mode) { |
- Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |
+ Isolate* isolate = old_map->GetIsolate(); |
+ |
+ Handle<DescriptorArray> old_descriptors( |
+ old_map->instance_descriptors(), isolate); |
+ int old_nof = old_map->NumberOfOwnDescriptors(); |
PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
Representation old_representation = old_details.representation(); |
@@ -2641,84 +2612,239 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
return old_map; |
} |
- if (new_representation.Equals(old_representation) && |
- old_details.type() == FIELD) { |
- Map::GeneralizeFieldType(old_map, modify_index, new_field_type); |
- return old_map; |
- } |
- |
- Handle<Map> root_map(old_map->FindRootMap()); |
- |
// Check the state of the root map. |
+ Handle<Map> root_map(old_map->FindRootMap(), isolate); |
if (!old_map->EquivalentToForTransition(*root_map)) { |
return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
old_details.attributes(), "not equivalent"); |
} |
+ int root_nof = root_map->NumberOfOwnDescriptors(); |
+ if (modify_index < root_nof) { |
+ PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
+ if ((old_details.type() != FIELD && store_mode == FORCE_FIELD) || |
+ (old_details.type() == FIELD && |
+ (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) || |
+ !new_representation.fits_into(old_details.representation())))) { |
+ return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
+ old_details.attributes(), "root modification"); |
+ } |
+ } |
- int verbatim = root_map->NumberOfOwnDescriptors(); |
+ Handle<Map> target_map = root_map; |
+ for (int i = root_nof; i < old_nof; ++i) { |
+ int j = target_map->SearchTransition(old_descriptors->GetKey(i)); |
+ if (j == TransitionArray::kNotFound) break; |
+ Handle<Map> tmp_map(target_map->GetTransition(j), isolate); |
+ Handle<DescriptorArray> tmp_descriptors = handle( |
+ tmp_map->instance_descriptors(), isolate); |
- if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
- return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
- old_details.attributes(), "root modification"); |
+ // 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)))) { |
+ return CopyGeneralizeAllRepresentations( |
+ old_map, modify_index, store_mode, |
+ old_details.attributes(), "incompatible"); |
+ } |
+ Representation old_representation = old_details.representation(); |
+ Representation tmp_representation = tmp_details.representation(); |
+ if (!old_representation.fits_into(tmp_representation) || |
+ (!new_representation.fits_into(tmp_representation) && |
+ modify_index == i)) { |
+ break; |
+ } |
+ if (tmp_type == FIELD) { |
+ // Generalize the field type as necessary. |
+ Handle<HeapType> old_field_type = (old_type == FIELD) |
+ ? handle(old_descriptors->GetFieldType(i), isolate) |
+ : old_descriptors->GetValue(i)->OptimalType( |
+ isolate, tmp_representation); |
+ if (modify_index == i) { |
+ old_field_type = GeneralizeFieldType( |
+ new_field_type, old_field_type, isolate); |
+ } |
+ GeneralizeFieldType(tmp_map, i, old_field_type); |
+ } else if (tmp_type == CONSTANT) { |
+ if (old_type != CONSTANT || |
+ old_descriptors->GetConstant(i) != tmp_descriptors->GetConstant(i)) { |
+ break; |
+ } |
+ } else { |
+ ASSERT_EQ(tmp_type, old_type); |
+ ASSERT_EQ(tmp_descriptors->GetValue(i), old_descriptors->GetValue(i)); |
+ } |
+ target_map = tmp_map; |
+ } |
+ |
+ // Directly change the map if the target map is more general. |
+ Handle<DescriptorArray> target_descriptors( |
+ target_map->instance_descriptors(), isolate); |
+ int target_nof = target_map->NumberOfOwnDescriptors(); |
+ if (target_nof == old_nof && |
+ (store_mode != FORCE_FIELD || |
+ target_descriptors->GetDetails(modify_index).type() == FIELD)) { |
+ ASSERT(modify_index < target_nof); |
+ ASSERT(new_representation.fits_into( |
+ target_descriptors->GetDetails(modify_index).representation())); |
+ ASSERT(target_descriptors->GetDetails(modify_index).type() != FIELD || |
+ new_field_type->NowIs( |
+ target_descriptors->GetFieldType(modify_index))); |
+ return target_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)); |
+ 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)))) { |
+ return CopyGeneralizeAllRepresentations( |
+ old_map, modify_index, store_mode, |
+ old_details.attributes(), "incompatible"); |
+ } |
+ target_map = tmp_map; |
} |
+ target_nof = target_map->NumberOfOwnDescriptors(); |
+ target_descriptors = handle(target_map->instance_descriptors(), isolate); |
- int descriptors = old_map->NumberOfOwnDescriptors(); |
- Map* raw_updated = root_map->FindUpdatedMap( |
- verbatim, descriptors, *old_descriptors); |
- if (raw_updated == NULL) { |
- return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode, |
- old_details.attributes(), "incompatible"); |
+ // Allocate a new descriptor array large enough to hold the required |
+ // descriptors, with minimally the exact same size as the old descriptor |
+ // array. |
+ int new_slack = Max( |
+ old_nof, old_descriptors->number_of_descriptors()) - old_nof; |
+ Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate( |
+ isolate, old_nof, new_slack); |
+ ASSERT(new_descriptors->length() > target_descriptors->length() || |
+ new_descriptors->NumberOfSlackDescriptors() > 0 || |
+ new_descriptors->number_of_descriptors() == |
+ old_descriptors->number_of_descriptors()); |
+ ASSERT(new_descriptors->number_of_descriptors() == old_nof); |
+ |
+ // 0 -> |root_nof| |
+ int current_offset = 0; |
+ for (int i = 0; i < root_nof; ++i) { |
+ PropertyDetails old_details = old_descriptors->GetDetails(i); |
+ if (old_details.type() == FIELD) current_offset++; |
+ Descriptor d(handle(old_descriptors->GetKey(i), isolate), |
+ handle(old_descriptors->GetValue(i), isolate), |
+ old_details); |
+ new_descriptors->Set(i, &d); |
} |
- Handle<Map> updated(raw_updated); |
- Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors()); |
- |
- int valid = updated->NumberOfOwnDescriptors(); |
+ // |root_nof| -> |target_nof| |
+ for (int i = root_nof; i < target_nof; ++i) { |
+ Handle<Name> target_key(target_descriptors->GetKey(i), isolate); |
+ PropertyDetails old_details = old_descriptors->GetDetails(i); |
+ PropertyDetails target_details = target_descriptors->GetDetails(i); |
+ target_details = target_details.CopyWithRepresentation( |
+ old_details.representation().generalize( |
+ target_details.representation())); |
+ if (modify_index == i) { |
+ target_details = target_details.CopyWithRepresentation( |
+ new_representation.generalize(target_details.representation())); |
+ } |
+ if (old_details.type() == FIELD || |
+ target_details.type() == FIELD || |
+ (modify_index == i && store_mode == FORCE_FIELD) || |
+ (target_descriptors->GetValue(i) != old_descriptors->GetValue(i))) { |
+ Handle<HeapType> old_field_type = (old_details.type() == FIELD) |
+ ? handle(old_descriptors->GetFieldType(i), isolate) |
+ : old_descriptors->GetValue(i)->OptimalType( |
+ isolate, target_details.representation()); |
+ Handle<HeapType> target_field_type = (target_details.type() == FIELD) |
+ ? handle(target_descriptors->GetFieldType(i), isolate) |
+ : target_descriptors->GetValue(i)->OptimalType( |
+ isolate, target_details.representation()); |
+ target_field_type = GeneralizeFieldType( |
+ target_field_type, old_field_type, isolate); |
+ if (modify_index == i) { |
+ target_field_type = GeneralizeFieldType( |
+ target_field_type, new_field_type, isolate); |
+ } |
+ FieldDescriptor d(target_key, |
+ current_offset++, |
+ target_field_type, |
+ target_details.attributes(), |
+ target_details.representation()); |
+ new_descriptors->Set(i, &d); |
+ } else { |
+ ASSERT_NE(FIELD, target_details.type()); |
+ Descriptor d(target_key, |
+ handle(target_descriptors->GetValue(i), isolate), |
+ target_details); |
+ new_descriptors->Set(i, &d); |
+ } |
+ } |
- // Directly change the map if the target map is more general. Ensure that the |
- // target type of the modify_index is a FIELD, unless we are migrating. |
- if (updated_descriptors->IsMoreGeneralThan( |
- verbatim, valid, descriptors, *old_descriptors) && |
- (store_mode == ALLOW_AS_CONSTANT || |
- updated_descriptors->GetDetails(modify_index).type() == FIELD)) { |
- Representation updated_representation = |
- updated_descriptors->GetDetails(modify_index).representation(); |
- if (new_representation.fits_into(updated_representation)) return updated; |
+ // |target_nof| -> |old_nof| |
+ for (int i = target_nof; i < old_nof; ++i) { |
+ PropertyDetails old_details = old_descriptors->GetDetails(i); |
+ Handle<Name> old_key(old_descriptors->GetKey(i), isolate); |
+ if (modify_index == i) { |
+ old_details = old_details.CopyWithRepresentation( |
+ new_representation.generalize(old_details.representation())); |
+ } |
+ if (old_details.type() == FIELD) { |
+ Handle<HeapType> old_field_type( |
+ old_descriptors->GetFieldType(i), isolate); |
+ if (modify_index == i) { |
+ old_field_type = GeneralizeFieldType( |
+ old_field_type, new_field_type, isolate); |
+ } |
+ FieldDescriptor d(old_key, |
+ current_offset++, |
+ old_field_type, |
+ old_details.attributes(), |
+ old_details.representation()); |
+ new_descriptors->Set(i, &d); |
+ } else { |
+ ASSERT(old_details.type() == CONSTANT || old_details.type() == CALLBACKS); |
+ if (modify_index == i && store_mode == FORCE_FIELD) { |
+ FieldDescriptor d(old_key, |
+ current_offset++, |
+ GeneralizeFieldType( |
+ old_descriptors->GetValue(i)->OptimalType( |
+ isolate, old_details.representation()), |
+ new_field_type, isolate), |
+ old_details.attributes(), |
+ old_details.representation()); |
+ new_descriptors->Set(i, &d); |
+ } else { |
+ ASSERT_NE(FIELD, old_details.type()); |
+ Descriptor d(old_key, |
+ handle(old_descriptors->GetValue(i), isolate), |
+ old_details); |
+ new_descriptors->Set(i, &d); |
+ } |
+ } |
} |
- Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge( |
- updated, verbatim, valid, descriptors, modify_index, |
- store_mode, old_map); |
- ASSERT(store_mode == ALLOW_AS_CONSTANT || |
- new_descriptors->GetDetails(modify_index).type() == FIELD); |
+ new_descriptors->Sort(); |
- Isolate* isolate = new_descriptors->GetIsolate(); |
- old_representation = |
- new_descriptors->GetDetails(modify_index).representation(); |
- Representation updated_representation = |
- new_representation.generalize(old_representation); |
- if (!updated_representation.Equals(old_representation)) { |
- new_descriptors->SetRepresentation(modify_index, updated_representation); |
- } |
- if (new_descriptors->GetDetails(modify_index).type() == FIELD) { |
- Handle<HeapType> field_type( |
- new_descriptors->GetFieldType(modify_index), isolate); |
- new_field_type = Map::GeneralizeFieldType( |
- field_type, new_field_type, isolate); |
- new_descriptors->SetValue(modify_index, *new_field_type); |
- } |
+ ASSERT(store_mode != FORCE_FIELD || |
+ new_descriptors->GetDetails(modify_index).type() == FIELD); |
Handle<Map> split_map(root_map->FindLastMatchMap( |
- verbatim, descriptors, *new_descriptors)); |
+ root_nof, old_nof, *new_descriptors), isolate); |
+ int split_nof = split_map->NumberOfOwnDescriptors(); |
+ ASSERT_NE(old_nof, split_nof); |
- int split_descriptors = split_map->NumberOfOwnDescriptors(); |
- // This is shadowed by |updated_descriptors| being more general than |
- // |old_descriptors|. |
- ASSERT(descriptors != split_descriptors); |
- |
- int descriptor = split_descriptors; |
split_map->DeprecateTarget( |
- old_descriptors->GetKey(descriptor), *new_descriptors); |
+ old_descriptors->GetKey(split_nof), *new_descriptors); |
if (FLAG_trace_generalization) { |
PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
@@ -2732,7 +2858,7 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
: HeapType::Constant(handle(new_descriptors->GetValue(modify_index), |
isolate), isolate); |
old_map->PrintGeneralization( |
- stdout, "", modify_index, descriptor, descriptors, |
+ stdout, "", modify_index, split_nof, old_nof, |
old_details.type() == CONSTANT && store_mode == FORCE_FIELD, |
old_details.representation(), new_details.representation(), |
*old_field_type, *new_field_type); |
@@ -2740,10 +2866,9 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map, |
// Add missing transitions. |
Handle<Map> new_map = split_map; |
- for (; descriptor < descriptors; descriptor++) { |
- new_map = CopyInstallDescriptors(new_map, descriptor, new_descriptors); |
+ for (int i = split_nof; i < old_nof; ++i) { |
+ new_map = CopyInstallDescriptors(new_map, i, new_descriptors); |
} |
- |
new_map->set_owns_descriptors(true); |
return new_map; |
} |
@@ -8397,150 +8522,6 @@ void DescriptorArray::CopyFrom(int index, |
} |
-// Creates a new descriptor array by merging the descriptor array of |right_map| |
-// into the (at least partly) updated descriptor array of |left_map|. |
-// The method merges two descriptor array in three parts. Both descriptor arrays |
-// are identical up to |verbatim|. They also overlap in keys up to |valid|. |
-// Between |verbatim| and |valid|, the resulting descriptor type as well as the |
-// representation are generalized from both |left_map| and |right_map|. Beyond |
-// |valid|, the descriptors are copied verbatim from |right_map| up to |
-// |new_size|. |
-// In case of incompatible types, the type and representation of |right_map| is |
-// used. |
-Handle<DescriptorArray> DescriptorArray::Merge(Handle<Map> left_map, |
- int verbatim, |
- int valid, |
- int new_size, |
- int modify_index, |
- StoreMode store_mode, |
- Handle<Map> right_map) { |
- ASSERT(verbatim <= valid); |
- ASSERT(valid <= new_size); |
- |
- // Allocate a new descriptor array large enough to hold the required |
- // descriptors, with minimally the exact same size as this descriptor array. |
- Isolate* isolate = left_map->GetIsolate(); |
- Handle<DescriptorArray> left(left_map->instance_descriptors()); |
- Handle<DescriptorArray> right(right_map->instance_descriptors()); |
- Handle<DescriptorArray> result = DescriptorArray::Allocate( |
- isolate, |
- new_size, |
- Max(new_size, right->number_of_descriptors()) - new_size); |
- ASSERT(result->length() > left->length() || |
- result->NumberOfSlackDescriptors() > 0 || |
- result->number_of_descriptors() == right->number_of_descriptors()); |
- ASSERT(result->number_of_descriptors() == new_size); |
- |
- int descriptor; |
- |
- // 0 -> |verbatim| |
- int current_offset = 0; |
- for (descriptor = 0; descriptor < verbatim; descriptor++) { |
- if (left->GetDetails(descriptor).type() == FIELD) current_offset++; |
- Descriptor d(handle(right->GetKey(descriptor)), |
- handle(right->GetValue(descriptor), right->GetIsolate()), |
- right->GetDetails(descriptor)); |
- result->Set(descriptor, &d); |
- } |
- |
- // |verbatim| -> |valid| |
- for (; descriptor < valid; descriptor++) { |
- PropertyDetails left_details = left->GetDetails(descriptor); |
- PropertyDetails right_details = right->GetDetails(descriptor); |
- if (left_details.type() == FIELD || right_details.type() == FIELD || |
- (store_mode == FORCE_FIELD && descriptor == modify_index) || |
- (left_details.type() == CONSTANT && |
- right_details.type() == CONSTANT && |
- left->GetValue(descriptor) != right->GetValue(descriptor))) { |
- ASSERT(left_details.type() == CONSTANT || left_details.type() == FIELD); |
- ASSERT(right_details.type() == CONSTANT || right_details.type() == FIELD); |
- Representation representation = left_details.representation().generalize( |
- right_details.representation()); |
- Handle<HeapType> left_type = (left_details.type() == FIELD) |
- ? handle(left->GetFieldType(descriptor), isolate) |
- : left->GetValue(descriptor)->OptimalType(isolate, representation); |
- Handle<HeapType> right_type = (right_details.type() == FIELD) |
- ? handle(right->GetFieldType(descriptor), isolate) |
- : right->GetValue(descriptor)->OptimalType(isolate, representation); |
- Handle<HeapType> field_type = Map::GeneralizeFieldType( |
- left_type, right_type, isolate); |
- FieldDescriptor d(handle(left->GetKey(descriptor), isolate), |
- current_offset++, |
- field_type, |
- right_details.attributes(), |
- representation); |
- result->Set(descriptor, &d); |
- } else { |
- Descriptor d(handle(right->GetKey(descriptor), isolate), |
- handle(right->GetValue(descriptor), isolate), |
- right_details); |
- result->Set(descriptor, &d); |
- } |
- } |
- |
- // |valid| -> |new_size| |
- for (; descriptor < new_size; descriptor++) { |
- PropertyDetails right_details = right->GetDetails(descriptor); |
- if (right_details.type() == FIELD) { |
- FieldDescriptor d(handle(right->GetKey(descriptor), isolate), |
- current_offset++, |
- handle(right->GetFieldType(descriptor), isolate), |
- right_details.attributes(), |
- right_details.representation()); |
- result->Set(descriptor, &d); |
- } else if (store_mode == FORCE_FIELD && descriptor == modify_index) { |
- ASSERT_EQ(CONSTANT, right_details.type()); |
- Representation field_representation = right_details.representation(); |
- Handle<HeapType> field_type = right->GetValue(descriptor)->OptimalType( |
- isolate, field_representation); |
- FieldDescriptor d(handle(right->GetKey(descriptor), isolate), |
- current_offset++, |
- field_type, |
- right_details.attributes(), |
- field_representation); |
- result->Set(descriptor, &d); |
- } else { |
- Descriptor d(handle(right->GetKey(descriptor), isolate), |
- handle(right->GetValue(descriptor), isolate), |
- right_details); |
- result->Set(descriptor, &d); |
- } |
- } |
- |
- result->Sort(); |
- return result; |
-} |
- |
- |
-// Checks whether a merge of |other| into |this| would return a copy of |this|. |
-bool DescriptorArray::IsMoreGeneralThan(int verbatim, |
- int valid, |
- int new_size, |
- DescriptorArray* other) { |
- ASSERT(verbatim <= valid); |
- ASSERT(valid <= new_size); |
- if (valid != new_size) return false; |
- |
- for (int descriptor = verbatim; descriptor < valid; descriptor++) { |
- PropertyDetails details = GetDetails(descriptor); |
- PropertyDetails other_details = other->GetDetails(descriptor); |
- if (!other_details.representation().fits_into(details.representation())) { |
- return false; |
- } |
- if (details.type() == CONSTANT) { |
- if (other_details.type() != CONSTANT) return false; |
- if (GetValue(descriptor) != other->GetValue(descriptor)) return false; |
- } else if (details.type() == FIELD && other_details.type() == FIELD) { |
- if (!other->GetFieldType(descriptor)->NowIs(GetFieldType(descriptor))) { |
- return false; |
- } |
- } |
- } |
- |
- return true; |
-} |
- |
- |
// We need the whiteness witness since sort will reshuffle the entries in the |
// descriptor array. If the descriptor array were to be black, the shuffling |
// would move a slot that was already recorded as pointing into an evacuation |