Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 2bf21a2c6d82a9b1191b83c1f16dc5b7401d81a5..89bc3c91c941c765ff346f068f93ce38a9044970 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -2883,45 +2883,43 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, |
void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) { |
Isolate* isolate = object->GetIsolate(); |
Handle<Map> old_map(object->map()); |
- int old_number_of_fields; |
- int number_of_fields = new_map->NumberOfFields(); |
- int inobject = new_map->GetInObjectProperties(); |
- int unused = new_map->unused_property_fields(); |
- |
- // Nothing to do if no functions were converted to fields and no smis were |
- // converted to doubles. |
- if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject, |
- unused, &old_number_of_fields)) { |
- object->synchronized_set_map(*new_map); |
- return; |
- } |
- |
- int total_size = number_of_fields + unused; |
- int external = total_size - inobject; |
+ // In case of a regular transition. |
+ if (new_map->GetBackPointer() == *old_map) { |
+ // If the map does not add named properties, simply set the map. |
+ if (old_map->NumberOfOwnDescriptors() == |
+ new_map->NumberOfOwnDescriptors()) { |
+ object->synchronized_set_map(*new_map); |
+ return; |
+ } |
- if (number_of_fields != old_number_of_fields && |
- new_map->GetBackPointer() == *old_map) { |
PropertyDetails details = new_map->GetLastDescriptorDetails(); |
+ // Either new_map adds an kDescriptor property, or a kField property for |
+ // which there is still space, and which does not require a mutable double |
+ // box (an out-of-object double). |
+ if (details.location() == kDescriptor || |
+ (old_map->unused_property_fields() > 0 && |
+ ((FLAG_unbox_double_fields && object->properties()->length() == 0) || |
+ !details.representation().IsDouble()))) { |
+ object->synchronized_set_map(*new_map); |
+ return; |
+ } |
+ // If there is still space in the object, we need to allocate a mutable |
+ // double box. |
if (old_map->unused_property_fields() > 0) { |
- if (details.representation().IsDouble()) { |
- FieldIndex index = |
- FieldIndex::ForDescriptor(*new_map, new_map->LastAdded()); |
- if (new_map->IsUnboxedDoubleField(index)) { |
- object->RawFastDoublePropertyAtPut(index, 0); |
- } else { |
- Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE); |
- object->RawFastPropertyAtPut(index, *value); |
- } |
- } |
+ FieldIndex index = |
+ FieldIndex::ForDescriptor(*new_map, new_map->LastAdded()); |
+ DCHECK(details.representation().IsDouble()); |
+ DCHECK(!new_map->IsUnboxedDoubleField(index)); |
+ Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE); |
+ object->RawFastPropertyAtPut(index, *value); |
object->synchronized_set_map(*new_map); |
return; |
} |
- DCHECK(number_of_fields == old_number_of_fields + 1); |
// This migration is a transition from a map that has run out of property |
- // space. Therefore it could be done by extending the backing store. |
- int grow_by = external - object->properties()->length(); |
+ // space. Extend the backing store. |
+ int grow_by = new_map->unused_property_fields() + 1; |
Handle<FixedArray> old_storage = handle(object->properties(), isolate); |
Handle<FixedArray> new_storage = |
isolate->factory()->CopyFixedArrayAndGrow(old_storage, grow_by); |
@@ -2933,8 +2931,8 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) { |
} else { |
value = isolate->factory()->uninitialized_value(); |
} |
- DCHECK(details.type() == DATA); |
- int target_index = details.field_index() - inobject; |
+ DCHECK_EQ(DATA, details.type()); |
+ int target_index = details.field_index() - new_map->GetInObjectProperties(); |
DCHECK(target_index >= 0); // Must be a backing store index. |
new_storage->set(target_index, *value); |
@@ -2946,6 +2944,23 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) { |
object->synchronized_set_map(*new_map); |
return; |
} |
+ |
+ int old_number_of_fields; |
+ int number_of_fields = new_map->NumberOfFields(); |
+ int inobject = new_map->GetInObjectProperties(); |
+ int unused = new_map->unused_property_fields(); |
+ |
+ // Nothing to do if no functions were converted to fields and no smis were |
+ // converted to doubles. |
+ if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject, |
+ unused, &old_number_of_fields)) { |
+ object->synchronized_set_map(*new_map); |
+ return; |
+ } |
+ |
+ int total_size = number_of_fields + unused; |
+ int external = total_size - inobject; |
+ |
Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); |
Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |