Commit 8a286ece authored by verwaest's avatar verwaest Committed by Commit bot

[runtime] Optimize MigrateFastToFast for the transition case

This avoids quite expensive computation further downstream.

Review URL: https://codereview.chromium.org/1697173002

Cr-Commit-Position: refs/heads/master@{#34007}
parent 5ca122a1
...@@ -2883,45 +2883,43 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map, ...@@ -2883,45 +2883,43 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) { void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
Isolate* isolate = object->GetIsolate(); Isolate* isolate = object->GetIsolate();
Handle<Map> old_map(object->map()); Handle<Map> old_map(object->map());
int old_number_of_fields; // In case of a regular transition.
int number_of_fields = new_map->NumberOfFields(); if (new_map->GetBackPointer() == *old_map) {
int inobject = new_map->GetInObjectProperties(); // If the map does not add named properties, simply set the map.
int unused = new_map->unused_property_fields(); if (old_map->NumberOfOwnDescriptors() ==
new_map->NumberOfOwnDescriptors()) {
// Nothing to do if no functions were converted to fields and no smis were object->synchronized_set_map(*new_map);
// converted to doubles. return;
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;
if (number_of_fields != old_number_of_fields &&
new_map->GetBackPointer() == *old_map) {
PropertyDetails details = new_map->GetLastDescriptorDetails(); 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 (old_map->unused_property_fields() > 0) {
if (details.representation().IsDouble()) { FieldIndex index =
FieldIndex index = FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
FieldIndex::ForDescriptor(*new_map, new_map->LastAdded()); DCHECK(details.representation().IsDouble());
if (new_map->IsUnboxedDoubleField(index)) { DCHECK(!new_map->IsUnboxedDoubleField(index));
object->RawFastDoublePropertyAtPut(index, 0); Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
} else { object->RawFastPropertyAtPut(index, *value);
Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
object->RawFastPropertyAtPut(index, *value);
}
}
object->synchronized_set_map(*new_map); object->synchronized_set_map(*new_map);
return; return;
} }
DCHECK(number_of_fields == old_number_of_fields + 1);
// This migration is a transition from a map that has run out of property // 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. // space. Extend the backing store.
int grow_by = external - object->properties()->length(); int grow_by = new_map->unused_property_fields() + 1;
Handle<FixedArray> old_storage = handle(object->properties(), isolate); Handle<FixedArray> old_storage = handle(object->properties(), isolate);
Handle<FixedArray> new_storage = Handle<FixedArray> new_storage =
isolate->factory()->CopyFixedArrayAndGrow(old_storage, grow_by); isolate->factory()->CopyFixedArrayAndGrow(old_storage, grow_by);
...@@ -2933,8 +2931,8 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) { ...@@ -2933,8 +2931,8 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
} else { } else {
value = isolate->factory()->uninitialized_value(); value = isolate->factory()->uninitialized_value();
} }
DCHECK(details.type() == DATA); DCHECK_EQ(DATA, details.type());
int target_index = details.field_index() - inobject; int target_index = details.field_index() - new_map->GetInObjectProperties();
DCHECK(target_index >= 0); // Must be a backing store index. DCHECK(target_index >= 0); // Must be a backing store index.
new_storage->set(target_index, *value); new_storage->set(target_index, *value);
...@@ -2946,6 +2944,23 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) { ...@@ -2946,6 +2944,23 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
object->synchronized_set_map(*new_map); object->synchronized_set_map(*new_map);
return; 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<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment