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_ = 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 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_ = 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 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_++; | 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 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 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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |