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