Index: src/mark-compact.cc |
=================================================================== |
--- src/mark-compact.cc (revision 3405) |
+++ src/mark-compact.cc (working copy) |
@@ -1698,6 +1698,8 @@ |
} |
+// Not used for objects in data space as it doesn't handle heap number alignment |
+// issues. |
int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj, |
PagedSpace* space) { |
// Recover map pointer. |
@@ -1714,7 +1716,7 @@ |
Address old_addr = obj->address(); |
if (new_addr != old_addr) { |
- memmove(new_addr, old_addr, obj_size); // Copy contents |
+ memmove(new_addr, old_addr, obj_size); // Copy contents. |
} |
ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); |
@@ -1729,7 +1731,32 @@ |
int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) { |
- return RelocateOldNonCodeObject(obj, Heap::old_data_space()); |
+ // Recover map pointer. |
+ MapWord encoding = obj->map_word(); |
+ Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); |
+ ASSERT(Heap::map_space()->Contains(map_addr)); |
+ |
+ // Get forwarding address before resetting map pointer. |
+ Address new_addr = GetForwardingAddressInOldSpace(obj); |
+ |
+ // Reset the map pointer. |
+ int obj_size = RestoreMap(obj, Heap::old_data_space(), new_addr, map_addr); |
+ |
+ Address old_addr = obj->address(); |
+ |
+ if (new_addr != old_addr) { |
+ if (HeapNumber::NeedsSpecialCopying(obj_size, new_addr, old_addr)) { |
+ memmove(new_addr, old_addr, kPointerSize); // Copy map. |
+ HeapNumber::cast(HeapObject::FromAddress(new_addr))->set_value( |
+ HeapNumber::cast(obj)->value()); |
+ } else { |
+ memmove(new_addr, old_addr, obj_size); // Copy contents. |
+ } |
+ } |
+ |
+ ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); |
+ |
+ return obj_size; |
} |
@@ -1771,7 +1798,7 @@ |
int MarkCompactCollector::RelocateNewObject(HeapObject* obj) { |
int obj_size = obj->Size(); |
- // Get forwarding address |
+ // Get forwarding address. |
Address old_addr = obj->address(); |
int offset = Heap::new_space()->ToSpaceOffsetForAddress(old_addr); |
@@ -1788,10 +1815,18 @@ |
} |
#endif |
- // New and old addresses cannot overlap. |
- memcpy(reinterpret_cast<void*>(new_addr), |
- reinterpret_cast<void*>(old_addr), |
- obj_size); |
+ if (HeapNumber::NeedsSpecialCopying(obj_size, new_addr, old_addr)) { |
+ memcpy(reinterpret_cast<void*>(new_addr), |
+ reinterpret_cast<void*>(old_addr), |
+ kPointerSize); |
+ HeapNumber::cast(HeapObject::FromAddress(new_addr))->set_value( |
+ HeapNumber::cast(obj)->value()); |
+ } else { |
+ // New and old addresses cannot overlap. |
+ memcpy(reinterpret_cast<void*>(new_addr), |
+ reinterpret_cast<void*>(old_addr), |
+ obj_size); |
+ } |
#ifdef DEBUG |
if (FLAG_gc_verbose) { |