| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index e0bcf44bb158caa78650c5e4b9c84d21d3f604b1..67f26f0f197fb9625e5f8f0c95aaf3047cbfba45 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -2270,6 +2270,11 @@ bool Map::InstancesNeedRewriting(Map* target,
|
| }
|
|
|
|
|
| +void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
|
| + CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->MigrateToMap(*new_map));
|
| +}
|
| +
|
| +
|
| // To migrate an instance to a map:
|
| // - First check whether the instance needs to be rewritten. If not, simply
|
| // change the map.
|
| @@ -2285,24 +2290,25 @@ bool Map::InstancesNeedRewriting(Map* target,
|
| // to temporarily store the inobject properties.
|
| // * If there are properties left in the backing store, install the backing
|
| // store.
|
| -void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
|
| - Isolate* isolate = object->GetIsolate();
|
| - Handle<Map> old_map(object->map());
|
| +MaybeObject* JSObject::MigrateToMap(Map* new_map) {
|
| + Heap* heap = GetHeap();
|
| + Map* old_map = map();
|
| int number_of_fields = new_map->NumberOfFields();
|
| int inobject = new_map->inobject_properties();
|
| int unused = new_map->unused_property_fields();
|
|
|
| - // Nothing to do if no functions were converted to fields and no smis were
|
| - // converted to doubles.
|
| + // Nothing to do if no functions were converted to fields.
|
| if (!old_map->InstancesNeedRewriting(
|
| - *new_map, number_of_fields, inobject, unused)) {
|
| - object->set_map(*new_map);
|
| - return;
|
| + new_map, number_of_fields, inobject, unused)) {
|
| + set_map(new_map);
|
| + return this;
|
| }
|
|
|
| int total_size = number_of_fields + unused;
|
| int external = total_size - inobject;
|
| - Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
|
| + FixedArray* array;
|
| + MaybeObject* maybe_array = heap->AllocateFixedArray(total_size);
|
| + if (!maybe_array->To(&array)) return maybe_array;
|
|
|
| DescriptorArray* old_descriptors = old_map->instance_descriptors();
|
| DescriptorArray* new_descriptors = new_map->instance_descriptors();
|
| @@ -2318,51 +2324,55 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
|
| }
|
| ASSERT(old_details.type() == CONSTANT ||
|
| old_details.type() == FIELD);
|
| - Object* raw_value = old_details.type() == CONSTANT
|
| + Object* value = old_details.type() == CONSTANT
|
| ? old_descriptors->GetValue(i)
|
| - : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
|
| - Handle<Object> value(raw_value, isolate);
|
| + : RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
|
| if (FLAG_track_double_fields &&
|
| !old_details.representation().IsDouble() &&
|
| details.representation().IsDouble()) {
|
| - if (old_details.representation().IsNone()) {
|
| - value = handle(Smi::FromInt(0), isolate);
|
| - }
|
| - value = NewStorageFor(isolate, value, details.representation());
|
| + if (old_details.representation().IsNone()) value = Smi::FromInt(0);
|
| + // Objects must be allocated in the old object space, since the
|
| + // overall number of HeapNumbers needed for the conversion might
|
| + // exceed the capacity of new space, and we would fail repeatedly
|
| + // trying to migrate the instance.
|
| + MaybeObject* maybe_storage =
|
| + value->AllocateNewStorageFor(heap, details.representation(), TENURED);
|
| + if (!maybe_storage->To(&value)) return maybe_storage;
|
| }
|
| ASSERT(!(FLAG_track_double_fields &&
|
| details.representation().IsDouble() &&
|
| value->IsSmi()));
|
| int target_index = new_descriptors->GetFieldIndex(i) - inobject;
|
| if (target_index < 0) target_index += total_size;
|
| - array->set(target_index, *value);
|
| + array->set(target_index, value);
|
| }
|
|
|
| - // From here on we cannot fail and we shouldn't GC anymore.
|
| - DisallowHeapAllocation no_allocation;
|
| + // From here on we cannot fail anymore.
|
|
|
| // Copy (real) inobject properties. If necessary, stop at number_of_fields to
|
| // avoid overwriting |one_pointer_filler_map|.
|
| int limit = Min(inobject, number_of_fields);
|
| for (int i = 0; i < limit; i++) {
|
| - object->FastPropertyAtPut(i, array->get(external + i));
|
| + FastPropertyAtPut(i, array->get(external + i));
|
| }
|
|
|
| // Create filler object past the new instance size.
|
| int new_instance_size = new_map->instance_size();
|
| int instance_size_delta = old_map->instance_size() - new_instance_size;
|
| ASSERT(instance_size_delta >= 0);
|
| - Address address = object->address() + new_instance_size;
|
| - isolate->heap()->CreateFillerObjectAt(address, instance_size_delta);
|
| + Address address = this->address() + new_instance_size;
|
| + heap->CreateFillerObjectAt(address, instance_size_delta);
|
|
|
| // If there are properties in the new backing store, trim it to the correct
|
| // size and install the backing store into the object.
|
| if (external > 0) {
|
| - RightTrimFixedArray<FROM_MUTATOR>(isolate->heap(), *array, inobject);
|
| - object->set_properties(*array);
|
| + RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject);
|
| + set_properties(array);
|
| }
|
|
|
| - object->set_map(*new_map);
|
| + set_map(new_map);
|
| +
|
| + return this;
|
| }
|
|
|
|
|
| @@ -3748,13 +3758,7 @@ void JSObject::MigrateInstance(Handle<JSObject> object) {
|
|
|
|
|
| Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) {
|
| - Map* new_map = object->map()->CurrentMapForDeprecated();
|
| - if (new_map == NULL) return Handle<Object>();
|
| - Handle<Map> original_map(object->map());
|
| - JSObject::MigrateToMap(object, handle(new_map));
|
| - if (FLAG_trace_migration) {
|
| - object->PrintInstanceMigration(stdout, *original_map, object->map());
|
| - }
|
| + MigrateInstance(object);
|
| return object;
|
| }
|
|
|
|
|