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

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

Issue 1622016: Reverting r4318 (merge of scavenge into sweeping pass of MSC garbage collecto... (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_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
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
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
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
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
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
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
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
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
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
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
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
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
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