| 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 |