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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 int MarkCompactCollector::previous_marked_count_ = 0; | 46 int MarkCompactCollector::previous_marked_count_ = 0; |
47 GCTracer* MarkCompactCollector::tracer_ = NULL; | 47 GCTracer* MarkCompactCollector::tracer_ = NULL; |
48 | 48 |
49 | 49 |
50 #ifdef DEBUG | 50 #ifdef DEBUG |
51 MarkCompactCollector::CollectorState MarkCompactCollector::state_ = IDLE; | 51 MarkCompactCollector::CollectorState MarkCompactCollector::state_ = IDLE; |
52 | 52 |
53 // Counters used for debugging the marking phase of mark-compact or mark-sweep | 53 // Counters used for debugging the marking phase of mark-compact or mark-sweep |
54 // collection. | 54 // collection. |
55 int MarkCompactCollector::live_bytes_ = 0; | 55 int MarkCompactCollector::live_bytes_ = 0; |
56 int MarkCompactCollector::live_young_objects_size_ = 0; | 56 int MarkCompactCollector::live_young_objects_ = 0; |
57 int MarkCompactCollector::live_old_data_objects_size_ = 0; | 57 int MarkCompactCollector::live_old_data_objects_ = 0; |
58 int MarkCompactCollector::live_old_pointer_objects_size_ = 0; | 58 int MarkCompactCollector::live_old_pointer_objects_ = 0; |
59 int MarkCompactCollector::live_code_objects_size_ = 0; | 59 int MarkCompactCollector::live_code_objects_ = 0; |
60 int MarkCompactCollector::live_map_objects_size_ = 0; | 60 int MarkCompactCollector::live_map_objects_ = 0; |
61 int MarkCompactCollector::live_cell_objects_size_ = 0; | 61 int MarkCompactCollector::live_cell_objects_ = 0; |
62 int MarkCompactCollector::live_lo_objects_size_ = 0; | 62 int MarkCompactCollector::live_lo_objects_ = 0; |
63 #endif | 63 #endif |
64 | 64 |
65 void MarkCompactCollector::CollectGarbage() { | 65 void MarkCompactCollector::CollectGarbage() { |
66 // Make sure that Prepare() has been called. The individual steps below will | 66 // Make sure that Prepare() has been called. The individual steps below will |
67 // update the state as they proceed. | 67 // update the state as they proceed. |
68 ASSERT(state_ == PREPARE_GC); | 68 ASSERT(state_ == PREPARE_GC); |
69 | 69 |
70 // Prepare has selected whether to compact the old generation or not. | 70 // Prepare has selected whether to compact the old generation or not. |
71 // Tell the tracer. | 71 // Tell the tracer. |
72 if (IsCompacting()) tracer_->set_is_compacting(); | 72 if (IsCompacting()) tracer_->set_is_compacting(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 #endif | 129 #endif |
130 | 130 |
131 PagedSpaces spaces; | 131 PagedSpaces spaces; |
132 for (PagedSpace* space = spaces.next(); | 132 for (PagedSpace* space = spaces.next(); |
133 space != NULL; space = spaces.next()) { | 133 space != NULL; space = spaces.next()) { |
134 space->PrepareForMarkCompact(compacting_collection_); | 134 space->PrepareForMarkCompact(compacting_collection_); |
135 } | 135 } |
136 | 136 |
137 #ifdef DEBUG | 137 #ifdef DEBUG |
138 live_bytes_ = 0; | 138 live_bytes_ = 0; |
139 live_young_objects_size_ = 0; | 139 live_young_objects_ = 0; |
140 live_old_pointer_objects_size_ = 0; | 140 live_old_pointer_objects_ = 0; |
141 live_old_data_objects_size_ = 0; | 141 live_old_data_objects_ = 0; |
142 live_code_objects_size_ = 0; | 142 live_code_objects_ = 0; |
143 live_map_objects_size_ = 0; | 143 live_map_objects_ = 0; |
144 live_cell_objects_size_ = 0; | 144 live_cell_objects_ = 0; |
145 live_lo_objects_size_ = 0; | 145 live_lo_objects_ = 0; |
146 #endif | 146 #endif |
147 } | 147 } |
148 | 148 |
149 | 149 |
150 void MarkCompactCollector::Finish() { | 150 void MarkCompactCollector::Finish() { |
151 #ifdef DEBUG | 151 #ifdef DEBUG |
152 ASSERT(state_ == SWEEP_SPACES || state_ == REBUILD_RSETS); | 152 ASSERT(state_ == SWEEP_SPACES || state_ == REBUILD_RSETS); |
153 state_ = IDLE; | 153 state_ = IDLE; |
154 #endif | 154 #endif |
155 // The stub cache is not traversed during GC; clear the cache to | 155 // The stub cache is not traversed during GC; clear the cache to |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 MapWord map_word = obj->map_word(); | 735 MapWord map_word = obj->map_word(); |
736 map_word.ClearMark(); | 736 map_word.ClearMark(); |
737 return obj->SizeFromMap(map_word.ToMap()); | 737 return obj->SizeFromMap(map_word.ToMap()); |
738 } | 738 } |
739 | 739 |
740 | 740 |
741 #ifdef DEBUG | 741 #ifdef DEBUG |
742 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { | 742 void MarkCompactCollector::UpdateLiveObjectCount(HeapObject* obj) { |
743 live_bytes_ += obj->Size(); | 743 live_bytes_ += obj->Size(); |
744 if (Heap::new_space()->Contains(obj)) { | 744 if (Heap::new_space()->Contains(obj)) { |
745 live_young_objects_size_ += obj->Size(); | 745 live_young_objects_++; |
746 } else if (Heap::map_space()->Contains(obj)) { | 746 } else if (Heap::map_space()->Contains(obj)) { |
747 ASSERT(obj->IsMap()); | 747 ASSERT(obj->IsMap()); |
748 live_map_objects_size_ += obj->Size(); | 748 live_map_objects_++; |
749 } else if (Heap::cell_space()->Contains(obj)) { | 749 } else if (Heap::cell_space()->Contains(obj)) { |
750 ASSERT(obj->IsJSGlobalPropertyCell()); | 750 ASSERT(obj->IsJSGlobalPropertyCell()); |
751 live_cell_objects_size_ += obj->Size(); | 751 live_cell_objects_++; |
752 } else if (Heap::old_pointer_space()->Contains(obj)) { | 752 } else if (Heap::old_pointer_space()->Contains(obj)) { |
753 live_old_pointer_objects_size_ += obj->Size(); | 753 live_old_pointer_objects_++; |
754 } else if (Heap::old_data_space()->Contains(obj)) { | 754 } else if (Heap::old_data_space()->Contains(obj)) { |
755 live_old_data_objects_size_ += obj->Size(); | 755 live_old_data_objects_++; |
756 } else if (Heap::code_space()->Contains(obj)) { | 756 } else if (Heap::code_space()->Contains(obj)) { |
757 live_code_objects_size_ += obj->Size(); | 757 live_code_objects_++; |
758 } else if (Heap::lo_space()->Contains(obj)) { | 758 } else if (Heap::lo_space()->Contains(obj)) { |
759 live_lo_objects_size_ += obj->Size(); | 759 live_lo_objects_++; |
760 } else { | 760 } else { |
761 UNREACHABLE(); | 761 UNREACHABLE(); |
762 } | 762 } |
763 } | 763 } |
764 #endif // DEBUG | 764 #endif // DEBUG |
765 | 765 |
766 | 766 |
767 void MarkCompactCollector::SweepLargeObjectSpace() { | 767 void MarkCompactCollector::SweepLargeObjectSpace() { |
768 #ifdef DEBUG | 768 #ifdef DEBUG |
769 ASSERT(state_ == MARK_LIVE_OBJECTS); | 769 ASSERT(state_ == MARK_LIVE_OBJECTS); |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1061 EncodeForwardingAddressesInRange<Alloc, | 1061 EncodeForwardingAddressesInRange<Alloc, |
1062 EncodeForwardingAddressInPagedSpace, | 1062 EncodeForwardingAddressInPagedSpace, |
1063 ProcessNonLive>( | 1063 ProcessNonLive>( |
1064 p->ObjectAreaStart(), | 1064 p->ObjectAreaStart(), |
1065 p->AllocationTop(), | 1065 p->AllocationTop(), |
1066 &offset); | 1066 &offset); |
1067 } | 1067 } |
1068 } | 1068 } |
1069 | 1069 |
1070 | 1070 |
1071 // We scavange new space simultaneously with sweeping. This is done in two | 1071 static void SweepSpace(NewSpace* space) { |
1072 // passes. | |
1073 // The first pass migrates all alive objects from one semispace to another or | |
1074 // promotes them to old space. Forwading address is written directly into | |
1075 // first word of object without any encoding. If object is dead we are writing | |
1076 // NULL as a forwarding address. | |
1077 // The second pass updates pointers to new space in all spaces. It is possible | |
1078 // to encounter pointers to dead objects during traversal of remembered set for | |
1079 // map space because remembered set bits corresponding to dead maps are cleared | |
1080 // later during map space sweeping. | |
1081 static void MigrateObject(Address dst, Address src, int size) { | |
1082 Heap::CopyBlock(reinterpret_cast<Object**>(dst), | |
1083 reinterpret_cast<Object**>(src), | |
1084 size); | |
1085 | |
1086 Memory::Address_at(src) = dst; | |
1087 } | |
1088 | |
1089 | |
1090 // Visitor for updating pointers from live objects in old spaces to new space. | |
1091 // It does not expect to encounter pointers to dead objects. | |
1092 class PointersToNewGenUpdatingVisitor: public ObjectVisitor { | |
1093 public: | |
1094 void VisitPointer(Object** p) { | |
1095 UpdatePointer(p); | |
1096 } | |
1097 | |
1098 void VisitPointers(Object** start, Object** end) { | |
1099 for (Object** p = start; p < end; p++) UpdatePointer(p); | |
1100 } | |
1101 | |
1102 void VisitCodeTarget(RelocInfo* rinfo) { | |
1103 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); | |
1104 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | |
1105 VisitPointer(&target); | |
1106 rinfo->set_target_address(Code::cast(target)->instruction_start()); | |
1107 } | |
1108 | |
1109 void VisitDebugTarget(RelocInfo* rinfo) { | |
1110 ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) && | |
1111 rinfo->IsPatchedReturnSequence()); | |
1112 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); | |
1113 VisitPointer(&target); | |
1114 rinfo->set_call_address(Code::cast(target)->instruction_start()); | |
1115 } | |
1116 | |
1117 private: | |
1118 void UpdatePointer(Object** p) { | |
1119 if (!(*p)->IsHeapObject()) return; | |
1120 | |
1121 HeapObject* obj = HeapObject::cast(*p); | |
1122 Address old_addr = obj->address(); | |
1123 | |
1124 if (Heap::new_space()->Contains(obj)) { | |
1125 ASSERT(Heap::InFromSpace(*p)); | |
1126 *p = HeapObject::FromAddress(Memory::Address_at(old_addr)); | |
1127 } | |
1128 } | |
1129 }; | |
1130 | |
1131 // Visitor for updating pointers from live objects in old spaces to new space. | |
1132 // It can encounter pointers to dead objects in new space when traversing map | |
1133 // space (see comment for MigrateObject). | |
1134 static void UpdatePointerToNewGen(HeapObject** p) { | |
1135 if (!(*p)->IsHeapObject()) return; | |
1136 | |
1137 Address old_addr = (*p)->address(); | |
1138 ASSERT(Heap::InFromSpace(*p)); | |
1139 | |
1140 Address new_addr = Memory::Address_at(old_addr); | |
1141 | |
1142 // Object pointed by *p is dead. Update is not required. | |
1143 if (new_addr == NULL) return; | |
1144 | |
1145 *p = HeapObject::FromAddress(new_addr); | |
1146 } | |
1147 | |
1148 | |
1149 static String* UpdateNewSpaceReferenceInExternalStringTableEntry(Object **p) { | |
1150 Address old_addr = HeapObject::cast(*p)->address(); | |
1151 Address new_addr = Memory::Address_at(old_addr); | |
1152 return String::cast(HeapObject::FromAddress(new_addr)); | |
1153 } | |
1154 | |
1155 | |
1156 static bool TryPromoteObject(HeapObject* object, int object_size) { | |
1157 Object* result; | |
1158 | |
1159 if (object_size > Heap::MaxObjectSizeInPagedSpace()) { | |
1160 result = Heap::lo_space()->AllocateRawFixedArray(object_size); | |
1161 if (!result->IsFailure()) { | |
1162 HeapObject* target = HeapObject::cast(result); | |
1163 MigrateObject(target->address(), object->address(), object_size); | |
1164 Heap::UpdateRSet(target); | |
1165 return true; | |
1166 } | |
1167 } else { | |
1168 OldSpace* target_space = Heap::TargetSpace(object); | |
1169 | |
1170 ASSERT(target_space == Heap::old_pointer_space() || | |
1171 target_space == Heap::old_data_space()); | |
1172 result = target_space->AllocateRaw(object_size); | |
1173 if (!result->IsFailure()) { | |
1174 HeapObject* target = HeapObject::cast(result); | |
1175 MigrateObject(target->address(), object->address(), object_size); | |
1176 if (target_space == Heap::old_pointer_space()) { | |
1177 Heap::UpdateRSet(target); | |
1178 } | |
1179 return true; | |
1180 } | |
1181 } | |
1182 | |
1183 return false; | |
1184 } | |
1185 | |
1186 | |
1187 static void SweepNewSpace(NewSpace* space) { | |
1188 Heap::CheckNewSpaceExpansionCriteria(); | |
1189 | |
1190 Address from_bottom = space->bottom(); | |
1191 Address from_top = space->top(); | |
1192 | |
1193 // Flip the semispaces. After flipping, to space is empty, from space has | |
1194 // live objects. | |
1195 space->Flip(); | |
1196 space->ResetAllocationInfo(); | |
1197 | |
1198 int size = 0; | |
1199 int survivors_size = 0; | |
1200 | |
1201 // First pass: traverse all objects in inactive semispace, remove marks, | |
1202 // migrate live objects and write forwarding addresses. | |
1203 for (Address current = from_bottom; current < from_top; current += size) { | |
1204 HeapObject* object = HeapObject::FromAddress(current); | |
1205 | |
1206 if (object->IsMarked()) { | |
1207 object->ClearMark(); | |
1208 MarkCompactCollector::tracer()->decrement_marked_count(); | |
1209 | |
1210 size = object->Size(); | |
1211 survivors_size += size; | |
1212 | |
1213 if (Heap::ShouldBePromoted(current, size) && | |
1214 TryPromoteObject(object, size)) { | |
1215 continue; | |
1216 } | |
1217 | |
1218 // Promotion either failed or not required. | |
1219 // Copy the content of the object. | |
1220 Object* target = space->AllocateRaw(size); | |
1221 | |
1222 // Allocation cannot fail at this point: semispaces are of equal size. | |
1223 ASSERT(!target->IsFailure()); | |
1224 | |
1225 MigrateObject(HeapObject::cast(target)->address(), current, size); | |
1226 } else { | |
1227 size = object->Size(); | |
1228 Memory::Address_at(current) = NULL; | |
1229 } | |
1230 } | |
1231 | |
1232 // Second pass: find pointers to new space and update them. | |
1233 PointersToNewGenUpdatingVisitor updating_visitor; | |
1234 | |
1235 // Update pointers in to space. | |
1236 HeapObject* object; | 1072 HeapObject* object; |
1237 for (Address current = space->bottom(); | 1073 for (Address current = space->bottom(); |
1238 current < space->top(); | 1074 current < space->top(); |
1239 current += object->Size()) { | 1075 current += object->Size()) { |
1240 object = HeapObject::FromAddress(current); | 1076 object = HeapObject::FromAddress(current); |
1241 | 1077 if (object->IsMarked()) { |
1242 object->IterateBody(object->map()->instance_type(), | 1078 object->ClearMark(); |
1243 object->Size(), | 1079 MarkCompactCollector::tracer()->decrement_marked_count(); |
1244 &updating_visitor); | 1080 } else { |
| 1081 // We give non-live objects a map that will correctly give their size, |
| 1082 // since their existing map might not be live after the collection. |
| 1083 int size = object->Size(); |
| 1084 if (size >= ByteArray::kHeaderSize) { |
| 1085 object->set_map(Heap::raw_unchecked_byte_array_map()); |
| 1086 ByteArray::cast(object)->set_length(ByteArray::LengthFor(size)); |
| 1087 } else { |
| 1088 ASSERT(size == kPointerSize); |
| 1089 object->set_map(Heap::raw_unchecked_one_pointer_filler_map()); |
| 1090 } |
| 1091 ASSERT(object->Size() == size); |
| 1092 } |
| 1093 // The object is now unmarked for the call to Size() at the top of the |
| 1094 // loop. |
1245 } | 1095 } |
1246 | |
1247 // Update roots. | |
1248 Heap::IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE); | |
1249 | |
1250 // Update pointers in old spaces. | |
1251 Heap::IterateRSet(Heap::old_pointer_space(), &UpdatePointerToNewGen); | |
1252 Heap::IterateRSet(Heap::map_space(), &UpdatePointerToNewGen); | |
1253 Heap::lo_space()->IterateRSet(&UpdatePointerToNewGen); | |
1254 | |
1255 // Update pointers from cells. | |
1256 HeapObjectIterator cell_iterator(Heap::cell_space()); | |
1257 for (HeapObject* cell = cell_iterator.next(); | |
1258 cell != NULL; | |
1259 cell = cell_iterator.next()) { | |
1260 if (cell->IsJSGlobalPropertyCell()) { | |
1261 Address value_address = | |
1262 reinterpret_cast<Address>(cell) + | |
1263 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); | |
1264 updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address)); | |
1265 } | |
1266 } | |
1267 | |
1268 // Update pointers from external string table. | |
1269 Heap::UpdateNewSpaceReferencesInExternalStringTable( | |
1270 &UpdateNewSpaceReferenceInExternalStringTableEntry); | |
1271 | |
1272 // All pointers were updated. Update auxiliary allocation info. | |
1273 Heap::IncrementYoungSurvivorsCounter(survivors_size); | |
1274 space->set_age_mark(space->top()); | |
1275 } | 1096 } |
1276 | 1097 |
1277 | 1098 |
1278 static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) { | 1099 static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) { |
1279 PageIterator it(space, PageIterator::PAGES_IN_USE); | 1100 PageIterator it(space, PageIterator::PAGES_IN_USE); |
1280 while (it.has_next()) { | 1101 while (it.has_next()) { |
1281 Page* p = it.next(); | 1102 Page* p = it.next(); |
1282 | 1103 |
1283 bool is_previous_alive = true; | 1104 bool is_previous_alive = true; |
1284 Address free_start = NULL; | 1105 Address free_start = NULL; |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 Map* map = NextMap(&map_to_evacuate_it_, NULL, true); | 1375 Map* map = NextMap(&map_to_evacuate_it_, NULL, true); |
1555 ASSERT(map != NULL); | 1376 ASSERT(map != NULL); |
1556 ASSERT(map->IsMap()); | 1377 ASSERT(map->IsMap()); |
1557 return map; | 1378 return map; |
1558 } | 1379 } |
1559 | 1380 |
1560 static void EvacuateMap(Map* vacant_map, Map* map_to_evacuate) { | 1381 static void EvacuateMap(Map* vacant_map, Map* map_to_evacuate) { |
1561 ASSERT(FreeListNode::IsFreeListNode(vacant_map)); | 1382 ASSERT(FreeListNode::IsFreeListNode(vacant_map)); |
1562 ASSERT(map_to_evacuate->IsMap()); | 1383 ASSERT(map_to_evacuate->IsMap()); |
1563 | 1384 |
1564 ASSERT(Map::kSize % 4 == 0); | 1385 memcpy( |
1565 | 1386 reinterpret_cast<void*>(vacant_map->address()), |
1566 Heap::CopyBlock(reinterpret_cast<Object**>(vacant_map->address()), | 1387 reinterpret_cast<void*>(map_to_evacuate->address()), |
1567 reinterpret_cast<Object**>(map_to_evacuate->address()), | 1388 Map::kSize); |
1568 Map::kSize); | |
1569 | |
1570 ASSERT(vacant_map->IsMap()); // Due to memcpy above. | 1389 ASSERT(vacant_map->IsMap()); // Due to memcpy above. |
1571 | 1390 |
1572 MapWord forwarding_map_word = MapWord::FromMap(vacant_map); | 1391 MapWord forwarding_map_word = MapWord::FromMap(vacant_map); |
1573 forwarding_map_word.SetOverflow(); | 1392 forwarding_map_word.SetOverflow(); |
1574 map_to_evacuate->set_map_word(forwarding_map_word); | 1393 map_to_evacuate->set_map_word(forwarding_map_word); |
1575 | 1394 |
1576 ASSERT(map_to_evacuate->map_word().IsOverflowed()); | 1395 ASSERT(map_to_evacuate->map_word().IsOverflowed()); |
1577 ASSERT(GetForwardedMap(map_to_evacuate->map_word()) == vacant_map); | 1396 ASSERT(GetForwardedMap(map_to_evacuate->map_word()) == vacant_map); |
1578 } | 1397 } |
1579 | 1398 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1639 ASSERT(!IsCompacting()); | 1458 ASSERT(!IsCompacting()); |
1640 // Noncompacting collections simply sweep the spaces to clear the mark | 1459 // Noncompacting collections simply sweep the spaces to clear the mark |
1641 // bits and free the nonlive blocks (for old and map spaces). We sweep | 1460 // bits and free the nonlive blocks (for old and map spaces). We sweep |
1642 // the map space last because freeing non-live maps overwrites them and | 1461 // the map space last because freeing non-live maps overwrites them and |
1643 // the other spaces rely on possibly non-live maps to get the sizes for | 1462 // the other spaces rely on possibly non-live maps to get the sizes for |
1644 // non-live objects. | 1463 // non-live objects. |
1645 SweepSpace(Heap::old_pointer_space(), &DeallocateOldPointerBlock); | 1464 SweepSpace(Heap::old_pointer_space(), &DeallocateOldPointerBlock); |
1646 SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock); | 1465 SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock); |
1647 SweepSpace(Heap::code_space(), &DeallocateCodeBlock); | 1466 SweepSpace(Heap::code_space(), &DeallocateCodeBlock); |
1648 SweepSpace(Heap::cell_space(), &DeallocateCellBlock); | 1467 SweepSpace(Heap::cell_space(), &DeallocateCellBlock); |
1649 SweepNewSpace(Heap::new_space()); | 1468 SweepSpace(Heap::new_space()); |
1650 SweepSpace(Heap::map_space(), &DeallocateMapBlock); | 1469 SweepSpace(Heap::map_space(), &DeallocateMapBlock); |
1651 int live_maps_size = Heap::map_space()->Size(); | 1470 int live_maps = Heap::map_space()->Size() / Map::kSize; |
1652 int live_maps = live_maps_size / Map::kSize; | 1471 ASSERT(live_map_objects_ == live_maps); |
1653 ASSERT(live_map_objects_size_ == live_maps_size); | |
1654 | 1472 |
1655 if (Heap::map_space()->NeedsCompaction(live_maps)) { | 1473 if (Heap::map_space()->NeedsCompaction(live_maps)) { |
1656 MapCompact map_compact(live_maps); | 1474 MapCompact map_compact(live_maps); |
1657 | 1475 |
1658 map_compact.CompactMaps(); | 1476 map_compact.CompactMaps(); |
1659 map_compact.UpdateMapPointersInRoots(); | 1477 map_compact.UpdateMapPointersInRoots(); |
1660 | 1478 |
1661 map_compact.FinishMapSpace(); | 1479 map_compact.FinishMapSpace(); |
1662 PagedSpaces spaces; | 1480 PagedSpaces spaces; |
1663 for (PagedSpace* space = spaces.next(); | 1481 for (PagedSpace* space = spaces.next(); |
(...skipping 11 matching lines...) Expand all Loading... |
1675 | 1493 |
1676 // Iterate the live objects in a range of addresses (eg, a page or a | 1494 // Iterate the live objects in a range of addresses (eg, a page or a |
1677 // semispace). The live regions of the range have been linked into a list. | 1495 // semispace). The live regions of the range have been linked into a list. |
1678 // The first live region is [first_live_start, first_live_end), and the last | 1496 // The first live region is [first_live_start, first_live_end), and the last |
1679 // address in the range is top. The callback function is used to get the | 1497 // address in the range is top. The callback function is used to get the |
1680 // size of each live object. | 1498 // size of each live object. |
1681 int MarkCompactCollector::IterateLiveObjectsInRange( | 1499 int MarkCompactCollector::IterateLiveObjectsInRange( |
1682 Address start, | 1500 Address start, |
1683 Address end, | 1501 Address end, |
1684 HeapObjectCallback size_func) { | 1502 HeapObjectCallback size_func) { |
1685 int live_objects_size = 0; | 1503 int live_objects = 0; |
1686 Address current = start; | 1504 Address current = start; |
1687 while (current < end) { | 1505 while (current < end) { |
1688 uint32_t encoded_map = Memory::uint32_at(current); | 1506 uint32_t encoded_map = Memory::uint32_at(current); |
1689 if (encoded_map == kSingleFreeEncoding) { | 1507 if (encoded_map == kSingleFreeEncoding) { |
1690 current += kPointerSize; | 1508 current += kPointerSize; |
1691 } else if (encoded_map == kMultiFreeEncoding) { | 1509 } else if (encoded_map == kMultiFreeEncoding) { |
1692 current += Memory::int_at(current + kIntSize); | 1510 current += Memory::int_at(current + kIntSize); |
1693 } else { | 1511 } else { |
1694 int size = size_func(HeapObject::FromAddress(current)); | 1512 live_objects++; |
1695 current += size; | 1513 current += size_func(HeapObject::FromAddress(current)); |
1696 live_objects_size += size; | |
1697 } | 1514 } |
1698 } | 1515 } |
1699 return live_objects_size; | 1516 return live_objects; |
1700 } | 1517 } |
1701 | 1518 |
1702 | 1519 |
1703 int MarkCompactCollector::IterateLiveObjects(NewSpace* space, | 1520 int MarkCompactCollector::IterateLiveObjects(NewSpace* space, |
1704 HeapObjectCallback size_f) { | 1521 HeapObjectCallback size_f) { |
1705 ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS); | 1522 ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS); |
1706 return IterateLiveObjectsInRange(space->bottom(), space->top(), size_f); | 1523 return IterateLiveObjectsInRange(space->bottom(), space->top(), size_f); |
1707 } | 1524 } |
1708 | 1525 |
1709 | 1526 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1815 | 1632 |
1816 void MarkCompactCollector::UpdatePointers() { | 1633 void MarkCompactCollector::UpdatePointers() { |
1817 #ifdef DEBUG | 1634 #ifdef DEBUG |
1818 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); | 1635 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); |
1819 state_ = UPDATE_POINTERS; | 1636 state_ = UPDATE_POINTERS; |
1820 #endif | 1637 #endif |
1821 UpdatingVisitor updating_visitor; | 1638 UpdatingVisitor updating_visitor; |
1822 Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG); | 1639 Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG); |
1823 GlobalHandles::IterateWeakRoots(&updating_visitor); | 1640 GlobalHandles::IterateWeakRoots(&updating_visitor); |
1824 | 1641 |
1825 int live_maps_size = IterateLiveObjects(Heap::map_space(), | 1642 int live_maps = IterateLiveObjects(Heap::map_space(), |
| 1643 &UpdatePointersInOldObject); |
| 1644 int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), |
| 1645 &UpdatePointersInOldObject); |
| 1646 int live_data_olds = IterateLiveObjects(Heap::old_data_space(), |
1826 &UpdatePointersInOldObject); | 1647 &UpdatePointersInOldObject); |
1827 int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(), | 1648 int live_codes = IterateLiveObjects(Heap::code_space(), |
1828 &UpdatePointersInOldObject); | 1649 &UpdatePointersInOldObject); |
1829 int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(), | 1650 int live_cells = IterateLiveObjects(Heap::cell_space(), |
1830 &UpdatePointersInOldObject); | 1651 &UpdatePointersInOldObject); |
1831 int live_codes_size = IterateLiveObjects(Heap::code_space(), | 1652 int live_news = IterateLiveObjects(Heap::new_space(), |
1832 &UpdatePointersInOldObject); | 1653 &UpdatePointersInNewObject); |
1833 int live_cells_size = IterateLiveObjects(Heap::cell_space(), | |
1834 &UpdatePointersInOldObject); | |
1835 int live_news_size = IterateLiveObjects(Heap::new_space(), | |
1836 &UpdatePointersInNewObject); | |
1837 | 1654 |
1838 // Large objects do not move, the map word can be updated directly. | 1655 // Large objects do not move, the map word can be updated directly. |
1839 LargeObjectIterator it(Heap::lo_space()); | 1656 LargeObjectIterator it(Heap::lo_space()); |
1840 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) | 1657 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) |
1841 UpdatePointersInNewObject(obj); | 1658 UpdatePointersInNewObject(obj); |
1842 | 1659 |
1843 USE(live_maps_size); | 1660 USE(live_maps); |
1844 USE(live_pointer_olds_size); | 1661 USE(live_pointer_olds); |
1845 USE(live_data_olds_size); | 1662 USE(live_data_olds); |
1846 USE(live_codes_size); | 1663 USE(live_codes); |
1847 USE(live_cells_size); | 1664 USE(live_cells); |
1848 USE(live_news_size); | 1665 USE(live_news); |
1849 ASSERT(live_maps_size == live_map_objects_size_); | 1666 ASSERT(live_maps == live_map_objects_); |
1850 ASSERT(live_data_olds_size == live_old_data_objects_size_); | 1667 ASSERT(live_data_olds == live_old_data_objects_); |
1851 ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_); | 1668 ASSERT(live_pointer_olds == live_old_pointer_objects_); |
1852 ASSERT(live_codes_size == live_code_objects_size_); | 1669 ASSERT(live_codes == live_code_objects_); |
1853 ASSERT(live_cells_size == live_cell_objects_size_); | 1670 ASSERT(live_cells == live_cell_objects_); |
1854 ASSERT(live_news_size == live_young_objects_size_); | 1671 ASSERT(live_news == live_young_objects_); |
1855 } | 1672 } |
1856 | 1673 |
1857 | 1674 |
1858 int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) { | 1675 int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) { |
1859 // Keep old map pointers | 1676 // Keep old map pointers |
1860 Map* old_map = obj->map(); | 1677 Map* old_map = obj->map(); |
1861 ASSERT(old_map->IsHeapObject()); | 1678 ASSERT(old_map->IsHeapObject()); |
1862 | 1679 |
1863 Address forwarded = GetForwardingAddressInOldSpace(old_map); | 1680 Address forwarded = GetForwardingAddressInOldSpace(old_map); |
1864 | 1681 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1959 // ------------------------------------------------------------------------- | 1776 // ------------------------------------------------------------------------- |
1960 // Phase 4: Relocate objects | 1777 // Phase 4: Relocate objects |
1961 | 1778 |
1962 void MarkCompactCollector::RelocateObjects() { | 1779 void MarkCompactCollector::RelocateObjects() { |
1963 #ifdef DEBUG | 1780 #ifdef DEBUG |
1964 ASSERT(state_ == UPDATE_POINTERS); | 1781 ASSERT(state_ == UPDATE_POINTERS); |
1965 state_ = RELOCATE_OBJECTS; | 1782 state_ = RELOCATE_OBJECTS; |
1966 #endif | 1783 #endif |
1967 // Relocates objects, always relocate map objects first. Relocating | 1784 // Relocates objects, always relocate map objects first. Relocating |
1968 // objects in other space relies on map objects to get object size. | 1785 // objects in other space relies on map objects to get object size. |
1969 int live_maps_size = IterateLiveObjects(Heap::map_space(), | 1786 int live_maps = IterateLiveObjects(Heap::map_space(), &RelocateMapObject); |
1970 &RelocateMapObject); | 1787 int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), |
1971 int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(), | 1788 &RelocateOldPointerObject); |
1972 &RelocateOldPointerObject); | 1789 int live_data_olds = IterateLiveObjects(Heap::old_data_space(), |
1973 int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(), | 1790 &RelocateOldDataObject); |
1974 &RelocateOldDataObject); | 1791 int live_codes = IterateLiveObjects(Heap::code_space(), &RelocateCodeObject); |
1975 int live_codes_size = IterateLiveObjects(Heap::code_space(), | 1792 int live_cells = IterateLiveObjects(Heap::cell_space(), &RelocateCellObject); |
1976 &RelocateCodeObject); | 1793 int live_news = IterateLiveObjects(Heap::new_space(), &RelocateNewObject); |
1977 int live_cells_size = IterateLiveObjects(Heap::cell_space(), | |
1978 &RelocateCellObject); | |
1979 int live_news_size = IterateLiveObjects(Heap::new_space(), | |
1980 &RelocateNewObject); | |
1981 | 1794 |
1982 USE(live_maps_size); | 1795 USE(live_maps); |
1983 USE(live_pointer_olds_size); | 1796 USE(live_data_olds); |
1984 USE(live_data_olds_size); | 1797 USE(live_pointer_olds); |
1985 USE(live_codes_size); | 1798 USE(live_codes); |
1986 USE(live_cells_size); | 1799 USE(live_cells); |
1987 USE(live_news_size); | 1800 USE(live_news); |
1988 ASSERT(live_maps_size == live_map_objects_size_); | 1801 ASSERT(live_maps == live_map_objects_); |
1989 ASSERT(live_data_olds_size == live_old_data_objects_size_); | 1802 ASSERT(live_data_olds == live_old_data_objects_); |
1990 ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_); | 1803 ASSERT(live_pointer_olds == live_old_pointer_objects_); |
1991 ASSERT(live_codes_size == live_code_objects_size_); | 1804 ASSERT(live_codes == live_code_objects_); |
1992 ASSERT(live_cells_size == live_cell_objects_size_); | 1805 ASSERT(live_cells == live_cell_objects_); |
1993 ASSERT(live_news_size == live_young_objects_size_); | 1806 ASSERT(live_news == live_young_objects_); |
1994 | 1807 |
1995 // Flip from and to spaces | 1808 // Flip from and to spaces |
1996 Heap::new_space()->Flip(); | 1809 Heap::new_space()->Flip(); |
1997 | 1810 |
1998 // Set age_mark to bottom in to space | 1811 // Set age_mark to bottom in to space |
1999 Address mark = Heap::new_space()->bottom(); | 1812 Address mark = Heap::new_space()->bottom(); |
2000 Heap::new_space()->set_age_mark(mark); | 1813 Heap::new_space()->set_age_mark(mark); |
2001 | 1814 |
2002 Heap::new_space()->MCCommitRelocationInfo(); | 1815 Heap::new_space()->MCCommitRelocationInfo(); |
2003 #ifdef DEBUG | 1816 #ifdef DEBUG |
2004 // It is safe to write to the remembered sets as remembered sets on a | 1817 // It is safe to write to the remembered sets as remembered sets on a |
2005 // page-by-page basis after committing the m-c forwarding pointer. | 1818 // page-by-page basis after committing the m-c forwarding pointer. |
2006 Page::set_rset_state(Page::IN_USE); | 1819 Page::set_rset_state(Page::IN_USE); |
2007 #endif | 1820 #endif |
2008 PagedSpaces spaces; | 1821 PagedSpaces spaces; |
2009 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) | 1822 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) |
2010 space->MCCommitRelocationInfo(); | 1823 space->MCCommitRelocationInfo(); |
2011 | |
2012 Heap::CheckNewSpaceExpansionCriteria(); | |
2013 Heap::IncrementYoungSurvivorsCounter(live_news_size); | |
2014 } | 1824 } |
2015 | 1825 |
2016 | 1826 |
2017 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { | 1827 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { |
2018 // Recover map pointer. | 1828 // Recover map pointer. |
2019 MapWord encoding = obj->map_word(); | 1829 MapWord encoding = obj->map_word(); |
2020 Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); | 1830 Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); |
2021 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); | 1831 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); |
2022 | 1832 |
2023 // Get forwarding address before resetting map pointer | 1833 // Get forwarding address before resetting map pointer |
2024 Address new_addr = GetForwardingAddressInOldSpace(obj); | 1834 Address new_addr = GetForwardingAddressInOldSpace(obj); |
2025 | 1835 |
2026 // Reset map pointer. The meta map object may not be copied yet so | 1836 // Reset map pointer. The meta map object may not be copied yet so |
2027 // Map::cast does not yet work. | 1837 // Map::cast does not yet work. |
2028 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); | 1838 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); |
2029 | 1839 |
2030 Address old_addr = obj->address(); | 1840 Address old_addr = obj->address(); |
2031 | 1841 |
2032 if (new_addr != old_addr) { | 1842 if (new_addr != old_addr) { |
2033 // Move contents. | 1843 memmove(new_addr, old_addr, Map::kSize); // copy contents |
2034 Heap::MoveBlock(reinterpret_cast<Object**>(new_addr), | |
2035 reinterpret_cast<Object**>(old_addr), | |
2036 Map::kSize); | |
2037 } | 1844 } |
2038 | 1845 |
2039 #ifdef DEBUG | 1846 #ifdef DEBUG |
2040 if (FLAG_gc_verbose) { | 1847 if (FLAG_gc_verbose) { |
2041 PrintF("relocate %p -> %p\n", old_addr, new_addr); | 1848 PrintF("relocate %p -> %p\n", old_addr, new_addr); |
2042 } | 1849 } |
2043 #endif | 1850 #endif |
2044 | 1851 |
2045 return Map::kSize; | 1852 return Map::kSize; |
2046 } | 1853 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2082 | 1889 |
2083 // Get forwarding address before resetting map pointer. | 1890 // Get forwarding address before resetting map pointer. |
2084 Address new_addr = GetForwardingAddressInOldSpace(obj); | 1891 Address new_addr = GetForwardingAddressInOldSpace(obj); |
2085 | 1892 |
2086 // Reset the map pointer. | 1893 // Reset the map pointer. |
2087 int obj_size = RestoreMap(obj, space, new_addr, map_addr); | 1894 int obj_size = RestoreMap(obj, space, new_addr, map_addr); |
2088 | 1895 |
2089 Address old_addr = obj->address(); | 1896 Address old_addr = obj->address(); |
2090 | 1897 |
2091 if (new_addr != old_addr) { | 1898 if (new_addr != old_addr) { |
2092 // Move contents. | 1899 memmove(new_addr, old_addr, obj_size); // Copy contents |
2093 Heap::MoveBlock(reinterpret_cast<Object**>(new_addr), | |
2094 reinterpret_cast<Object**>(old_addr), | |
2095 obj_size); | |
2096 } | 1900 } |
2097 | 1901 |
2098 ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); | 1902 ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); |
2099 | 1903 |
2100 HeapObject* copied_to = HeapObject::FromAddress(new_addr); | 1904 HeapObject* copied_to = HeapObject::FromAddress(new_addr); |
2101 if (copied_to->IsJSFunction()) { | 1905 if (copied_to->IsJSFunction()) { |
2102 PROFILE(FunctionMoveEvent(old_addr, new_addr)); | 1906 PROFILE(FunctionMoveEvent(old_addr, new_addr)); |
2103 } | 1907 } |
2104 | 1908 |
2105 return obj_size; | 1909 return obj_size; |
(...skipping 23 matching lines...) Expand all Loading... |
2129 | 1933 |
2130 // Get forwarding address before resetting map pointer | 1934 // Get forwarding address before resetting map pointer |
2131 Address new_addr = GetForwardingAddressInOldSpace(obj); | 1935 Address new_addr = GetForwardingAddressInOldSpace(obj); |
2132 | 1936 |
2133 // Reset the map pointer. | 1937 // Reset the map pointer. |
2134 int obj_size = RestoreMap(obj, Heap::code_space(), new_addr, map_addr); | 1938 int obj_size = RestoreMap(obj, Heap::code_space(), new_addr, map_addr); |
2135 | 1939 |
2136 Address old_addr = obj->address(); | 1940 Address old_addr = obj->address(); |
2137 | 1941 |
2138 if (new_addr != old_addr) { | 1942 if (new_addr != old_addr) { |
2139 // Move contents. | 1943 memmove(new_addr, old_addr, obj_size); // Copy contents. |
2140 Heap::MoveBlock(reinterpret_cast<Object**>(new_addr), | |
2141 reinterpret_cast<Object**>(old_addr), | |
2142 obj_size); | |
2143 } | 1944 } |
2144 | 1945 |
2145 HeapObject* copied_to = HeapObject::FromAddress(new_addr); | 1946 HeapObject* copied_to = HeapObject::FromAddress(new_addr); |
2146 if (copied_to->IsCode()) { | 1947 if (copied_to->IsCode()) { |
2147 // May also update inline cache target. | 1948 // May also update inline cache target. |
2148 Code::cast(copied_to)->Relocate(new_addr - old_addr); | 1949 Code::cast(copied_to)->Relocate(new_addr - old_addr); |
2149 // Notify the logger that compiled code has moved. | 1950 // Notify the logger that compiled code has moved. |
2150 PROFILE(CodeMoveEvent(old_addr, new_addr)); | 1951 PROFILE(CodeMoveEvent(old_addr, new_addr)); |
2151 } | 1952 } |
2152 | 1953 |
(...skipping 15 matching lines...) Expand all Loading... |
2168 if (Heap::new_space()->FromSpaceContains(new_addr)) { | 1969 if (Heap::new_space()->FromSpaceContains(new_addr)) { |
2169 ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= | 1970 ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= |
2170 Heap::new_space()->ToSpaceOffsetForAddress(old_addr)); | 1971 Heap::new_space()->ToSpaceOffsetForAddress(old_addr)); |
2171 } else { | 1972 } else { |
2172 ASSERT(Heap::TargetSpace(obj) == Heap::old_pointer_space() || | 1973 ASSERT(Heap::TargetSpace(obj) == Heap::old_pointer_space() || |
2173 Heap::TargetSpace(obj) == Heap::old_data_space()); | 1974 Heap::TargetSpace(obj) == Heap::old_data_space()); |
2174 } | 1975 } |
2175 #endif | 1976 #endif |
2176 | 1977 |
2177 // New and old addresses cannot overlap. | 1978 // New and old addresses cannot overlap. |
2178 Heap::CopyBlock(reinterpret_cast<Object**>(new_addr), | 1979 memcpy(reinterpret_cast<void*>(new_addr), |
2179 reinterpret_cast<Object**>(old_addr), | 1980 reinterpret_cast<void*>(old_addr), |
2180 obj_size); | 1981 obj_size); |
2181 | 1982 |
2182 #ifdef DEBUG | 1983 #ifdef DEBUG |
2183 if (FLAG_gc_verbose) { | 1984 if (FLAG_gc_verbose) { |
2184 PrintF("relocate %p -> %p\n", old_addr, new_addr); | 1985 PrintF("relocate %p -> %p\n", old_addr, new_addr); |
2185 } | 1986 } |
2186 #endif | 1987 #endif |
2187 | 1988 |
2188 HeapObject* copied_to = HeapObject::FromAddress(new_addr); | 1989 HeapObject* copied_to = HeapObject::FromAddress(new_addr); |
2189 if (copied_to->IsJSFunction()) { | 1990 if (copied_to->IsJSFunction()) { |
2190 PROFILE(FunctionMoveEvent(old_addr, new_addr)); | 1991 PROFILE(FunctionMoveEvent(old_addr, new_addr)); |
(...skipping 19 matching lines...) Expand all Loading... |
2210 #ifdef ENABLE_LOGGING_AND_PROFILING | 2011 #ifdef ENABLE_LOGGING_AND_PROFILING |
2211 if (obj->IsCode()) { | 2012 if (obj->IsCode()) { |
2212 PROFILE(CodeDeleteEvent(obj->address())); | 2013 PROFILE(CodeDeleteEvent(obj->address())); |
2213 } else if (obj->IsJSFunction()) { | 2014 } else if (obj->IsJSFunction()) { |
2214 PROFILE(FunctionDeleteEvent(obj->address())); | 2015 PROFILE(FunctionDeleteEvent(obj->address())); |
2215 } | 2016 } |
2216 #endif | 2017 #endif |
2217 } | 2018 } |
2218 | 2019 |
2219 } } // namespace v8::internal | 2020 } } // namespace v8::internal |
OLD | NEW |