| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 934 } | 934 } |
| 935 | 935 |
| 936 | 936 |
| 937 void Heap::Scavenge() { | 937 void Heap::Scavenge() { |
| 938 #ifdef DEBUG | 938 #ifdef DEBUG |
| 939 if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers(); | 939 if (FLAG_enable_slow_asserts) VerifyNonPointerSpacePointers(); |
| 940 #endif | 940 #endif |
| 941 | 941 |
| 942 gc_state_ = SCAVENGE; | 942 gc_state_ = SCAVENGE; |
| 943 | 943 |
| 944 SwitchScavengingVisitorsTableIfProfilingWasEnabled(); | |
| 945 | |
| 946 Page::FlipMeaningOfInvalidatedWatermarkFlag(this); | 944 Page::FlipMeaningOfInvalidatedWatermarkFlag(this); |
| 947 #ifdef DEBUG | 945 #ifdef DEBUG |
| 948 VerifyPageWatermarkValidity(old_pointer_space_, ALL_VALID); | 946 VerifyPageWatermarkValidity(old_pointer_space_, ALL_VALID); |
| 949 VerifyPageWatermarkValidity(map_space_, ALL_VALID); | 947 VerifyPageWatermarkValidity(map_space_, ALL_VALID); |
| 950 #endif | 948 #endif |
| 951 | 949 |
| 952 // We do not update an allocation watermark of the top page during linear | 950 // We do not update an allocation watermark of the top page during linear |
| 953 // allocation to avoid overhead. So to maintain the watermark invariant | 951 // allocation to avoid overhead. So to maintain the watermark invariant |
| 954 // we have to manually cache the watermark and mark the top page as having an | 952 // we have to manually cache the watermark and mark the top page as having an |
| 955 // invalid watermark. This guarantees that dirty regions iteration will use a | 953 // invalid watermark. This guarantees that dirty regions iteration will use a |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1227 } | 1225 } |
| 1228 | 1226 |
| 1229 // Take another spin if there are now unswept objects in new space | 1227 // Take another spin if there are now unswept objects in new space |
| 1230 // (there are currently no more unswept promoted objects). | 1228 // (there are currently no more unswept promoted objects). |
| 1231 } while (new_space_front < new_space_.top()); | 1229 } while (new_space_front < new_space_.top()); |
| 1232 | 1230 |
| 1233 return new_space_front; | 1231 return new_space_front; |
| 1234 } | 1232 } |
| 1235 | 1233 |
| 1236 | 1234 |
| 1237 enum LoggingAndProfiling { | |
| 1238 LOGGING_AND_PROFILING_ENABLED, | |
| 1239 LOGGING_AND_PROFILING_DISABLED | |
| 1240 }; | |
| 1241 | |
| 1242 | |
| 1243 typedef void (*ScavengingCallback)(Map* map, | |
| 1244 HeapObject** slot, | |
| 1245 HeapObject* object); | |
| 1246 | |
| 1247 | |
| 1248 static Atomic32 scavenging_visitors_table_mode_; | |
| 1249 static VisitorDispatchTable<ScavengingCallback> scavenging_visitors_table_; | |
| 1250 | |
| 1251 | |
| 1252 INLINE(static void DoScavengeObject(Map* map, | |
| 1253 HeapObject** slot, | |
| 1254 HeapObject* obj)); | |
| 1255 | |
| 1256 | |
| 1257 void DoScavengeObject(Map* map, HeapObject** slot, HeapObject* obj) { | |
| 1258 scavenging_visitors_table_.GetVisitor(map)(map, slot, obj); | |
| 1259 } | |
| 1260 | |
| 1261 | |
| 1262 template<LoggingAndProfiling logging_and_profiling_mode> | |
| 1263 class ScavengingVisitor : public StaticVisitorBase { | 1235 class ScavengingVisitor : public StaticVisitorBase { |
| 1264 public: | 1236 public: |
| 1265 static void Initialize() { | 1237 static void Initialize() { |
| 1266 table_.Register(kVisitSeqAsciiString, &EvacuateSeqAsciiString); | 1238 table_.Register(kVisitSeqAsciiString, &EvacuateSeqAsciiString); |
| 1267 table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString); | 1239 table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString); |
| 1268 table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate); | 1240 table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate); |
| 1269 table_.Register(kVisitByteArray, &EvacuateByteArray); | 1241 table_.Register(kVisitByteArray, &EvacuateByteArray); |
| 1270 table_.Register(kVisitFixedArray, &EvacuateFixedArray); | 1242 table_.Register(kVisitFixedArray, &EvacuateFixedArray); |
| 1271 | |
| 1272 table_.Register(kVisitGlobalContext, | 1243 table_.Register(kVisitGlobalContext, |
| 1273 &ObjectEvacuationStrategy<POINTER_OBJECT>:: | 1244 &ObjectEvacuationStrategy<POINTER_OBJECT>:: |
| 1274 template VisitSpecialized<Context::kSize>); | 1245 VisitSpecialized<Context::kSize>); |
| 1246 |
| 1247 typedef ObjectEvacuationStrategy<POINTER_OBJECT> PointerObject; |
| 1275 | 1248 |
| 1276 table_.Register(kVisitConsString, | 1249 table_.Register(kVisitConsString, |
| 1277 &ObjectEvacuationStrategy<POINTER_OBJECT>:: | 1250 &ObjectEvacuationStrategy<POINTER_OBJECT>:: |
| 1278 template VisitSpecialized<ConsString::kSize>); | 1251 VisitSpecialized<ConsString::kSize>); |
| 1279 | 1252 |
| 1280 table_.Register(kVisitSharedFunctionInfo, | 1253 table_.Register(kVisitSharedFunctionInfo, |
| 1281 &ObjectEvacuationStrategy<POINTER_OBJECT>:: | 1254 &ObjectEvacuationStrategy<POINTER_OBJECT>:: |
| 1282 template VisitSpecialized<SharedFunctionInfo::kSize>); | 1255 VisitSpecialized<SharedFunctionInfo::kSize>); |
| 1283 | 1256 |
| 1284 table_.Register(kVisitJSFunction, | 1257 table_.Register(kVisitJSFunction, |
| 1285 &ObjectEvacuationStrategy<POINTER_OBJECT>:: | 1258 &ObjectEvacuationStrategy<POINTER_OBJECT>:: |
| 1286 template VisitSpecialized<JSFunction::kSize>); | 1259 VisitSpecialized<JSFunction::kSize>); |
| 1287 | 1260 |
| 1288 table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>, | 1261 table_.RegisterSpecializations<ObjectEvacuationStrategy<DATA_OBJECT>, |
| 1289 kVisitDataObject, | 1262 kVisitDataObject, |
| 1290 kVisitDataObjectGeneric>(); | 1263 kVisitDataObjectGeneric>(); |
| 1291 | 1264 |
| 1292 table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, | 1265 table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, |
| 1293 kVisitJSObject, | 1266 kVisitJSObject, |
| 1294 kVisitJSObjectGeneric>(); | 1267 kVisitJSObjectGeneric>(); |
| 1295 | 1268 |
| 1296 table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, | 1269 table_.RegisterSpecializations<ObjectEvacuationStrategy<POINTER_OBJECT>, |
| 1297 kVisitStruct, | 1270 kVisitStruct, |
| 1298 kVisitStructGeneric>(); | 1271 kVisitStructGeneric>(); |
| 1299 } | 1272 } |
| 1300 | 1273 |
| 1301 static VisitorDispatchTable<ScavengingCallback>* GetTable() { | 1274 |
| 1302 return &table_; | 1275 static inline void Scavenge(Map* map, HeapObject** slot, HeapObject* obj) { |
| 1276 table_.GetVisitor(map)(map, slot, obj); |
| 1303 } | 1277 } |
| 1304 | 1278 |
| 1279 |
| 1305 private: | 1280 private: |
| 1306 enum ObjectContents { DATA_OBJECT, POINTER_OBJECT }; | 1281 enum ObjectContents { DATA_OBJECT, POINTER_OBJECT }; |
| 1307 enum SizeRestriction { SMALL, UNKNOWN_SIZE }; | 1282 enum SizeRestriction { SMALL, UNKNOWN_SIZE }; |
| 1308 | 1283 |
| 1309 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 1284 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 1310 static void RecordCopiedObject(Heap* heap, HeapObject* obj) { | 1285 static void RecordCopiedObject(Heap* heap, HeapObject* obj) { |
| 1311 bool should_record = false; | 1286 bool should_record = false; |
| 1312 #ifdef DEBUG | 1287 #ifdef DEBUG |
| 1313 should_record = FLAG_heap_stats; | 1288 should_record = FLAG_heap_stats; |
| 1314 #endif | 1289 #endif |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1331 INLINE(static HeapObject* MigrateObject(Heap* heap, | 1306 INLINE(static HeapObject* MigrateObject(Heap* heap, |
| 1332 HeapObject* source, | 1307 HeapObject* source, |
| 1333 HeapObject* target, | 1308 HeapObject* target, |
| 1334 int size)) { | 1309 int size)) { |
| 1335 // Copy the content of source to target. | 1310 // Copy the content of source to target. |
| 1336 heap->CopyBlock(target->address(), source->address(), size); | 1311 heap->CopyBlock(target->address(), source->address(), size); |
| 1337 | 1312 |
| 1338 // Set the forwarding address. | 1313 // Set the forwarding address. |
| 1339 source->set_map_word(MapWord::FromForwardingAddress(target)); | 1314 source->set_map_word(MapWord::FromForwardingAddress(target)); |
| 1340 | 1315 |
| 1341 if (logging_and_profiling_mode == LOGGING_AND_PROFILING_ENABLED) { | |
| 1342 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) | 1316 #if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING) |
| 1343 // Update NewSpace stats if necessary. | 1317 // Update NewSpace stats if necessary. |
| 1344 RecordCopiedObject(heap, target); | 1318 RecordCopiedObject(heap, target); |
| 1345 #endif | 1319 #endif |
| 1346 HEAP_PROFILE(heap, ObjectMoveEvent(source->address(), target->address())); | 1320 HEAP_PROFILE(heap, ObjectMoveEvent(source->address(), target->address())); |
| 1347 #if defined(ENABLE_LOGGING_AND_PROFILING) | 1321 #if defined(ENABLE_LOGGING_AND_PROFILING) |
| 1348 Isolate* isolate = heap->isolate(); | 1322 Isolate* isolate = heap->isolate(); |
| 1349 if (isolate->logger()->is_logging() || | 1323 if (isolate->logger()->is_logging() || |
| 1350 isolate->cpu_profiler()->is_profiling()) { | 1324 isolate->cpu_profiler()->is_profiling()) { |
| 1351 if (target->IsSharedFunctionInfo()) { | 1325 if (target->IsSharedFunctionInfo()) { |
| 1352 PROFILE(isolate, SharedFunctionInfoMoveEvent( | 1326 PROFILE(isolate, SharedFunctionInfoMoveEvent( |
| 1353 source->address(), target->address())); | 1327 source->address(), target->address())); |
| 1354 } | |
| 1355 } | 1328 } |
| 1329 } |
| 1356 #endif | 1330 #endif |
| 1357 } | |
| 1358 | |
| 1359 return target; | 1331 return target; |
| 1360 } | 1332 } |
| 1361 | 1333 |
| 1362 | 1334 |
| 1363 template<ObjectContents object_contents, SizeRestriction size_restriction> | 1335 template<ObjectContents object_contents, SizeRestriction size_restriction> |
| 1364 static inline void EvacuateObject(Map* map, | 1336 static inline void EvacuateObject(Map* map, |
| 1365 HeapObject** slot, | 1337 HeapObject** slot, |
| 1366 HeapObject* object, | 1338 HeapObject* object, |
| 1367 int object_size) { | 1339 int object_size) { |
| 1368 ASSERT((size_restriction != SMALL) || | 1340 ASSERT((size_restriction != SMALL) || |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 | 1436 |
| 1465 MapWord first_word = first->map_word(); | 1437 MapWord first_word = first->map_word(); |
| 1466 if (first_word.IsForwardingAddress()) { | 1438 if (first_word.IsForwardingAddress()) { |
| 1467 HeapObject* target = first_word.ToForwardingAddress(); | 1439 HeapObject* target = first_word.ToForwardingAddress(); |
| 1468 | 1440 |
| 1469 *slot = target; | 1441 *slot = target; |
| 1470 object->set_map_word(MapWord::FromForwardingAddress(target)); | 1442 object->set_map_word(MapWord::FromForwardingAddress(target)); |
| 1471 return; | 1443 return; |
| 1472 } | 1444 } |
| 1473 | 1445 |
| 1474 DoScavengeObject(first->map(), slot, first); | 1446 Scavenge(first->map(), slot, first); |
| 1475 object->set_map_word(MapWord::FromForwardingAddress(*slot)); | 1447 object->set_map_word(MapWord::FromForwardingAddress(*slot)); |
| 1476 return; | 1448 return; |
| 1477 } | 1449 } |
| 1478 | 1450 |
| 1479 int object_size = ConsString::kSize; | 1451 int object_size = ConsString::kSize; |
| 1480 EvacuateObject<POINTER_OBJECT, SMALL>(map, slot, object, object_size); | 1452 EvacuateObject<POINTER_OBJECT, SMALL>(map, slot, object, object_size); |
| 1481 } | 1453 } |
| 1482 | 1454 |
| 1483 template<ObjectContents object_contents> | 1455 template<ObjectContents object_contents> |
| 1484 class ObjectEvacuationStrategy { | 1456 class ObjectEvacuationStrategy { |
| 1485 public: | 1457 public: |
| 1486 template<int object_size> | 1458 template<int object_size> |
| 1487 static inline void VisitSpecialized(Map* map, | 1459 static inline void VisitSpecialized(Map* map, |
| 1488 HeapObject** slot, | 1460 HeapObject** slot, |
| 1489 HeapObject* object) { | 1461 HeapObject* object) { |
| 1490 EvacuateObject<object_contents, SMALL>(map, slot, object, object_size); | 1462 EvacuateObject<object_contents, SMALL>(map, slot, object, object_size); |
| 1491 } | 1463 } |
| 1492 | 1464 |
| 1493 static inline void Visit(Map* map, | 1465 static inline void Visit(Map* map, |
| 1494 HeapObject** slot, | 1466 HeapObject** slot, |
| 1495 HeapObject* object) { | 1467 HeapObject* object) { |
| 1496 int object_size = map->instance_size(); | 1468 int object_size = map->instance_size(); |
| 1497 EvacuateObject<object_contents, SMALL>(map, slot, object, object_size); | 1469 EvacuateObject<object_contents, SMALL>(map, slot, object, object_size); |
| 1498 } | 1470 } |
| 1499 }; | 1471 }; |
| 1500 | 1472 |
| 1501 static VisitorDispatchTable<ScavengingCallback> table_; | 1473 typedef void (*Callback)(Map* map, HeapObject** slot, HeapObject* object); |
| 1474 |
| 1475 static VisitorDispatchTable<Callback> table_; |
| 1502 }; | 1476 }; |
| 1503 | 1477 |
| 1504 | 1478 |
| 1505 template<LoggingAndProfiling logging_and_profiling_mode> | 1479 VisitorDispatchTable<ScavengingVisitor::Callback> ScavengingVisitor::table_; |
| 1506 VisitorDispatchTable<ScavengingCallback> | |
| 1507 ScavengingVisitor<logging_and_profiling_mode>::table_; | |
| 1508 | |
| 1509 | |
| 1510 static void InitializeScavengingVisitorsTables() { | |
| 1511 ScavengingVisitor<LOGGING_AND_PROFILING_DISABLED>::Initialize(); | |
| 1512 ScavengingVisitor<LOGGING_AND_PROFILING_ENABLED>::Initialize(); | |
| 1513 scavenging_visitors_table_.CopyFrom( | |
| 1514 ScavengingVisitor<LOGGING_AND_PROFILING_DISABLED>::GetTable()); | |
| 1515 scavenging_visitors_table_mode_ = LOGGING_AND_PROFILING_DISABLED; | |
| 1516 } | |
| 1517 | |
| 1518 | |
| 1519 void Heap::SwitchScavengingVisitorsTableIfProfilingWasEnabled() { | |
| 1520 if (scavenging_visitors_table_mode_ == LOGGING_AND_PROFILING_ENABLED) { | |
| 1521 // Table was already updated by some isolate. | |
| 1522 return; | |
| 1523 } | |
| 1524 | |
| 1525 if (isolate()->logger()->is_logging() || | |
| 1526 isolate()->cpu_profiler()->is_profiling() || | |
| 1527 (isolate()->heap_profiler() != NULL && | |
| 1528 isolate()->heap_profiler()->is_profiling())) { | |
| 1529 // If one of the isolates is doing scavenge at this moment of time | |
| 1530 // it might see this table in an inconsitent state when | |
| 1531 // some of the callbacks point to | |
| 1532 // ScavengingVisitor<LOGGING_AND_PROFILING_ENABLED> and others | |
| 1533 // to ScavengingVisitor<LOGGING_AND_PROFILING_DISABLED>. | |
| 1534 // However this does not lead to any bugs as such isolate does not have | |
| 1535 // profiling enabled and any isolate with enabled profiling is guaranteed | |
| 1536 // to see the table in the consistent state. | |
| 1537 scavenging_visitors_table_.CopyFrom( | |
| 1538 ScavengingVisitor<LOGGING_AND_PROFILING_ENABLED>::GetTable()); | |
| 1539 | |
| 1540 // We use Release_Store to prevent reordering of this write before writes | |
| 1541 // to the table. | |
| 1542 Release_Store(&scavenging_visitors_table_mode_, | |
| 1543 LOGGING_AND_PROFILING_ENABLED); | |
| 1544 } | |
| 1545 } | |
| 1546 | 1480 |
| 1547 | 1481 |
| 1548 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { | 1482 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { |
| 1549 ASSERT(HEAP->InFromSpace(object)); | 1483 ASSERT(HEAP->InFromSpace(object)); |
| 1550 MapWord first_word = object->map_word(); | 1484 MapWord first_word = object->map_word(); |
| 1551 ASSERT(!first_word.IsForwardingAddress()); | 1485 ASSERT(!first_word.IsForwardingAddress()); |
| 1552 Map* map = first_word.ToMap(); | 1486 Map* map = first_word.ToMap(); |
| 1553 DoScavengeObject(map, p, object); | 1487 ScavengingVisitor::Scavenge(map, p, object); |
| 1554 } | 1488 } |
| 1555 | 1489 |
| 1556 | 1490 |
| 1557 MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type, | 1491 MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type, |
| 1558 int instance_size) { | 1492 int instance_size) { |
| 1559 Object* result; | 1493 Object* result; |
| 1560 { MaybeObject* maybe_result = AllocateRawMap(); | 1494 { MaybeObject* maybe_result = AllocateRawMap(); |
| 1561 if (!maybe_result->ToObject(&result)) return maybe_result; | 1495 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1562 } | 1496 } |
| 1563 | 1497 |
| (...skipping 3258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4822 // Configuration is based on the flags new-space-size (really the semispace | 4756 // Configuration is based on the flags new-space-size (really the semispace |
| 4823 // size) and old-space-size if set or the initial values of semispace_size_ | 4757 // size) and old-space-size if set or the initial values of semispace_size_ |
| 4824 // and old_generation_size_ otherwise. | 4758 // and old_generation_size_ otherwise. |
| 4825 if (!configured_) { | 4759 if (!configured_) { |
| 4826 if (!ConfigureHeapDefault()) return false; | 4760 if (!ConfigureHeapDefault()) return false; |
| 4827 } | 4761 } |
| 4828 | 4762 |
| 4829 gc_initializer_mutex->Lock(); | 4763 gc_initializer_mutex->Lock(); |
| 4830 static bool initialized_gc = false; | 4764 static bool initialized_gc = false; |
| 4831 if (!initialized_gc) { | 4765 if (!initialized_gc) { |
| 4832 initialized_gc = true; | 4766 initialized_gc = true; |
| 4833 InitializeScavengingVisitorsTables(); | 4767 ScavengingVisitor::Initialize(); |
| 4834 NewSpaceScavenger::Initialize(); | 4768 NewSpaceScavenger::Initialize(); |
| 4835 MarkCompactCollector::Initialize(); | 4769 MarkCompactCollector::Initialize(); |
| 4836 } | 4770 } |
| 4837 gc_initializer_mutex->Unlock(); | 4771 gc_initializer_mutex->Unlock(); |
| 4838 | 4772 |
| 4839 MarkMapPointersAsEncoded(false); | 4773 MarkMapPointersAsEncoded(false); |
| 4840 | 4774 |
| 4841 // Setup memory allocator and reserve a chunk of memory for new | 4775 // Setup memory allocator and reserve a chunk of memory for new |
| 4842 // space. The chunk is double the size of the requested reserved | 4776 // space. The chunk is double the size of the requested reserved |
| 4843 // new space size to ensure that we can find a pair of semispaces that | 4777 // new space size to ensure that we can find a pair of semispaces that |
| 4844 // are contiguous and aligned to their size. | 4778 // are contiguous and aligned to their size. |
| 4845 if (!isolate_->memory_allocator()->Setup(MaxReserved(), MaxExecutableSize())) | 4779 if (!isolate_->memory_allocator()->Setup(MaxReserved(), MaxExecutableSize())) |
| (...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5853 } | 5787 } |
| 5854 | 5788 |
| 5855 | 5789 |
| 5856 void ExternalStringTable::TearDown() { | 5790 void ExternalStringTable::TearDown() { |
| 5857 new_space_strings_.Free(); | 5791 new_space_strings_.Free(); |
| 5858 old_space_strings_.Free(); | 5792 old_space_strings_.Free(); |
| 5859 } | 5793 } |
| 5860 | 5794 |
| 5861 | 5795 |
| 5862 } } // namespace v8::internal | 5796 } } // namespace v8::internal |
| OLD | NEW |