| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index ae8409e13f2bac649e97a83596bf854735ce324c..886d26a22d0d5bfd4b0ea752612d23387ba6d419 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -1922,6 +1922,50 @@ void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
|
| }
|
|
|
|
|
| +// Returns true if during migration from |old_map| to |new_map| "tagged"
|
| +// inobject fields are going to be replaced with unboxed double fields.
|
| +static bool ShouldClearSlotsRecorded(Map* old_map, Map* new_map,
|
| + int new_number_of_fields) {
|
| + DisallowHeapAllocation no_gc;
|
| + int inobject = new_map->inobject_properties();
|
| + DCHECK(inobject <= old_map->inobject_properties());
|
| +
|
| + int limit = Min(inobject, new_number_of_fields);
|
| + for (int i = 0; i < limit; i++) {
|
| + FieldIndex index = FieldIndex::ForPropertyIndex(new_map, i);
|
| + if (new_map->IsUnboxedDoubleField(index) &&
|
| + !old_map->IsUnboxedDoubleField(index)) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +
|
| +static void RemoveOldToOldSlotsRecorded(Heap* heap, JSObject* object,
|
| + FieldIndex index) {
|
| + DisallowHeapAllocation no_gc;
|
| +
|
| + Object* old_value = object->RawFastPropertyAt(index);
|
| + if (old_value->IsHeapObject()) {
|
| + HeapObject* ho = HeapObject::cast(old_value);
|
| + if (heap->InNewSpace(ho)) {
|
| + // At this point there must be no old-to-new slots recorded for this
|
| + // object.
|
| + SLOW_DCHECK(
|
| + !heap->store_buffer()->CellIsInStoreBuffer(reinterpret_cast<Address>(
|
| + HeapObject::RawField(object, index.offset()))));
|
| + } else {
|
| + Page* p = Page::FromAddress(reinterpret_cast<Address>(ho));
|
| + if (p->IsEvacuationCandidate()) {
|
| + Object** slot = HeapObject::RawField(object, index.offset());
|
| + SlotsBuffer::RemoveSlot(p->slots_buffer(), slot);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| // To migrate a fast instance to a fast map:
|
| // - First check whether the instance needs to be rewritten. If not, simply
|
| // change the map.
|
| @@ -2075,16 +2119,32 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
|
| // From here on we cannot fail and we shouldn't GC anymore.
|
| DisallowHeapAllocation no_allocation;
|
|
|
| + Heap* heap = isolate->heap();
|
| +
|
| + // If we are going to put an unboxed double to the field that used to
|
| + // contain HeapObject we should ensure that this slot is removed from
|
| + // both StoreBuffer and respective SlotsBuffer.
|
| + bool clear_slots_recorded =
|
| + FLAG_unbox_double_fields && !heap->InNewSpace(object->address()) &&
|
| + ShouldClearSlotsRecorded(*old_map, *new_map, number_of_fields);
|
| + if (clear_slots_recorded) {
|
| + Address obj_address = object->address();
|
| + Address start_address = obj_address + JSObject::kHeaderSize;
|
| + Address end_address = obj_address + old_map->instance_size();
|
| + heap->store_buffer()->RemoveSlots(start_address, end_address);
|
| + }
|
| +
|
| // 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++) {
|
| FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
|
| Object* value = array->get(external + i);
|
| - // Can't use JSObject::FastPropertyAtPut() because proper map was not set
|
| - // yet.
|
| if (new_map->IsUnboxedDoubleField(index)) {
|
| DCHECK(value->IsMutableHeapNumber());
|
| + if (clear_slots_recorded && !old_map->IsUnboxedDoubleField(index)) {
|
| + RemoveOldToOldSlotsRecorded(heap, *object, index);
|
| + }
|
| object->RawFastDoublePropertyAtPut(index,
|
| HeapNumber::cast(value)->value());
|
| } else {
|
| @@ -2092,8 +2152,6 @@ void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
|
| }
|
| }
|
|
|
| - Heap* heap = isolate->heap();
|
| -
|
| // 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) {
|
|
|