| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 MarkCompactCollector::CollectorState MarkCompactCollector::state_ = IDLE; | 49 MarkCompactCollector::CollectorState MarkCompactCollector::state_ = IDLE; |
| 50 | 50 |
| 51 // Counters used for debugging the marking phase of mark-compact or mark-sweep | 51 // Counters used for debugging the marking phase of mark-compact or mark-sweep |
| 52 // collection. | 52 // collection. |
| 53 int MarkCompactCollector::live_bytes_ = 0; | 53 int MarkCompactCollector::live_bytes_ = 0; |
| 54 int MarkCompactCollector::live_young_objects_ = 0; | 54 int MarkCompactCollector::live_young_objects_ = 0; |
| 55 int MarkCompactCollector::live_old_data_objects_ = 0; | 55 int MarkCompactCollector::live_old_data_objects_ = 0; |
| 56 int MarkCompactCollector::live_old_pointer_objects_ = 0; | 56 int MarkCompactCollector::live_old_pointer_objects_ = 0; |
| 57 int MarkCompactCollector::live_code_objects_ = 0; | 57 int MarkCompactCollector::live_code_objects_ = 0; |
| 58 int MarkCompactCollector::live_map_objects_ = 0; | 58 int MarkCompactCollector::live_map_objects_ = 0; |
| 59 int MarkCompactCollector::live_cell_objects_ = 0; |
| 59 int MarkCompactCollector::live_lo_objects_ = 0; | 60 int MarkCompactCollector::live_lo_objects_ = 0; |
| 60 #endif | 61 #endif |
| 61 | 62 |
| 62 void MarkCompactCollector::CollectGarbage() { | 63 void MarkCompactCollector::CollectGarbage() { |
| 63 // Make sure that Prepare() has been called. The individual steps below will | 64 // Make sure that Prepare() has been called. The individual steps below will |
| 64 // update the state as they proceed. | 65 // update the state as they proceed. |
| 65 ASSERT(state_ == PREPARE_GC); | 66 ASSERT(state_ == PREPARE_GC); |
| 66 | 67 |
| 67 // Prepare has selected whether to compact the old generation or not. | 68 // Prepare has selected whether to compact the old generation or not. |
| 68 // Tell the tracer. | 69 // Tell the tracer. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 space->PrepareForMarkCompact(compacting_collection_); | 149 space->PrepareForMarkCompact(compacting_collection_); |
| 149 } | 150 } |
| 150 | 151 |
| 151 #ifdef DEBUG | 152 #ifdef DEBUG |
| 152 live_bytes_ = 0; | 153 live_bytes_ = 0; |
| 153 live_young_objects_ = 0; | 154 live_young_objects_ = 0; |
| 154 live_old_pointer_objects_ = 0; | 155 live_old_pointer_objects_ = 0; |
| 155 live_old_data_objects_ = 0; | 156 live_old_data_objects_ = 0; |
| 156 live_code_objects_ = 0; | 157 live_code_objects_ = 0; |
| 157 live_map_objects_ = 0; | 158 live_map_objects_ = 0; |
| 159 live_cell_objects_ = 0; |
| 158 live_lo_objects_ = 0; | 160 live_lo_objects_ = 0; |
| 159 #endif | 161 #endif |
| 160 } | 162 } |
| 161 | 163 |
| 162 | 164 |
| 163 void MarkCompactCollector::Finish() { | 165 void MarkCompactCollector::Finish() { |
| 164 #ifdef DEBUG | 166 #ifdef DEBUG |
| 165 ASSERT(state_ == SWEEP_SPACES || state_ == REBUILD_RSETS); | 167 ASSERT(state_ == SWEEP_SPACES || state_ == REBUILD_RSETS); |
| 166 state_ = IDLE; | 168 state_ = IDLE; |
| 167 #endif | 169 #endif |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 if (marking_stack.is_full()) return; | 703 if (marking_stack.is_full()) return; |
| 702 | 704 |
| 703 HeapObjectIterator code_it(Heap::code_space(), &OverflowObjectSize); | 705 HeapObjectIterator code_it(Heap::code_space(), &OverflowObjectSize); |
| 704 ScanOverflowedObjects(&code_it); | 706 ScanOverflowedObjects(&code_it); |
| 705 if (marking_stack.is_full()) return; | 707 if (marking_stack.is_full()) return; |
| 706 | 708 |
| 707 HeapObjectIterator map_it(Heap::map_space(), &OverflowObjectSize); | 709 HeapObjectIterator map_it(Heap::map_space(), &OverflowObjectSize); |
| 708 ScanOverflowedObjects(&map_it); | 710 ScanOverflowedObjects(&map_it); |
| 709 if (marking_stack.is_full()) return; | 711 if (marking_stack.is_full()) return; |
| 710 | 712 |
| 713 HeapObjectIterator cell_it(Heap::cell_space(), &OverflowObjectSize); |
| 714 ScanOverflowedObjects(&cell_it); |
| 715 if (marking_stack.is_full()) return; |
| 716 |
| 711 LargeObjectIterator lo_it(Heap::lo_space(), &OverflowObjectSize); | 717 LargeObjectIterator lo_it(Heap::lo_space(), &OverflowObjectSize); |
| 712 ScanOverflowedObjects(&lo_it); | 718 ScanOverflowedObjects(&lo_it); |
| 713 if (marking_stack.is_full()) return; | 719 if (marking_stack.is_full()) return; |
| 714 | 720 |
| 715 marking_stack.clear_overflowed(); | 721 marking_stack.clear_overflowed(); |
| 716 } | 722 } |
| 717 | 723 |
| 718 | 724 |
| 719 // Mark all objects reachable (transitively) from objects on the marking | 725 // Mark all objects reachable (transitively) from objects on the marking |
| 720 // stack. Before: the marking stack contains zero or more heap object | 726 // stack. Before: the marking stack contains zero or more heap object |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 | 807 |
| 802 | 808 |
| 803 #ifdef DEBUG | 809 #ifdef DEBUG |
| 804 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { | 810 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { |
| 805 live_bytes_ += obj->Size(); | 811 live_bytes_ += obj->Size(); |
| 806 if (Heap::new_space()->Contains(obj)) { | 812 if (Heap::new_space()->Contains(obj)) { |
| 807 live_young_objects_++; | 813 live_young_objects_++; |
| 808 } else if (Heap::map_space()->Contains(obj)) { | 814 } else if (Heap::map_space()->Contains(obj)) { |
| 809 ASSERT(obj->IsMap()); | 815 ASSERT(obj->IsMap()); |
| 810 live_map_objects_++; | 816 live_map_objects_++; |
| 817 } else if (Heap::cell_space()->Contains(obj)) { |
| 818 ASSERT(obj->IsJSGlobalPropertyCell()); |
| 819 live_cell_objects_++; |
| 811 } else if (Heap::old_pointer_space()->Contains(obj)) { | 820 } else if (Heap::old_pointer_space()->Contains(obj)) { |
| 812 live_old_pointer_objects_++; | 821 live_old_pointer_objects_++; |
| 813 } else if (Heap::old_data_space()->Contains(obj)) { | 822 } else if (Heap::old_data_space()->Contains(obj)) { |
| 814 live_old_data_objects_++; | 823 live_old_data_objects_++; |
| 815 } else if (Heap::code_space()->Contains(obj)) { | 824 } else if (Heap::code_space()->Contains(obj)) { |
| 816 live_code_objects_++; | 825 live_code_objects_++; |
| 817 } else if (Heap::lo_space()->Contains(obj)) { | 826 } else if (Heap::lo_space()->Contains(obj)) { |
| 818 live_lo_objects_++; | 827 live_lo_objects_++; |
| 819 } else { | 828 } else { |
| 820 UNREACHABLE(); | 829 UNREACHABLE(); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 960 forwarded = target_space->MCAllocateRaw(object_size); | 969 forwarded = target_space->MCAllocateRaw(object_size); |
| 961 } | 970 } |
| 962 if (forwarded->IsFailure()) { | 971 if (forwarded->IsFailure()) { |
| 963 forwarded = Heap::new_space()->MCAllocateRaw(object_size); | 972 forwarded = Heap::new_space()->MCAllocateRaw(object_size); |
| 964 } | 973 } |
| 965 return forwarded; | 974 return forwarded; |
| 966 } | 975 } |
| 967 | 976 |
| 968 | 977 |
| 969 // Allocation functions for the paged spaces call the space's MCAllocateRaw. | 978 // Allocation functions for the paged spaces call the space's MCAllocateRaw. |
| 970 inline Object* MCAllocateFromOldPointerSpace(HeapObject* object, | 979 inline Object* MCAllocateFromOldPointerSpace(HeapObject* ignore, |
| 971 int object_size) { | 980 int object_size) { |
| 972 return Heap::old_pointer_space()->MCAllocateRaw(object_size); | 981 return Heap::old_pointer_space()->MCAllocateRaw(object_size); |
| 973 } | 982 } |
| 974 | 983 |
| 975 | 984 |
| 976 inline Object* MCAllocateFromOldDataSpace(HeapObject* object, int object_size) { | 985 inline Object* MCAllocateFromOldDataSpace(HeapObject* ignore, int object_size) { |
| 977 return Heap::old_data_space()->MCAllocateRaw(object_size); | 986 return Heap::old_data_space()->MCAllocateRaw(object_size); |
| 978 } | 987 } |
| 979 | 988 |
| 980 | 989 |
| 981 inline Object* MCAllocateFromCodeSpace(HeapObject* object, int object_size) { | 990 inline Object* MCAllocateFromCodeSpace(HeapObject* ignore, int object_size) { |
| 982 return Heap::code_space()->MCAllocateRaw(object_size); | 991 return Heap::code_space()->MCAllocateRaw(object_size); |
| 983 } | 992 } |
| 984 | 993 |
| 985 | 994 |
| 986 inline Object* MCAllocateFromMapSpace(HeapObject* object, int object_size) { | 995 inline Object* MCAllocateFromMapSpace(HeapObject* ignore, int object_size) { |
| 987 return Heap::map_space()->MCAllocateRaw(object_size); | 996 return Heap::map_space()->MCAllocateRaw(object_size); |
| 988 } | 997 } |
| 989 | 998 |
| 990 | 999 |
| 1000 inline Object* MCAllocateFromCellSpace(HeapObject* ignore, int object_size) { |
| 1001 return Heap::cell_space()->MCAllocateRaw(object_size); |
| 1002 } |
| 1003 |
| 1004 |
| 991 // The forwarding address is encoded at the same offset as the current | 1005 // The forwarding address is encoded at the same offset as the current |
| 992 // to-space object, but in from space. | 1006 // to-space object, but in from space. |
| 993 inline void EncodeForwardingAddressInNewSpace(HeapObject* old_object, | 1007 inline void EncodeForwardingAddressInNewSpace(HeapObject* old_object, |
| 994 int object_size, | 1008 int object_size, |
| 995 Object* new_object, | 1009 Object* new_object, |
| 996 int* ignored) { | 1010 int* ignored) { |
| 997 int offset = | 1011 int offset = |
| 998 Heap::new_space()->ToSpaceOffsetForAddress(old_object->address()); | 1012 Heap::new_space()->ToSpaceOffsetForAddress(old_object->address()); |
| 999 Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset) = | 1013 Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset) = |
| 1000 HeapObject::cast(new_object)->address(); | 1014 HeapObject::cast(new_object)->address(); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1139 MarkCompactCollector::tracer()->decrement_marked_count(); | 1153 MarkCompactCollector::tracer()->decrement_marked_count(); |
| 1140 } else { | 1154 } else { |
| 1141 // We give non-live objects a map that will correctly give their size, | 1155 // We give non-live objects a map that will correctly give their size, |
| 1142 // since their existing map might not be live after the collection. | 1156 // since their existing map might not be live after the collection. |
| 1143 int size = object->Size(); | 1157 int size = object->Size(); |
| 1144 if (size >= ByteArray::kHeaderSize) { | 1158 if (size >= ByteArray::kHeaderSize) { |
| 1145 object->set_map(Heap::byte_array_map()); | 1159 object->set_map(Heap::byte_array_map()); |
| 1146 ByteArray::cast(object)->set_length(ByteArray::LengthFor(size)); | 1160 ByteArray::cast(object)->set_length(ByteArray::LengthFor(size)); |
| 1147 } else { | 1161 } else { |
| 1148 ASSERT(size == kPointerSize); | 1162 ASSERT(size == kPointerSize); |
| 1149 object->set_map(Heap::one_word_filler_map()); | 1163 object->set_map(Heap::one_pointer_filler_map()); |
| 1150 } | 1164 } |
| 1151 ASSERT(object->Size() == size); | 1165 ASSERT(object->Size() == size); |
| 1152 } | 1166 } |
| 1153 // The object is now unmarked for the call to Size() at the top of the | 1167 // The object is now unmarked for the call to Size() at the top of the |
| 1154 // loop. | 1168 // loop. |
| 1155 } | 1169 } |
| 1156 } | 1170 } |
| 1157 | 1171 |
| 1158 | 1172 |
| 1159 static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) { | 1173 static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1189 } | 1203 } |
| 1190 if (is_previous_alive) { // Transition from live to free. | 1204 if (is_previous_alive) { // Transition from live to free. |
| 1191 free_start = current; | 1205 free_start = current; |
| 1192 is_previous_alive = false; | 1206 is_previous_alive = false; |
| 1193 } | 1207 } |
| 1194 } | 1208 } |
| 1195 // The object is now unmarked for the call to Size() at the top of the | 1209 // The object is now unmarked for the call to Size() at the top of the |
| 1196 // loop. | 1210 // loop. |
| 1197 } | 1211 } |
| 1198 | 1212 |
| 1199 // If the last region was not live we need to from free_start to the | 1213 // If the last region was not live we need to deallocate from |
| 1200 // allocation top in the page. | 1214 // free_start to the allocation top in the page. |
| 1201 if (!is_previous_alive) { | 1215 if (!is_previous_alive) { |
| 1202 int free_size = p->AllocationTop() - free_start; | 1216 int free_size = p->AllocationTop() - free_start; |
| 1203 if (free_size > 0) { | 1217 if (free_size > 0) { |
| 1204 dealloc(free_start, free_size); | 1218 dealloc(free_start, free_size); |
| 1205 } | 1219 } |
| 1206 } | 1220 } |
| 1207 } | 1221 } |
| 1208 } | 1222 } |
| 1209 | 1223 |
| 1210 | 1224 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1234 // chunks and free them separately. | 1248 // chunks and free them separately. |
| 1235 ASSERT(size_in_bytes % Map::kSize == 0); | 1249 ASSERT(size_in_bytes % Map::kSize == 0); |
| 1236 Heap::ClearRSetRange(start, size_in_bytes); | 1250 Heap::ClearRSetRange(start, size_in_bytes); |
| 1237 Address end = start + size_in_bytes; | 1251 Address end = start + size_in_bytes; |
| 1238 for (Address a = start; a < end; a += Map::kSize) { | 1252 for (Address a = start; a < end; a += Map::kSize) { |
| 1239 Heap::map_space()->Free(a); | 1253 Heap::map_space()->Free(a); |
| 1240 } | 1254 } |
| 1241 } | 1255 } |
| 1242 | 1256 |
| 1243 | 1257 |
| 1258 void MarkCompactCollector::DeallocateCellBlock(Address start, |
| 1259 int size_in_bytes) { |
| 1260 // Free-list elements in cell space are assumed to have a fixed size. |
| 1261 // We break the free block into chunks and add them to the free list |
| 1262 // individually. |
| 1263 int size = Heap::cell_space()->object_size_in_bytes(); |
| 1264 ASSERT(size_in_bytes % size == 0); |
| 1265 Heap::ClearRSetRange(start, size_in_bytes); |
| 1266 Address end = start + size_in_bytes; |
| 1267 for (Address a = start; a < end; a += size) { |
| 1268 Heap::cell_space()->Free(a); |
| 1269 } |
| 1270 } |
| 1271 |
| 1272 |
| 1244 void MarkCompactCollector::EncodeForwardingAddresses() { | 1273 void MarkCompactCollector::EncodeForwardingAddresses() { |
| 1245 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); | 1274 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); |
| 1246 // Objects in the active semispace of the young generation may be | 1275 // Objects in the active semispace of the young generation may be |
| 1247 // relocated to the inactive semispace (if not promoted). Set the | 1276 // relocated to the inactive semispace (if not promoted). Set the |
| 1248 // relocation info to the beginning of the inactive semispace. | 1277 // relocation info to the beginning of the inactive semispace. |
| 1249 Heap::new_space()->MCResetRelocationInfo(); | 1278 Heap::new_space()->MCResetRelocationInfo(); |
| 1250 | 1279 |
| 1251 // Compute the forwarding pointers in each space. | 1280 // Compute the forwarding pointers in each space. |
| 1252 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace, | 1281 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldPointerSpace, |
| 1253 IgnoreNonLiveObject>( | 1282 IgnoreNonLiveObject>( |
| 1254 Heap::old_pointer_space()); | 1283 Heap::old_pointer_space()); |
| 1255 | 1284 |
| 1256 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace, | 1285 EncodeForwardingAddressesInPagedSpace<MCAllocateFromOldDataSpace, |
| 1257 IgnoreNonLiveObject>( | 1286 IgnoreNonLiveObject>( |
| 1258 Heap::old_data_space()); | 1287 Heap::old_data_space()); |
| 1259 | 1288 |
| 1260 EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace, | 1289 EncodeForwardingAddressesInPagedSpace<MCAllocateFromCodeSpace, |
| 1261 LogNonLiveCodeObject>( | 1290 LogNonLiveCodeObject>( |
| 1262 Heap::code_space()); | 1291 Heap::code_space()); |
| 1263 | 1292 |
| 1293 EncodeForwardingAddressesInPagedSpace<MCAllocateFromCellSpace, |
| 1294 IgnoreNonLiveObject>( |
| 1295 Heap::cell_space()); |
| 1296 |
| 1297 |
| 1264 // Compute new space next to last after the old and code spaces have been | 1298 // Compute new space next to last after the old and code spaces have been |
| 1265 // compacted. Objects in new space can be promoted to old or code space. | 1299 // compacted. Objects in new space can be promoted to old or code space. |
| 1266 EncodeForwardingAddressesInNewSpace(); | 1300 EncodeForwardingAddressesInNewSpace(); |
| 1267 | 1301 |
| 1268 // Compute map space last because computing forwarding addresses | 1302 // Compute map space last because computing forwarding addresses |
| 1269 // overwrites non-live objects. Objects in the other spaces rely on | 1303 // overwrites non-live objects. Objects in the other spaces rely on |
| 1270 // non-live map pointers to get the sizes of non-live objects. | 1304 // non-live map pointers to get the sizes of non-live objects. |
| 1271 EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace, | 1305 EncodeForwardingAddressesInPagedSpace<MCAllocateFromMapSpace, |
| 1272 IgnoreNonLiveObject>( | 1306 IgnoreNonLiveObject>( |
| 1273 Heap::map_space()); | 1307 Heap::map_space()); |
| 1274 | 1308 |
| 1275 // Write relocation info to the top page, so we can use it later. This is | 1309 // Write relocation info to the top page, so we can use it later. This is |
| 1276 // done after promoting objects from the new space so we get the correct | 1310 // done after promoting objects from the new space so we get the correct |
| 1277 // allocation top. | 1311 // allocation top. |
| 1278 Heap::old_pointer_space()->MCWriteRelocationInfoToPage(); | 1312 Heap::old_pointer_space()->MCWriteRelocationInfoToPage(); |
| 1279 Heap::old_data_space()->MCWriteRelocationInfoToPage(); | 1313 Heap::old_data_space()->MCWriteRelocationInfoToPage(); |
| 1280 Heap::code_space()->MCWriteRelocationInfoToPage(); | 1314 Heap::code_space()->MCWriteRelocationInfoToPage(); |
| 1281 Heap::map_space()->MCWriteRelocationInfoToPage(); | 1315 Heap::map_space()->MCWriteRelocationInfoToPage(); |
| 1316 Heap::cell_space()->MCWriteRelocationInfoToPage(); |
| 1282 } | 1317 } |
| 1283 | 1318 |
| 1284 | 1319 |
| 1285 void MarkCompactCollector::SweepSpaces() { | 1320 void MarkCompactCollector::SweepSpaces() { |
| 1286 ASSERT(state_ == SWEEP_SPACES); | 1321 ASSERT(state_ == SWEEP_SPACES); |
| 1287 ASSERT(!IsCompacting()); | 1322 ASSERT(!IsCompacting()); |
| 1288 // Noncompacting collections simply sweep the spaces to clear the mark | 1323 // Noncompacting collections simply sweep the spaces to clear the mark |
| 1289 // bits and free the nonlive blocks (for old and map spaces). We sweep | 1324 // bits and free the nonlive blocks (for old and map spaces). We sweep |
| 1290 // the map space last because freeing non-live maps overwrites them and | 1325 // the map space last because freeing non-live maps overwrites them and |
| 1291 // the other spaces rely on possibly non-live maps to get the sizes for | 1326 // the other spaces rely on possibly non-live maps to get the sizes for |
| 1292 // non-live objects. | 1327 // non-live objects. |
| 1293 SweepSpace(Heap::old_pointer_space(), &DeallocateOldPointerBlock); | 1328 SweepSpace(Heap::old_pointer_space(), &DeallocateOldPointerBlock); |
| 1294 SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock); | 1329 SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock); |
| 1295 SweepSpace(Heap::code_space(), &DeallocateCodeBlock); | 1330 SweepSpace(Heap::code_space(), &DeallocateCodeBlock); |
| 1331 SweepSpace(Heap::cell_space(), &DeallocateCellBlock); |
| 1296 SweepSpace(Heap::new_space()); | 1332 SweepSpace(Heap::new_space()); |
| 1297 SweepSpace(Heap::map_space(), &DeallocateMapBlock); | 1333 SweepSpace(Heap::map_space(), &DeallocateMapBlock); |
| 1298 } | 1334 } |
| 1299 | 1335 |
| 1300 | 1336 |
| 1301 // Iterate the live objects in a range of addresses (eg, a page or a | 1337 // Iterate the live objects in a range of addresses (eg, a page or a |
| 1302 // semispace). The live regions of the range have been linked into a list. | 1338 // semispace). The live regions of the range have been linked into a list. |
| 1303 // The first live region is [first_live_start, first_live_end), and the last | 1339 // The first live region is [first_live_start, first_live_end), and the last |
| 1304 // address in the range is top. The callback function is used to get the | 1340 // address in the range is top. The callback function is used to get the |
| 1305 // size of each live object. | 1341 // size of each live object. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1364 private: | 1400 private: |
| 1365 void UpdatePointer(Object** p) { | 1401 void UpdatePointer(Object** p) { |
| 1366 if (!(*p)->IsHeapObject()) return; | 1402 if (!(*p)->IsHeapObject()) return; |
| 1367 | 1403 |
| 1368 HeapObject* obj = HeapObject::cast(*p); | 1404 HeapObject* obj = HeapObject::cast(*p); |
| 1369 Address old_addr = obj->address(); | 1405 Address old_addr = obj->address(); |
| 1370 Address new_addr; | 1406 Address new_addr; |
| 1371 ASSERT(!Heap::InFromSpace(obj)); | 1407 ASSERT(!Heap::InFromSpace(obj)); |
| 1372 | 1408 |
| 1373 if (Heap::new_space()->Contains(obj)) { | 1409 if (Heap::new_space()->Contains(obj)) { |
| 1374 Address f_addr = Heap::new_space()->FromSpaceLow() + | 1410 Address forwarding_pointer_addr = |
| 1375 Heap::new_space()->ToSpaceOffsetForAddress(old_addr); | 1411 Heap::new_space()->FromSpaceLow() + |
| 1376 new_addr = Memory::Address_at(f_addr); | 1412 Heap::new_space()->ToSpaceOffsetForAddress(old_addr); |
| 1413 new_addr = Memory::Address_at(forwarding_pointer_addr); |
| 1377 | 1414 |
| 1378 #ifdef DEBUG | 1415 #ifdef DEBUG |
| 1379 ASSERT(Heap::old_pointer_space()->Contains(new_addr) || | 1416 ASSERT(Heap::old_pointer_space()->Contains(new_addr) || |
| 1380 Heap::old_data_space()->Contains(new_addr) || | 1417 Heap::old_data_space()->Contains(new_addr) || |
| 1381 Heap::code_space()->Contains(new_addr) || | 1418 Heap::new_space()->FromSpaceContains(new_addr) || |
| 1382 Heap::new_space()->FromSpaceContains(new_addr)); | 1419 Heap::lo_space()->Contains(HeapObject::FromAddress(new_addr))); |
| 1383 | 1420 |
| 1384 if (Heap::new_space()->FromSpaceContains(new_addr)) { | 1421 if (Heap::new_space()->FromSpaceContains(new_addr)) { |
| 1385 ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= | 1422 ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= |
| 1386 Heap::new_space()->ToSpaceOffsetForAddress(old_addr)); | 1423 Heap::new_space()->ToSpaceOffsetForAddress(old_addr)); |
| 1387 } | 1424 } |
| 1388 #endif | 1425 #endif |
| 1389 | 1426 |
| 1390 } else if (Heap::lo_space()->Contains(obj)) { | 1427 } else if (Heap::lo_space()->Contains(obj)) { |
| 1391 // Don't move objects in the large object space. | 1428 // Don't move objects in the large object space. |
| 1392 return; | 1429 return; |
| 1393 | 1430 |
| 1394 } else { | 1431 } else { |
| 1395 ASSERT(Heap::old_pointer_space()->Contains(obj) || | 1432 #ifdef DEBUG |
| 1396 Heap::old_data_space()->Contains(obj) || | 1433 PagedSpaces spaces; |
| 1397 Heap::code_space()->Contains(obj) || | 1434 PagedSpace* original_space = spaces.next(); |
| 1398 Heap::map_space()->Contains(obj)); | 1435 while (original_space != NULL) { |
| 1399 | 1436 if (original_space->Contains(obj)) break; |
| 1437 original_space = spaces.next(); |
| 1438 } |
| 1439 ASSERT(original_space != NULL); |
| 1440 #endif |
| 1400 new_addr = MarkCompactCollector::GetForwardingAddressInOldSpace(obj); | 1441 new_addr = MarkCompactCollector::GetForwardingAddressInOldSpace(obj); |
| 1401 ASSERT(Heap::old_pointer_space()->Contains(new_addr) || | 1442 ASSERT(original_space->Contains(new_addr)); |
| 1402 Heap::old_data_space()->Contains(new_addr) || | 1443 ASSERT(original_space->MCSpaceOffsetForAddress(new_addr) <= |
| 1403 Heap::code_space()->Contains(new_addr) || | 1444 original_space->MCSpaceOffsetForAddress(old_addr)); |
| 1404 Heap::map_space()->Contains(new_addr)); | |
| 1405 | |
| 1406 #ifdef DEBUG | |
| 1407 if (Heap::old_pointer_space()->Contains(obj)) { | |
| 1408 ASSERT(Heap::old_pointer_space()->MCSpaceOffsetForAddress(new_addr) <= | |
| 1409 Heap::old_pointer_space()->MCSpaceOffsetForAddress(old_addr)); | |
| 1410 } else if (Heap::old_data_space()->Contains(obj)) { | |
| 1411 ASSERT(Heap::old_data_space()->MCSpaceOffsetForAddress(new_addr) <= | |
| 1412 Heap::old_data_space()->MCSpaceOffsetForAddress(old_addr)); | |
| 1413 } else if (Heap::code_space()->Contains(obj)) { | |
| 1414 ASSERT(Heap::code_space()->MCSpaceOffsetForAddress(new_addr) <= | |
| 1415 Heap::code_space()->MCSpaceOffsetForAddress(old_addr)); | |
| 1416 } else { | |
| 1417 ASSERT(Heap::map_space()->MCSpaceOffsetForAddress(new_addr) <= | |
| 1418 Heap::map_space()->MCSpaceOffsetForAddress(old_addr)); | |
| 1419 } | |
| 1420 #endif | |
| 1421 } | 1445 } |
| 1422 | 1446 |
| 1423 *p = HeapObject::FromAddress(new_addr); | 1447 *p = HeapObject::FromAddress(new_addr); |
| 1424 | 1448 |
| 1425 #ifdef DEBUG | 1449 #ifdef DEBUG |
| 1426 if (FLAG_gc_verbose) { | 1450 if (FLAG_gc_verbose) { |
| 1427 PrintF("update %p : %p -> %p\n", | 1451 PrintF("update %p : %p -> %p\n", |
| 1428 reinterpret_cast<Address>(p), old_addr, new_addr); | 1452 reinterpret_cast<Address>(p), old_addr, new_addr); |
| 1429 } | 1453 } |
| 1430 #endif | 1454 #endif |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1442 GlobalHandles::IterateWeakRoots(&updating_visitor); | 1466 GlobalHandles::IterateWeakRoots(&updating_visitor); |
| 1443 | 1467 |
| 1444 int live_maps = IterateLiveObjects(Heap::map_space(), | 1468 int live_maps = IterateLiveObjects(Heap::map_space(), |
| 1445 &UpdatePointersInOldObject); | 1469 &UpdatePointersInOldObject); |
| 1446 int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), | 1470 int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), |
| 1447 &UpdatePointersInOldObject); | 1471 &UpdatePointersInOldObject); |
| 1448 int live_data_olds = IterateLiveObjects(Heap::old_data_space(), | 1472 int live_data_olds = IterateLiveObjects(Heap::old_data_space(), |
| 1449 &UpdatePointersInOldObject); | 1473 &UpdatePointersInOldObject); |
| 1450 int live_codes = IterateLiveObjects(Heap::code_space(), | 1474 int live_codes = IterateLiveObjects(Heap::code_space(), |
| 1451 &UpdatePointersInOldObject); | 1475 &UpdatePointersInOldObject); |
| 1476 int live_cells = IterateLiveObjects(Heap::cell_space(), |
| 1477 &UpdatePointersInOldObject); |
| 1452 int live_news = IterateLiveObjects(Heap::new_space(), | 1478 int live_news = IterateLiveObjects(Heap::new_space(), |
| 1453 &UpdatePointersInNewObject); | 1479 &UpdatePointersInNewObject); |
| 1454 | 1480 |
| 1455 // Large objects do not move, the map word can be updated directly. | 1481 // Large objects do not move, the map word can be updated directly. |
| 1456 LargeObjectIterator it(Heap::lo_space()); | 1482 LargeObjectIterator it(Heap::lo_space()); |
| 1457 while (it.has_next()) UpdatePointersInNewObject(it.next()); | 1483 while (it.has_next()) UpdatePointersInNewObject(it.next()); |
| 1458 | 1484 |
| 1459 USE(live_maps); | 1485 USE(live_maps); |
| 1460 USE(live_pointer_olds); | 1486 USE(live_pointer_olds); |
| 1461 USE(live_data_olds); | 1487 USE(live_data_olds); |
| 1462 USE(live_codes); | 1488 USE(live_codes); |
| 1489 USE(live_cells); |
| 1463 USE(live_news); | 1490 USE(live_news); |
| 1464 | |
| 1465 #ifdef DEBUG | |
| 1466 ASSERT(live_maps == live_map_objects_); | 1491 ASSERT(live_maps == live_map_objects_); |
| 1467 ASSERT(live_data_olds == live_old_data_objects_); | 1492 ASSERT(live_data_olds == live_old_data_objects_); |
| 1468 ASSERT(live_pointer_olds == live_old_pointer_objects_); | 1493 ASSERT(live_pointer_olds == live_old_pointer_objects_); |
| 1469 ASSERT(live_codes == live_code_objects_); | 1494 ASSERT(live_codes == live_code_objects_); |
| 1495 ASSERT(live_cells == live_cell_objects_); |
| 1470 ASSERT(live_news == live_young_objects_); | 1496 ASSERT(live_news == live_young_objects_); |
| 1471 #endif | |
| 1472 } | 1497 } |
| 1473 | 1498 |
| 1474 | 1499 |
| 1475 int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) { | 1500 int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) { |
| 1476 // Keep old map pointers | 1501 // Keep old map pointers |
| 1477 Map* old_map = obj->map(); | 1502 Map* old_map = obj->map(); |
| 1478 ASSERT(old_map->IsHeapObject()); | 1503 ASSERT(old_map->IsHeapObject()); |
| 1479 | 1504 |
| 1480 Address forwarded = GetForwardingAddressInOldSpace(old_map); | 1505 Address forwarded = GetForwardingAddressInOldSpace(old_map); |
| 1481 | 1506 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1582 state_ = RELOCATE_OBJECTS; | 1607 state_ = RELOCATE_OBJECTS; |
| 1583 #endif | 1608 #endif |
| 1584 // Relocates objects, always relocate map objects first. Relocating | 1609 // Relocates objects, always relocate map objects first. Relocating |
| 1585 // objects in other space relies on map objects to get object size. | 1610 // objects in other space relies on map objects to get object size. |
| 1586 int live_maps = IterateLiveObjects(Heap::map_space(), &RelocateMapObject); | 1611 int live_maps = IterateLiveObjects(Heap::map_space(), &RelocateMapObject); |
| 1587 int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), | 1612 int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), |
| 1588 &RelocateOldPointerObject); | 1613 &RelocateOldPointerObject); |
| 1589 int live_data_olds = IterateLiveObjects(Heap::old_data_space(), | 1614 int live_data_olds = IterateLiveObjects(Heap::old_data_space(), |
| 1590 &RelocateOldDataObject); | 1615 &RelocateOldDataObject); |
| 1591 int live_codes = IterateLiveObjects(Heap::code_space(), &RelocateCodeObject); | 1616 int live_codes = IterateLiveObjects(Heap::code_space(), &RelocateCodeObject); |
| 1617 int live_cells = IterateLiveObjects(Heap::cell_space(), &RelocateCellObject); |
| 1592 int live_news = IterateLiveObjects(Heap::new_space(), &RelocateNewObject); | 1618 int live_news = IterateLiveObjects(Heap::new_space(), &RelocateNewObject); |
| 1593 | 1619 |
| 1594 USE(live_maps); | 1620 USE(live_maps); |
| 1595 USE(live_data_olds); | 1621 USE(live_data_olds); |
| 1596 USE(live_pointer_olds); | 1622 USE(live_pointer_olds); |
| 1597 USE(live_codes); | 1623 USE(live_codes); |
| 1624 USE(live_cells); |
| 1598 USE(live_news); | 1625 USE(live_news); |
| 1599 #ifdef DEBUG | |
| 1600 ASSERT(live_maps == live_map_objects_); | 1626 ASSERT(live_maps == live_map_objects_); |
| 1601 ASSERT(live_data_olds == live_old_data_objects_); | 1627 ASSERT(live_data_olds == live_old_data_objects_); |
| 1602 ASSERT(live_pointer_olds == live_old_pointer_objects_); | 1628 ASSERT(live_pointer_olds == live_old_pointer_objects_); |
| 1603 ASSERT(live_codes == live_code_objects_); | 1629 ASSERT(live_codes == live_code_objects_); |
| 1630 ASSERT(live_cells == live_cell_objects_); |
| 1604 ASSERT(live_news == live_young_objects_); | 1631 ASSERT(live_news == live_young_objects_); |
| 1605 #endif | |
| 1606 | 1632 |
| 1607 // Notify code object in LO to convert IC target to address | 1633 // Notify code object in LO to convert IC target to address |
| 1608 // This must happen after lo_space_->Compact | 1634 // This must happen after lo_space_->Compact |
| 1609 LargeObjectIterator it(Heap::lo_space()); | 1635 LargeObjectIterator it(Heap::lo_space()); |
| 1610 while (it.has_next()) { ConvertCodeICTargetToAddress(it.next()); } | 1636 while (it.has_next()) { ConvertCodeICTargetToAddress(it.next()); } |
| 1611 | 1637 |
| 1612 // Flips from and to spaces | 1638 // Flip from and to spaces |
| 1613 Heap::new_space()->Flip(); | 1639 Heap::new_space()->Flip(); |
| 1614 | 1640 |
| 1615 // Sets age_mark to bottom in to space | 1641 // Set age_mark to bottom in to space |
| 1616 Address mark = Heap::new_space()->bottom(); | 1642 Address mark = Heap::new_space()->bottom(); |
| 1617 Heap::new_space()->set_age_mark(mark); | 1643 Heap::new_space()->set_age_mark(mark); |
| 1618 | 1644 |
| 1619 Heap::new_space()->MCCommitRelocationInfo(); | 1645 Heap::new_space()->MCCommitRelocationInfo(); |
| 1620 #ifdef DEBUG | 1646 #ifdef DEBUG |
| 1621 // It is safe to write to the remembered sets as remembered sets on a | 1647 // It is safe to write to the remembered sets as remembered sets on a |
| 1622 // page-by-page basis after committing the m-c forwarding pointer. | 1648 // page-by-page basis after committing the m-c forwarding pointer. |
| 1623 Page::set_rset_state(Page::IN_USE); | 1649 Page::set_rset_state(Page::IN_USE); |
| 1624 #endif | 1650 #endif |
| 1625 PagedSpaces spaces; | 1651 PagedSpaces spaces; |
| 1626 while (PagedSpace* space = spaces.next()) space->MCCommitRelocationInfo(); | 1652 while (PagedSpace* space = spaces.next()) space->MCCommitRelocationInfo(); |
| 1627 } | 1653 } |
| 1628 | 1654 |
| 1629 | 1655 |
| 1630 int MarkCompactCollector::ConvertCodeICTargetToAddress(HeapObject* obj) { | 1656 int MarkCompactCollector::ConvertCodeICTargetToAddress(HeapObject* obj) { |
| 1631 if (obj->IsCode()) { | 1657 if (obj->IsCode()) { |
| 1632 Code::cast(obj)->ConvertICTargetsFromObjectToAddress(); | 1658 Code::cast(obj)->ConvertICTargetsFromObjectToAddress(); |
| 1633 } | 1659 } |
| 1634 return obj->Size(); | 1660 return obj->Size(); |
| 1635 } | 1661 } |
| 1636 | 1662 |
| 1637 | 1663 |
| 1638 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { | 1664 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { |
| 1639 // decode map pointer (forwarded address) | 1665 // Recover map pointer. |
| 1640 MapWord encoding = obj->map_word(); | 1666 MapWord encoding = obj->map_word(); |
| 1641 Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); | 1667 Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); |
| 1642 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); | 1668 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); |
| 1643 | 1669 |
| 1644 // Get forwarding address before resetting map pointer | 1670 // Get forwarding address before resetting map pointer |
| 1645 Address new_addr = GetForwardingAddressInOldSpace(obj); | 1671 Address new_addr = GetForwardingAddressInOldSpace(obj); |
| 1646 | 1672 |
| 1647 // recover map pointer | 1673 // Reset map pointer. The meta map object may not be copied yet so |
| 1674 // Map::cast does not yet work. |
| 1648 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); | 1675 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); |
| 1649 | 1676 |
| 1650 // The meta map object may not be copied yet. | |
| 1651 Address old_addr = obj->address(); | 1677 Address old_addr = obj->address(); |
| 1652 | 1678 |
| 1653 if (new_addr != old_addr) { | 1679 if (new_addr != old_addr) { |
| 1654 memmove(new_addr, old_addr, Map::kSize); // copy contents | 1680 memmove(new_addr, old_addr, Map::kSize); // copy contents |
| 1655 } | 1681 } |
| 1656 | 1682 |
| 1657 #ifdef DEBUG | 1683 #ifdef DEBUG |
| 1658 if (FLAG_gc_verbose) { | 1684 if (FLAG_gc_verbose) { |
| 1659 PrintF("relocate %p -> %p\n", old_addr, new_addr); | 1685 PrintF("relocate %p -> %p\n", old_addr, new_addr); |
| 1660 } | 1686 } |
| 1661 #endif | 1687 #endif |
| 1662 | 1688 |
| 1663 return Map::kSize; | 1689 return Map::kSize; |
| 1664 } | 1690 } |
| 1665 | 1691 |
| 1666 | 1692 |
| 1667 static inline int RelocateOldObject(HeapObject* obj, | 1693 static inline int RestoreMap(HeapObject* obj, |
| 1668 OldSpace* space, | 1694 PagedSpace* space, |
| 1669 Address new_addr, | 1695 Address new_addr, |
| 1670 Address map_addr) { | 1696 Address map_addr) { |
| 1671 // recover map pointer | 1697 // This must be a non-map object, and the function relies on the |
| 1672 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); | 1698 // assumption that the Map space is compacted before the other paged |
| 1699 // spaces (see RelocateObjects). |
| 1673 | 1700 |
| 1674 // This is a non-map object, it relies on the assumption that the Map space | 1701 // Reset map pointer. |
| 1675 // is compacted before the Old space (see RelocateObjects). | 1702 obj->set_map(Map::cast(HeapObject::FromAddress(map_addr))); |
| 1703 |
| 1676 int obj_size = obj->Size(); | 1704 int obj_size = obj->Size(); |
| 1677 ASSERT_OBJECT_SIZE(obj_size); | 1705 ASSERT_OBJECT_SIZE(obj_size); |
| 1678 | 1706 |
| 1679 ASSERT(space->MCSpaceOffsetForAddress(new_addr) <= | 1707 ASSERT(space->MCSpaceOffsetForAddress(new_addr) <= |
| 1680 space->MCSpaceOffsetForAddress(obj->address())); | 1708 space->MCSpaceOffsetForAddress(obj->address())); |
| 1681 | 1709 |
| 1682 space->MCAdjustRelocationEnd(new_addr, obj_size); | |
| 1683 | |
| 1684 #ifdef DEBUG | 1710 #ifdef DEBUG |
| 1685 if (FLAG_gc_verbose) { | 1711 if (FLAG_gc_verbose) { |
| 1686 PrintF("relocate %p -> %p\n", obj->address(), new_addr); | 1712 PrintF("relocate %p -> %p\n", obj->address(), new_addr); |
| 1687 } | 1713 } |
| 1688 #endif | 1714 #endif |
| 1689 | 1715 |
| 1690 return obj_size; | 1716 return obj_size; |
| 1691 } | 1717 } |
| 1692 | 1718 |
| 1693 | 1719 |
| 1694 int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj, | 1720 int MarkCompactCollector::RelocateOldNonCodeObject(HeapObject* obj, |
| 1695 OldSpace* space) { | 1721 PagedSpace* space) { |
| 1696 // decode map pointer (forwarded address) | 1722 // Recover map pointer. |
| 1697 MapWord encoding = obj->map_word(); | 1723 MapWord encoding = obj->map_word(); |
| 1698 Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); | 1724 Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); |
| 1699 ASSERT(Heap::map_space()->Contains(map_addr)); | 1725 ASSERT(Heap::map_space()->Contains(map_addr)); |
| 1700 | 1726 |
| 1701 // Get forwarding address before resetting map pointer | 1727 // Get forwarding address before resetting map pointer. |
| 1702 Address new_addr = GetForwardingAddressInOldSpace(obj); | 1728 Address new_addr = GetForwardingAddressInOldSpace(obj); |
| 1703 | 1729 |
| 1704 int obj_size = RelocateOldObject(obj, space, new_addr, map_addr); | 1730 // Reset the map pointer. |
| 1731 int obj_size = RestoreMap(obj, space, new_addr, map_addr); |
| 1705 | 1732 |
| 1706 Address old_addr = obj->address(); | 1733 Address old_addr = obj->address(); |
| 1707 | 1734 |
| 1708 if (new_addr != old_addr) { | 1735 if (new_addr != old_addr) { |
| 1709 memmove(new_addr, old_addr, obj_size); // copy contents | 1736 memmove(new_addr, old_addr, obj_size); // Copy contents |
| 1710 } | 1737 } |
| 1711 | 1738 |
| 1712 ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); | 1739 ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); |
| 1713 | 1740 |
| 1714 return obj_size; | 1741 return obj_size; |
| 1715 } | 1742 } |
| 1716 | 1743 |
| 1717 | 1744 |
| 1718 int MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) { | 1745 int MarkCompactCollector::RelocateOldPointerObject(HeapObject* obj) { |
| 1719 return RelocateOldNonCodeObject(obj, Heap::old_pointer_space()); | 1746 return RelocateOldNonCodeObject(obj, Heap::old_pointer_space()); |
| 1720 } | 1747 } |
| 1721 | 1748 |
| 1722 | 1749 |
| 1723 int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) { | 1750 int MarkCompactCollector::RelocateOldDataObject(HeapObject* obj) { |
| 1724 return RelocateOldNonCodeObject(obj, Heap::old_data_space()); | 1751 return RelocateOldNonCodeObject(obj, Heap::old_data_space()); |
| 1725 } | 1752 } |
| 1726 | 1753 |
| 1727 | 1754 |
| 1755 int MarkCompactCollector::RelocateCellObject(HeapObject* obj) { |
| 1756 return RelocateOldNonCodeObject(obj, Heap::cell_space()); |
| 1757 } |
| 1758 |
| 1759 |
| 1728 int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) { | 1760 int MarkCompactCollector::RelocateCodeObject(HeapObject* obj) { |
| 1729 // decode map pointer (forwarded address) | 1761 // Recover map pointer. |
| 1730 MapWord encoding = obj->map_word(); | 1762 MapWord encoding = obj->map_word(); |
| 1731 Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); | 1763 Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); |
| 1732 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); | 1764 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); |
| 1733 | 1765 |
| 1734 // Get forwarding address before resetting map pointer | 1766 // Get forwarding address before resetting map pointer |
| 1735 Address new_addr = GetForwardingAddressInOldSpace(obj); | 1767 Address new_addr = GetForwardingAddressInOldSpace(obj); |
| 1736 | 1768 |
| 1737 int obj_size = RelocateOldObject(obj, Heap::code_space(), new_addr, map_addr); | 1769 // Reset the map pointer. |
| 1770 int obj_size = RestoreMap(obj, Heap::code_space(), new_addr, map_addr); |
| 1738 | 1771 |
| 1739 // convert inline cache target to address using old address | 1772 // Convert inline cache target to address using old address. |
| 1740 if (obj->IsCode()) { | 1773 if (obj->IsCode()) { |
| 1741 // convert target to address first related to old_address | |
| 1742 Code::cast(obj)->ConvertICTargetsFromObjectToAddress(); | 1774 Code::cast(obj)->ConvertICTargetsFromObjectToAddress(); |
| 1743 } | 1775 } |
| 1744 | 1776 |
| 1745 Address old_addr = obj->address(); | 1777 Address old_addr = obj->address(); |
| 1746 | 1778 |
| 1747 if (new_addr != old_addr) { | 1779 if (new_addr != old_addr) { |
| 1748 memmove(new_addr, old_addr, obj_size); // copy contents | 1780 memmove(new_addr, old_addr, obj_size); // Copy contents. |
| 1749 } | 1781 } |
| 1750 | 1782 |
| 1751 HeapObject* copied_to = HeapObject::FromAddress(new_addr); | 1783 HeapObject* copied_to = HeapObject::FromAddress(new_addr); |
| 1752 if (copied_to->IsCode()) { | 1784 if (copied_to->IsCode()) { |
| 1753 // may also update inline cache target. | 1785 // May also update inline cache target. |
| 1754 Code::cast(copied_to)->Relocate(new_addr - old_addr); | 1786 Code::cast(copied_to)->Relocate(new_addr - old_addr); |
| 1755 // Notify the logger that compiled code has moved. | 1787 // Notify the logger that compiled code has moved. |
| 1756 LOG(CodeMoveEvent(old_addr, new_addr)); | 1788 LOG(CodeMoveEvent(old_addr, new_addr)); |
| 1757 } | 1789 } |
| 1758 | 1790 |
| 1759 return obj_size; | 1791 return obj_size; |
| 1760 } | 1792 } |
| 1761 | 1793 |
| 1762 | 1794 |
| 1763 int MarkCompactCollector::RelocateNewObject(HeapObject* obj) { | 1795 int MarkCompactCollector::RelocateNewObject(HeapObject* obj) { |
| 1764 int obj_size = obj->Size(); | 1796 int obj_size = obj->Size(); |
| 1765 | 1797 |
| 1766 // Get forwarding address | 1798 // Get forwarding address |
| 1767 Address old_addr = obj->address(); | 1799 Address old_addr = obj->address(); |
| 1768 int offset = Heap::new_space()->ToSpaceOffsetForAddress(old_addr); | 1800 int offset = Heap::new_space()->ToSpaceOffsetForAddress(old_addr); |
| 1769 | 1801 |
| 1770 Address new_addr = | 1802 Address new_addr = |
| 1771 Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset); | 1803 Memory::Address_at(Heap::new_space()->FromSpaceLow() + offset); |
| 1772 | 1804 |
| 1805 #ifdef DEBUG |
| 1773 if (Heap::new_space()->FromSpaceContains(new_addr)) { | 1806 if (Heap::new_space()->FromSpaceContains(new_addr)) { |
| 1774 ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= | 1807 ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= |
| 1775 Heap::new_space()->ToSpaceOffsetForAddress(old_addr)); | 1808 Heap::new_space()->ToSpaceOffsetForAddress(old_addr)); |
| 1776 } else { | 1809 } else { |
| 1777 OldSpace* target_space = Heap::TargetSpace(obj); | 1810 ASSERT(Heap::TargetSpace(obj) == Heap::old_pointer_space() || |
| 1778 ASSERT(target_space == Heap::old_pointer_space() || | 1811 Heap::TargetSpace(obj) == Heap::old_data_space()); |
| 1779 target_space == Heap::old_data_space()); | |
| 1780 target_space->MCAdjustRelocationEnd(new_addr, obj_size); | |
| 1781 } | 1812 } |
| 1813 #endif |
| 1782 | 1814 |
| 1783 // New and old addresses cannot overlap. | 1815 // New and old addresses cannot overlap. |
| 1784 memcpy(reinterpret_cast<void*>(new_addr), | 1816 memcpy(reinterpret_cast<void*>(new_addr), |
| 1785 reinterpret_cast<void*>(old_addr), | 1817 reinterpret_cast<void*>(old_addr), |
| 1786 obj_size); | 1818 obj_size); |
| 1787 | 1819 |
| 1788 #ifdef DEBUG | 1820 #ifdef DEBUG |
| 1789 if (FLAG_gc_verbose) { | 1821 if (FLAG_gc_verbose) { |
| 1790 PrintF("relocate %p -> %p\n", old_addr, new_addr); | 1822 PrintF("relocate %p -> %p\n", old_addr, new_addr); |
| 1791 } | 1823 } |
| 1792 #endif | 1824 #endif |
| 1793 | 1825 |
| 1794 return obj_size; | 1826 return obj_size; |
| 1795 } | 1827 } |
| 1796 | 1828 |
| 1797 | 1829 |
| 1798 // ------------------------------------------------------------------------- | 1830 // ------------------------------------------------------------------------- |
| 1799 // Phase 5: rebuild remembered sets | 1831 // Phase 5: rebuild remembered sets |
| 1800 | 1832 |
| 1801 void MarkCompactCollector::RebuildRSets() { | 1833 void MarkCompactCollector::RebuildRSets() { |
| 1802 #ifdef DEBUG | 1834 #ifdef DEBUG |
| 1803 ASSERT(state_ == RELOCATE_OBJECTS); | 1835 ASSERT(state_ == RELOCATE_OBJECTS); |
| 1804 state_ = REBUILD_RSETS; | 1836 state_ = REBUILD_RSETS; |
| 1805 #endif | 1837 #endif |
| 1806 Heap::RebuildRSets(); | 1838 Heap::RebuildRSets(); |
| 1807 } | 1839 } |
| 1808 | 1840 |
| 1809 } } // namespace v8::internal | 1841 } } // namespace v8::internal |
| OLD | NEW |