Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: src/mark-compact.cc

Issue 1217011: Merging scavenge into sweeping phase of mark-sweep(-compact) collector. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mark-compact.h ('k') | src/utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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_ = 0; 56 int MarkCompactCollector::live_young_objects_size_ = 0;
57 int MarkCompactCollector::live_old_data_objects_ = 0; 57 int MarkCompactCollector::live_old_data_objects_size_ = 0;
58 int MarkCompactCollector::live_old_pointer_objects_ = 0; 58 int MarkCompactCollector::live_old_pointer_objects_size_ = 0;
59 int MarkCompactCollector::live_code_objects_ = 0; 59 int MarkCompactCollector::live_code_objects_size_ = 0;
60 int MarkCompactCollector::live_map_objects_ = 0; 60 int MarkCompactCollector::live_map_objects_size_ = 0;
61 int MarkCompactCollector::live_cell_objects_ = 0; 61 int MarkCompactCollector::live_cell_objects_size_ = 0;
62 int MarkCompactCollector::live_lo_objects_ = 0; 62 int MarkCompactCollector::live_lo_objects_size_ = 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
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_ = 0; 139 live_young_objects_size_ = 0;
140 live_old_pointer_objects_ = 0; 140 live_old_pointer_objects_size_ = 0;
141 live_old_data_objects_ = 0; 141 live_old_data_objects_size_ = 0;
142 live_code_objects_ = 0; 142 live_code_objects_size_ = 0;
143 live_map_objects_ = 0; 143 live_map_objects_size_ = 0;
144 live_cell_objects_ = 0; 144 live_cell_objects_size_ = 0;
145 live_lo_objects_ = 0; 145 live_lo_objects_size_ = 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
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_++; 745 live_young_objects_size_ += obj->Size();
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_++; 748 live_map_objects_size_ += obj->Size();
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_++; 751 live_cell_objects_size_ += obj->Size();
752 } else if (Heap::old_pointer_space()->Contains(obj)) { 752 } else if (Heap::old_pointer_space()->Contains(obj)) {
753 live_old_pointer_objects_++; 753 live_old_pointer_objects_size_ += obj->Size();
754 } else if (Heap::old_data_space()->Contains(obj)) { 754 } else if (Heap::old_data_space()->Contains(obj)) {
755 live_old_data_objects_++; 755 live_old_data_objects_size_ += obj->Size();
756 } else if (Heap::code_space()->Contains(obj)) { 756 } else if (Heap::code_space()->Contains(obj)) {
757 live_code_objects_++; 757 live_code_objects_size_ += obj->Size();
758 } else if (Heap::lo_space()->Contains(obj)) { 758 } else if (Heap::lo_space()->Contains(obj)) {
759 live_lo_objects_++; 759 live_lo_objects_size_ += obj->Size();
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
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 static void SweepSpace(NewSpace* space) { 1071 // We scavange new space simultaneously with sweeping. This is done in two
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.
1072 HeapObject* object; 1236 HeapObject* object;
1073 for (Address current = space->bottom(); 1237 for (Address current = space->bottom();
1074 current < space->top(); 1238 current < space->top();
1075 current += object->Size()) { 1239 current += object->Size()) {
1076 object = HeapObject::FromAddress(current); 1240 object = HeapObject::FromAddress(current);
1077 if (object->IsMarked()) { 1241
1078 object->ClearMark(); 1242 object->IterateBody(object->map()->instance_type(),
1079 MarkCompactCollector::tracer()->decrement_marked_count(); 1243 object->Size(),
1080 } else { 1244 &updating_visitor);
1081 // We give non-live objects a map that will correctly give their size, 1245 }
1082 // since their existing map might not be live after the collection. 1246
1083 int size = object->Size(); 1247 // Update roots.
1084 if (size >= ByteArray::kHeaderSize) { 1248 Heap::IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE);
1085 object->set_map(Heap::raw_unchecked_byte_array_map()); 1249
1086 ByteArray::cast(object)->set_length(ByteArray::LengthFor(size)); 1250 // Update pointers in old spaces.
1087 } else { 1251 Heap::IterateRSet(Heap::old_pointer_space(), &UpdatePointerToNewGen);
1088 ASSERT(size == kPointerSize); 1252 Heap::IterateRSet(Heap::map_space(), &UpdatePointerToNewGen);
1089 object->set_map(Heap::raw_unchecked_one_pointer_filler_map()); 1253 Heap::lo_space()->IterateRSet(&UpdatePointerToNewGen);
1090 } 1254
1091 ASSERT(object->Size() == size); 1255 // Update pointers from cells.
1092 } 1256 HeapObjectIterator cell_iterator(Heap::cell_space());
1093 // The object is now unmarked for the call to Size() at the top of the 1257 for (HeapObject* cell = cell_iterator.next();
1094 // loop. 1258 cell != NULL;
1095 } 1259 cell = cell_iterator.next()) {
1096 } 1260 if (cell->IsJSGlobalPropertyCell()) {
1097 1261 Address value_address =
1098 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 }
1276
1277
1099 static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) { 1278 static void SweepSpace(PagedSpace* space, DeallocateFunction dealloc) {
1100 PageIterator it(space, PageIterator::PAGES_IN_USE); 1279 PageIterator it(space, PageIterator::PAGES_IN_USE);
1101 while (it.has_next()) { 1280 while (it.has_next()) {
1102 Page* p = it.next(); 1281 Page* p = it.next();
1103 1282
1104 bool is_previous_alive = true; 1283 bool is_previous_alive = true;
1105 Address free_start = NULL; 1284 Address free_start = NULL;
1106 HeapObject* object; 1285 HeapObject* object;
1107 1286
1108 for (Address current = p->ObjectAreaStart(); 1287 for (Address current = p->ObjectAreaStart();
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
1375 Map* map = NextMap(&map_to_evacuate_it_, NULL, true); 1554 Map* map = NextMap(&map_to_evacuate_it_, NULL, true);
1376 ASSERT(map != NULL); 1555 ASSERT(map != NULL);
1377 ASSERT(map->IsMap()); 1556 ASSERT(map->IsMap());
1378 return map; 1557 return map;
1379 } 1558 }
1380 1559
1381 static void EvacuateMap(Map* vacant_map, Map* map_to_evacuate) { 1560 static void EvacuateMap(Map* vacant_map, Map* map_to_evacuate) {
1382 ASSERT(FreeListNode::IsFreeListNode(vacant_map)); 1561 ASSERT(FreeListNode::IsFreeListNode(vacant_map));
1383 ASSERT(map_to_evacuate->IsMap()); 1562 ASSERT(map_to_evacuate->IsMap());
1384 1563
1385 memcpy( 1564 ASSERT(Map::kSize % 4 == 0);
1386 reinterpret_cast<void*>(vacant_map->address()), 1565
1387 reinterpret_cast<void*>(map_to_evacuate->address()), 1566 Heap::CopyBlock(reinterpret_cast<Object**>(vacant_map->address()),
1388 Map::kSize); 1567 reinterpret_cast<Object**>(map_to_evacuate->address()),
1568 Map::kSize);
1569
1389 ASSERT(vacant_map->IsMap()); // Due to memcpy above. 1570 ASSERT(vacant_map->IsMap()); // Due to memcpy above.
1390 1571
1391 MapWord forwarding_map_word = MapWord::FromMap(vacant_map); 1572 MapWord forwarding_map_word = MapWord::FromMap(vacant_map);
1392 forwarding_map_word.SetOverflow(); 1573 forwarding_map_word.SetOverflow();
1393 map_to_evacuate->set_map_word(forwarding_map_word); 1574 map_to_evacuate->set_map_word(forwarding_map_word);
1394 1575
1395 ASSERT(map_to_evacuate->map_word().IsOverflowed()); 1576 ASSERT(map_to_evacuate->map_word().IsOverflowed());
1396 ASSERT(GetForwardedMap(map_to_evacuate->map_word()) == vacant_map); 1577 ASSERT(GetForwardedMap(map_to_evacuate->map_word()) == vacant_map);
1397 } 1578 }
1398 1579
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1458 ASSERT(!IsCompacting()); 1639 ASSERT(!IsCompacting());
1459 // Noncompacting collections simply sweep the spaces to clear the mark 1640 // Noncompacting collections simply sweep the spaces to clear the mark
1460 // bits and free the nonlive blocks (for old and map spaces). We sweep 1641 // bits and free the nonlive blocks (for old and map spaces). We sweep
1461 // the map space last because freeing non-live maps overwrites them and 1642 // the map space last because freeing non-live maps overwrites them and
1462 // the other spaces rely on possibly non-live maps to get the sizes for 1643 // the other spaces rely on possibly non-live maps to get the sizes for
1463 // non-live objects. 1644 // non-live objects.
1464 SweepSpace(Heap::old_pointer_space(), &DeallocateOldPointerBlock); 1645 SweepSpace(Heap::old_pointer_space(), &DeallocateOldPointerBlock);
1465 SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock); 1646 SweepSpace(Heap::old_data_space(), &DeallocateOldDataBlock);
1466 SweepSpace(Heap::code_space(), &DeallocateCodeBlock); 1647 SweepSpace(Heap::code_space(), &DeallocateCodeBlock);
1467 SweepSpace(Heap::cell_space(), &DeallocateCellBlock); 1648 SweepSpace(Heap::cell_space(), &DeallocateCellBlock);
1468 SweepSpace(Heap::new_space()); 1649 SweepNewSpace(Heap::new_space());
1469 SweepSpace(Heap::map_space(), &DeallocateMapBlock); 1650 SweepSpace(Heap::map_space(), &DeallocateMapBlock);
1470 int live_maps = Heap::map_space()->Size() / Map::kSize; 1651 int live_maps_size = Heap::map_space()->Size();
1471 ASSERT(live_map_objects_ == live_maps); 1652 int live_maps = live_maps_size / Map::kSize;
1653 ASSERT(live_map_objects_size_ == live_maps_size);
1472 1654
1473 if (Heap::map_space()->NeedsCompaction(live_maps)) { 1655 if (Heap::map_space()->NeedsCompaction(live_maps)) {
1474 MapCompact map_compact(live_maps); 1656 MapCompact map_compact(live_maps);
1475 1657
1476 map_compact.CompactMaps(); 1658 map_compact.CompactMaps();
1477 map_compact.UpdateMapPointersInRoots(); 1659 map_compact.UpdateMapPointersInRoots();
1478 1660
1479 map_compact.FinishMapSpace(); 1661 map_compact.FinishMapSpace();
1480 PagedSpaces spaces; 1662 PagedSpaces spaces;
1481 for (PagedSpace* space = spaces.next(); 1663 for (PagedSpace* space = spaces.next();
(...skipping 11 matching lines...) Expand all
1493 1675
1494 // Iterate the live objects in a range of addresses (eg, a page or a 1676 // Iterate the live objects in a range of addresses (eg, a page or a
1495 // semispace). The live regions of the range have been linked into a list. 1677 // semispace). The live regions of the range have been linked into a list.
1496 // The first live region is [first_live_start, first_live_end), and the last 1678 // The first live region is [first_live_start, first_live_end), and the last
1497 // address in the range is top. The callback function is used to get the 1679 // address in the range is top. The callback function is used to get the
1498 // size of each live object. 1680 // size of each live object.
1499 int MarkCompactCollector::IterateLiveObjectsInRange( 1681 int MarkCompactCollector::IterateLiveObjectsInRange(
1500 Address start, 1682 Address start,
1501 Address end, 1683 Address end,
1502 HeapObjectCallback size_func) { 1684 HeapObjectCallback size_func) {
1503 int live_objects = 0; 1685 int live_objects_size = 0;
1504 Address current = start; 1686 Address current = start;
1505 while (current < end) { 1687 while (current < end) {
1506 uint32_t encoded_map = Memory::uint32_at(current); 1688 uint32_t encoded_map = Memory::uint32_at(current);
1507 if (encoded_map == kSingleFreeEncoding) { 1689 if (encoded_map == kSingleFreeEncoding) {
1508 current += kPointerSize; 1690 current += kPointerSize;
1509 } else if (encoded_map == kMultiFreeEncoding) { 1691 } else if (encoded_map == kMultiFreeEncoding) {
1510 current += Memory::int_at(current + kIntSize); 1692 current += Memory::int_at(current + kIntSize);
1511 } else { 1693 } else {
1512 live_objects++; 1694 int size = size_func(HeapObject::FromAddress(current));
1513 current += size_func(HeapObject::FromAddress(current)); 1695 current += size;
1696 live_objects_size += size;
1514 } 1697 }
1515 } 1698 }
1516 return live_objects; 1699 return live_objects_size;
1517 } 1700 }
1518 1701
1519 1702
1520 int MarkCompactCollector::IterateLiveObjects(NewSpace* space, 1703 int MarkCompactCollector::IterateLiveObjects(NewSpace* space,
1521 HeapObjectCallback size_f) { 1704 HeapObjectCallback size_f) {
1522 ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS); 1705 ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
1523 return IterateLiveObjectsInRange(space->bottom(), space->top(), size_f); 1706 return IterateLiveObjectsInRange(space->bottom(), space->top(), size_f);
1524 } 1707 }
1525 1708
1526 1709
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1632 1815
1633 void MarkCompactCollector::UpdatePointers() { 1816 void MarkCompactCollector::UpdatePointers() {
1634 #ifdef DEBUG 1817 #ifdef DEBUG
1635 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); 1818 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES);
1636 state_ = UPDATE_POINTERS; 1819 state_ = UPDATE_POINTERS;
1637 #endif 1820 #endif
1638 UpdatingVisitor updating_visitor; 1821 UpdatingVisitor updating_visitor;
1639 Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG); 1822 Heap::IterateRoots(&updating_visitor, VISIT_ONLY_STRONG);
1640 GlobalHandles::IterateWeakRoots(&updating_visitor); 1823 GlobalHandles::IterateWeakRoots(&updating_visitor);
1641 1824
1642 int live_maps = IterateLiveObjects(Heap::map_space(), 1825 int live_maps_size = 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(),
1647 &UpdatePointersInOldObject); 1826 &UpdatePointersInOldObject);
1648 int live_codes = IterateLiveObjects(Heap::code_space(), 1827 int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(),
1649 &UpdatePointersInOldObject); 1828 &UpdatePointersInOldObject);
1650 int live_cells = IterateLiveObjects(Heap::cell_space(), 1829 int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(),
1651 &UpdatePointersInOldObject); 1830 &UpdatePointersInOldObject);
1652 int live_news = IterateLiveObjects(Heap::new_space(), 1831 int live_codes_size = IterateLiveObjects(Heap::code_space(),
1653 &UpdatePointersInNewObject); 1832 &UpdatePointersInOldObject);
1833 int live_cells_size = IterateLiveObjects(Heap::cell_space(),
1834 &UpdatePointersInOldObject);
1835 int live_news_size = IterateLiveObjects(Heap::new_space(),
1836 &UpdatePointersInNewObject);
1654 1837
1655 // Large objects do not move, the map word can be updated directly. 1838 // Large objects do not move, the map word can be updated directly.
1656 LargeObjectIterator it(Heap::lo_space()); 1839 LargeObjectIterator it(Heap::lo_space());
1657 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) 1840 for (HeapObject* obj = it.next(); obj != NULL; obj = it.next())
1658 UpdatePointersInNewObject(obj); 1841 UpdatePointersInNewObject(obj);
1659 1842
1660 USE(live_maps); 1843 USE(live_maps_size);
1661 USE(live_pointer_olds); 1844 USE(live_pointer_olds_size);
1662 USE(live_data_olds); 1845 USE(live_data_olds_size);
1663 USE(live_codes); 1846 USE(live_codes_size);
1664 USE(live_cells); 1847 USE(live_cells_size);
1665 USE(live_news); 1848 USE(live_news_size);
1666 ASSERT(live_maps == live_map_objects_); 1849 ASSERT(live_maps_size == live_map_objects_size_);
1667 ASSERT(live_data_olds == live_old_data_objects_); 1850 ASSERT(live_data_olds_size == live_old_data_objects_size_);
1668 ASSERT(live_pointer_olds == live_old_pointer_objects_); 1851 ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_);
1669 ASSERT(live_codes == live_code_objects_); 1852 ASSERT(live_codes_size == live_code_objects_size_);
1670 ASSERT(live_cells == live_cell_objects_); 1853 ASSERT(live_cells_size == live_cell_objects_size_);
1671 ASSERT(live_news == live_young_objects_); 1854 ASSERT(live_news_size == live_young_objects_size_);
1672 } 1855 }
1673 1856
1674 1857
1675 int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) { 1858 int MarkCompactCollector::UpdatePointersInNewObject(HeapObject* obj) {
1676 // Keep old map pointers 1859 // Keep old map pointers
1677 Map* old_map = obj->map(); 1860 Map* old_map = obj->map();
1678 ASSERT(old_map->IsHeapObject()); 1861 ASSERT(old_map->IsHeapObject());
1679 1862
1680 Address forwarded = GetForwardingAddressInOldSpace(old_map); 1863 Address forwarded = GetForwardingAddressInOldSpace(old_map);
1681 1864
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1776 // ------------------------------------------------------------------------- 1959 // -------------------------------------------------------------------------
1777 // Phase 4: Relocate objects 1960 // Phase 4: Relocate objects
1778 1961
1779 void MarkCompactCollector::RelocateObjects() { 1962 void MarkCompactCollector::RelocateObjects() {
1780 #ifdef DEBUG 1963 #ifdef DEBUG
1781 ASSERT(state_ == UPDATE_POINTERS); 1964 ASSERT(state_ == UPDATE_POINTERS);
1782 state_ = RELOCATE_OBJECTS; 1965 state_ = RELOCATE_OBJECTS;
1783 #endif 1966 #endif
1784 // Relocates objects, always relocate map objects first. Relocating 1967 // Relocates objects, always relocate map objects first. Relocating
1785 // objects in other space relies on map objects to get object size. 1968 // objects in other space relies on map objects to get object size.
1786 int live_maps = IterateLiveObjects(Heap::map_space(), &RelocateMapObject); 1969 int live_maps_size = IterateLiveObjects(Heap::map_space(),
1787 int live_pointer_olds = IterateLiveObjects(Heap::old_pointer_space(), 1970 &RelocateMapObject);
1788 &RelocateOldPointerObject); 1971 int live_pointer_olds_size = IterateLiveObjects(Heap::old_pointer_space(),
1789 int live_data_olds = IterateLiveObjects(Heap::old_data_space(), 1972 &RelocateOldPointerObject);
1790 &RelocateOldDataObject); 1973 int live_data_olds_size = IterateLiveObjects(Heap::old_data_space(),
1791 int live_codes = IterateLiveObjects(Heap::code_space(), &RelocateCodeObject); 1974 &RelocateOldDataObject);
1792 int live_cells = IterateLiveObjects(Heap::cell_space(), &RelocateCellObject); 1975 int live_codes_size = IterateLiveObjects(Heap::code_space(),
1793 int live_news = IterateLiveObjects(Heap::new_space(), &RelocateNewObject); 1976 &RelocateCodeObject);
1977 int live_cells_size = IterateLiveObjects(Heap::cell_space(),
1978 &RelocateCellObject);
1979 int live_news_size = IterateLiveObjects(Heap::new_space(),
1980 &RelocateNewObject);
1794 1981
1795 USE(live_maps); 1982 USE(live_maps_size);
1796 USE(live_data_olds); 1983 USE(live_pointer_olds_size);
1797 USE(live_pointer_olds); 1984 USE(live_data_olds_size);
1798 USE(live_codes); 1985 USE(live_codes_size);
1799 USE(live_cells); 1986 USE(live_cells_size);
1800 USE(live_news); 1987 USE(live_news_size);
1801 ASSERT(live_maps == live_map_objects_); 1988 ASSERT(live_maps_size == live_map_objects_size_);
1802 ASSERT(live_data_olds == live_old_data_objects_); 1989 ASSERT(live_data_olds_size == live_old_data_objects_size_);
1803 ASSERT(live_pointer_olds == live_old_pointer_objects_); 1990 ASSERT(live_pointer_olds_size == live_old_pointer_objects_size_);
1804 ASSERT(live_codes == live_code_objects_); 1991 ASSERT(live_codes_size == live_code_objects_size_);
1805 ASSERT(live_cells == live_cell_objects_); 1992 ASSERT(live_cells_size == live_cell_objects_size_);
1806 ASSERT(live_news == live_young_objects_); 1993 ASSERT(live_news_size == live_young_objects_size_);
1807 1994
1808 // Flip from and to spaces 1995 // Flip from and to spaces
1809 Heap::new_space()->Flip(); 1996 Heap::new_space()->Flip();
1810 1997
1811 // Set age_mark to bottom in to space 1998 // Set age_mark to bottom in to space
1812 Address mark = Heap::new_space()->bottom(); 1999 Address mark = Heap::new_space()->bottom();
1813 Heap::new_space()->set_age_mark(mark); 2000 Heap::new_space()->set_age_mark(mark);
1814 2001
1815 Heap::new_space()->MCCommitRelocationInfo(); 2002 Heap::new_space()->MCCommitRelocationInfo();
1816 #ifdef DEBUG 2003 #ifdef DEBUG
1817 // It is safe to write to the remembered sets as remembered sets on a 2004 // It is safe to write to the remembered sets as remembered sets on a
1818 // page-by-page basis after committing the m-c forwarding pointer. 2005 // page-by-page basis after committing the m-c forwarding pointer.
1819 Page::set_rset_state(Page::IN_USE); 2006 Page::set_rset_state(Page::IN_USE);
1820 #endif 2007 #endif
1821 PagedSpaces spaces; 2008 PagedSpaces spaces;
1822 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) 2009 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next())
1823 space->MCCommitRelocationInfo(); 2010 space->MCCommitRelocationInfo();
2011
2012 Heap::CheckNewSpaceExpansionCriteria();
2013 Heap::IncrementYoungSurvivorsCounter(live_news_size);
1824 } 2014 }
1825 2015
1826 2016
1827 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) { 2017 int MarkCompactCollector::RelocateMapObject(HeapObject* obj) {
1828 // Recover map pointer. 2018 // Recover map pointer.
1829 MapWord encoding = obj->map_word(); 2019 MapWord encoding = obj->map_word();
1830 Address map_addr = encoding.DecodeMapAddress(Heap::map_space()); 2020 Address map_addr = encoding.DecodeMapAddress(Heap::map_space());
1831 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr))); 2021 ASSERT(Heap::map_space()->Contains(HeapObject::FromAddress(map_addr)));
1832 2022
1833 // Get forwarding address before resetting map pointer 2023 // Get forwarding address before resetting map pointer
1834 Address new_addr = GetForwardingAddressInOldSpace(obj); 2024 Address new_addr = GetForwardingAddressInOldSpace(obj);
1835 2025
1836 // Reset map pointer. The meta map object may not be copied yet so 2026 // Reset map pointer. The meta map object may not be copied yet so
1837 // Map::cast does not yet work. 2027 // Map::cast does not yet work.
1838 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr))); 2028 obj->set_map(reinterpret_cast<Map*>(HeapObject::FromAddress(map_addr)));
1839 2029
1840 Address old_addr = obj->address(); 2030 Address old_addr = obj->address();
1841 2031
1842 if (new_addr != old_addr) { 2032 if (new_addr != old_addr) {
1843 memmove(new_addr, old_addr, Map::kSize); // copy contents 2033 // Move contents.
2034 Heap::MoveBlock(reinterpret_cast<Object**>(new_addr),
2035 reinterpret_cast<Object**>(old_addr),
2036 Map::kSize);
1844 } 2037 }
1845 2038
1846 #ifdef DEBUG 2039 #ifdef DEBUG
1847 if (FLAG_gc_verbose) { 2040 if (FLAG_gc_verbose) {
1848 PrintF("relocate %p -> %p\n", old_addr, new_addr); 2041 PrintF("relocate %p -> %p\n", old_addr, new_addr);
1849 } 2042 }
1850 #endif 2043 #endif
1851 2044
1852 return Map::kSize; 2045 return Map::kSize;
1853 } 2046 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1889 2082
1890 // Get forwarding address before resetting map pointer. 2083 // Get forwarding address before resetting map pointer.
1891 Address new_addr = GetForwardingAddressInOldSpace(obj); 2084 Address new_addr = GetForwardingAddressInOldSpace(obj);
1892 2085
1893 // Reset the map pointer. 2086 // Reset the map pointer.
1894 int obj_size = RestoreMap(obj, space, new_addr, map_addr); 2087 int obj_size = RestoreMap(obj, space, new_addr, map_addr);
1895 2088
1896 Address old_addr = obj->address(); 2089 Address old_addr = obj->address();
1897 2090
1898 if (new_addr != old_addr) { 2091 if (new_addr != old_addr) {
1899 memmove(new_addr, old_addr, obj_size); // Copy contents 2092 // Move contents.
2093 Heap::MoveBlock(reinterpret_cast<Object**>(new_addr),
2094 reinterpret_cast<Object**>(old_addr),
2095 obj_size);
1900 } 2096 }
1901 2097
1902 ASSERT(!HeapObject::FromAddress(new_addr)->IsCode()); 2098 ASSERT(!HeapObject::FromAddress(new_addr)->IsCode());
1903 2099
1904 HeapObject* copied_to = HeapObject::FromAddress(new_addr); 2100 HeapObject* copied_to = HeapObject::FromAddress(new_addr);
1905 if (copied_to->IsJSFunction()) { 2101 if (copied_to->IsJSFunction()) {
1906 LOG(FunctionMoveEvent(old_addr, new_addr)); 2102 LOG(FunctionMoveEvent(old_addr, new_addr));
1907 } 2103 }
1908 2104
1909 return obj_size; 2105 return obj_size;
(...skipping 23 matching lines...) Expand all
1933 2129
1934 // Get forwarding address before resetting map pointer 2130 // Get forwarding address before resetting map pointer
1935 Address new_addr = GetForwardingAddressInOldSpace(obj); 2131 Address new_addr = GetForwardingAddressInOldSpace(obj);
1936 2132
1937 // Reset the map pointer. 2133 // Reset the map pointer.
1938 int obj_size = RestoreMap(obj, Heap::code_space(), new_addr, map_addr); 2134 int obj_size = RestoreMap(obj, Heap::code_space(), new_addr, map_addr);
1939 2135
1940 Address old_addr = obj->address(); 2136 Address old_addr = obj->address();
1941 2137
1942 if (new_addr != old_addr) { 2138 if (new_addr != old_addr) {
1943 memmove(new_addr, old_addr, obj_size); // Copy contents. 2139 // Move contents.
2140 Heap::MoveBlock(reinterpret_cast<Object**>(new_addr),
2141 reinterpret_cast<Object**>(old_addr),
2142 obj_size);
1944 } 2143 }
1945 2144
1946 HeapObject* copied_to = HeapObject::FromAddress(new_addr); 2145 HeapObject* copied_to = HeapObject::FromAddress(new_addr);
1947 if (copied_to->IsCode()) { 2146 if (copied_to->IsCode()) {
1948 // May also update inline cache target. 2147 // May also update inline cache target.
1949 Code::cast(copied_to)->Relocate(new_addr - old_addr); 2148 Code::cast(copied_to)->Relocate(new_addr - old_addr);
1950 // Notify the logger that compiled code has moved. 2149 // Notify the logger that compiled code has moved.
1951 LOG(CodeMoveEvent(old_addr, new_addr)); 2150 LOG(CodeMoveEvent(old_addr, new_addr));
1952 } 2151 }
1953 2152
(...skipping 15 matching lines...) Expand all
1969 if (Heap::new_space()->FromSpaceContains(new_addr)) { 2168 if (Heap::new_space()->FromSpaceContains(new_addr)) {
1970 ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <= 2169 ASSERT(Heap::new_space()->FromSpaceOffsetForAddress(new_addr) <=
1971 Heap::new_space()->ToSpaceOffsetForAddress(old_addr)); 2170 Heap::new_space()->ToSpaceOffsetForAddress(old_addr));
1972 } else { 2171 } else {
1973 ASSERT(Heap::TargetSpace(obj) == Heap::old_pointer_space() || 2172 ASSERT(Heap::TargetSpace(obj) == Heap::old_pointer_space() ||
1974 Heap::TargetSpace(obj) == Heap::old_data_space()); 2173 Heap::TargetSpace(obj) == Heap::old_data_space());
1975 } 2174 }
1976 #endif 2175 #endif
1977 2176
1978 // New and old addresses cannot overlap. 2177 // New and old addresses cannot overlap.
1979 memcpy(reinterpret_cast<void*>(new_addr), 2178 Heap::CopyBlock(reinterpret_cast<Object**>(new_addr),
1980 reinterpret_cast<void*>(old_addr), 2179 reinterpret_cast<Object**>(old_addr),
1981 obj_size); 2180 obj_size);
1982 2181
1983 #ifdef DEBUG 2182 #ifdef DEBUG
1984 if (FLAG_gc_verbose) { 2183 if (FLAG_gc_verbose) {
1985 PrintF("relocate %p -> %p\n", old_addr, new_addr); 2184 PrintF("relocate %p -> %p\n", old_addr, new_addr);
1986 } 2185 }
1987 #endif 2186 #endif
1988 2187
1989 HeapObject* copied_to = HeapObject::FromAddress(new_addr); 2188 HeapObject* copied_to = HeapObject::FromAddress(new_addr);
1990 if (copied_to->IsJSFunction()) { 2189 if (copied_to->IsJSFunction()) {
1991 LOG(FunctionMoveEvent(old_addr, new_addr)); 2190 LOG(FunctionMoveEvent(old_addr, new_addr));
(...skipping 19 matching lines...) Expand all
2011 #ifdef ENABLE_LOGGING_AND_PROFILING 2210 #ifdef ENABLE_LOGGING_AND_PROFILING
2012 if (obj->IsCode()) { 2211 if (obj->IsCode()) {
2013 LOG(CodeDeleteEvent(obj->address())); 2212 LOG(CodeDeleteEvent(obj->address()));
2014 } else if (obj->IsJSFunction()) { 2213 } else if (obj->IsJSFunction()) {
2015 LOG(FunctionDeleteEvent(obj->address())); 2214 LOG(FunctionDeleteEvent(obj->address()));
2016 } 2215 }
2017 #endif 2216 #endif
2018 } 2217 }
2019 2218
2020 } } // namespace v8::internal 2219 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/mark-compact.h ('k') | src/utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698