| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/heap/scavenger.h" | 5 #include "src/heap/scavenger.h" |
| 6 | 6 |
| 7 #include "src/contexts.h" | 7 #include "src/contexts.h" |
| 8 #include "src/heap/heap.h" | 8 #include "src/heap/heap.h" |
| 9 #include "src/heap/objects-visiting-inl.h" | 9 #include "src/heap/objects-visiting-inl.h" |
| 10 #include "src/heap/scavenger-inl.h" | 10 #include "src/heap/scavenger-inl.h" |
| 11 #include "src/isolate.h" | 11 #include "src/isolate.h" |
| 12 #include "src/log.h" | 12 #include "src/log.h" |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 | 16 |
| 17 enum LoggingAndProfiling { | 17 enum LoggingAndProfiling { |
| 18 LOGGING_AND_PROFILING_ENABLED, | 18 LOGGING_AND_PROFILING_ENABLED, |
| 19 LOGGING_AND_PROFILING_DISABLED | 19 LOGGING_AND_PROFILING_DISABLED |
| 20 }; | 20 }; |
| 21 | 21 |
| 22 | 22 |
| 23 enum MarksHandling { TRANSFER_MARKS, IGNORE_MARKS }; | 23 enum MarksHandling { TRANSFER_MARKS, IGNORE_MARKS }; |
| 24 | 24 |
| 25 template <MarksHandling marks_handling, PromotionMode promotion_mode, | 25 template <MarksHandling marks_handling, |
| 26 LoggingAndProfiling logging_and_profiling_mode> | 26 LoggingAndProfiling logging_and_profiling_mode> |
| 27 class ScavengingVisitor : public StaticVisitorBase { | 27 class ScavengingVisitor : public StaticVisitorBase { |
| 28 public: | 28 public: |
| 29 static void Initialize() { | 29 static void Initialize() { |
| 30 table_.Register(kVisitSeqOneByteString, &EvacuateSeqOneByteString); | 30 table_.Register(kVisitSeqOneByteString, &EvacuateSeqOneByteString); |
| 31 table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString); | 31 table_.Register(kVisitSeqTwoByteString, &EvacuateSeqTwoByteString); |
| 32 table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate); | 32 table_.Register(kVisitShortcutCandidate, &EvacuateShortcutCandidate); |
| 33 table_.Register(kVisitByteArray, &EvacuateByteArray); | 33 table_.Register(kVisitByteArray, &EvacuateByteArray); |
| 34 table_.Register(kVisitFixedArray, &EvacuateFixedArray); | 34 table_.Register(kVisitFixedArray, &EvacuateFixedArray); |
| 35 table_.Register(kVisitFixedDoubleArray, &EvacuateFixedDoubleArray); | 35 table_.Register(kVisitFixedDoubleArray, &EvacuateFixedDoubleArray); |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 return false; | 199 return false; |
| 200 } | 200 } |
| 201 | 201 |
| 202 template <ObjectContents object_contents, AllocationAlignment alignment> | 202 template <ObjectContents object_contents, AllocationAlignment alignment> |
| 203 static inline void EvacuateObject(Map* map, HeapObject** slot, | 203 static inline void EvacuateObject(Map* map, HeapObject** slot, |
| 204 HeapObject* object, int object_size) { | 204 HeapObject* object, int object_size) { |
| 205 SLOW_DCHECK(object_size <= Page::kAllocatableMemory); | 205 SLOW_DCHECK(object_size <= Page::kAllocatableMemory); |
| 206 SLOW_DCHECK(object->Size() == object_size); | 206 SLOW_DCHECK(object->Size() == object_size); |
| 207 Heap* heap = map->GetHeap(); | 207 Heap* heap = map->GetHeap(); |
| 208 | 208 |
| 209 if (!heap->ShouldBePromoted<promotion_mode>(object->address(), | 209 if (!heap->ShouldBePromoted(object->address(), object_size)) { |
| 210 object_size)) { | |
| 211 // A semi-space copy may fail due to fragmentation. In that case, we | 210 // A semi-space copy may fail due to fragmentation. In that case, we |
| 212 // try to promote the object. | 211 // try to promote the object. |
| 213 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) { | 212 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) { |
| 214 return; | 213 return; |
| 215 } | 214 } |
| 216 } | 215 } |
| 217 | 216 |
| 218 if (PromoteObject<object_contents, alignment>(map, slot, object, | 217 if (PromoteObject<object_contents, alignment>(map, slot, object, |
| 219 object_size)) { | 218 object_size)) { |
| 220 return; | 219 return; |
| 221 } | 220 } |
| 222 if (promotion_mode == PROMOTE_MARKED) { | 221 |
| 223 FatalProcessOutOfMemory("Scavenger: promoting marked\n"); | |
| 224 } | |
| 225 // If promotion failed, we try to copy the object to the other semi-space | 222 // If promotion failed, we try to copy the object to the other semi-space |
| 226 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return; | 223 if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) return; |
| 227 | 224 |
| 228 FatalProcessOutOfMemory("Scavenger: semi-space copy\n"); | 225 FatalProcessOutOfMemory("Scavenger: semi-space copy\n"); |
| 229 } | 226 } |
| 230 | 227 |
| 231 static inline void EvacuateJSFunction(Map* map, HeapObject** slot, | 228 static inline void EvacuateJSFunction(Map* map, HeapObject** slot, |
| 232 HeapObject* object) { | 229 HeapObject* object) { |
| 233 ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object); | 230 ObjectEvacuationStrategy<POINTER_OBJECT>::Visit(map, slot, object); |
| 234 | 231 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 static inline void Visit(Map* map, HeapObject** slot, HeapObject* object) { | 348 static inline void Visit(Map* map, HeapObject** slot, HeapObject* object) { |
| 352 int object_size = map->instance_size(); | 349 int object_size = map->instance_size(); |
| 353 EvacuateObject<object_contents, kWordAligned>(map, slot, object, | 350 EvacuateObject<object_contents, kWordAligned>(map, slot, object, |
| 354 object_size); | 351 object_size); |
| 355 } | 352 } |
| 356 }; | 353 }; |
| 357 | 354 |
| 358 static VisitorDispatchTable<ScavengingCallback> table_; | 355 static VisitorDispatchTable<ScavengingCallback> table_; |
| 359 }; | 356 }; |
| 360 | 357 |
| 361 template <MarksHandling marks_handling, PromotionMode promotion_mode, | 358 template <MarksHandling marks_handling, |
| 362 LoggingAndProfiling logging_and_profiling_mode> | 359 LoggingAndProfiling logging_and_profiling_mode> |
| 363 VisitorDispatchTable<ScavengingCallback> ScavengingVisitor< | 360 VisitorDispatchTable<ScavengingCallback> |
| 364 marks_handling, promotion_mode, logging_and_profiling_mode>::table_; | 361 ScavengingVisitor<marks_handling, logging_and_profiling_mode>::table_; |
| 365 | 362 |
| 366 // static | 363 // static |
| 367 void Scavenger::Initialize() { | 364 void Scavenger::Initialize() { |
| 368 ScavengingVisitor<TRANSFER_MARKS, PROMOTE_MARKED, | 365 ScavengingVisitor<TRANSFER_MARKS, |
| 369 LOGGING_AND_PROFILING_DISABLED>::Initialize(); | 366 LOGGING_AND_PROFILING_DISABLED>::Initialize(); |
| 370 ScavengingVisitor<IGNORE_MARKS, DEFAULT_PROMOTION, | 367 ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_DISABLED>::Initialize(); |
| 371 LOGGING_AND_PROFILING_DISABLED>::Initialize(); | 368 ScavengingVisitor<TRANSFER_MARKS, |
| 372 ScavengingVisitor<TRANSFER_MARKS, PROMOTE_MARKED, | |
| 373 LOGGING_AND_PROFILING_ENABLED>::Initialize(); | 369 LOGGING_AND_PROFILING_ENABLED>::Initialize(); |
| 374 ScavengingVisitor<IGNORE_MARKS, DEFAULT_PROMOTION, | 370 ScavengingVisitor<IGNORE_MARKS, LOGGING_AND_PROFILING_ENABLED>::Initialize(); |
| 375 LOGGING_AND_PROFILING_ENABLED>::Initialize(); | |
| 376 } | 371 } |
| 377 | 372 |
| 378 | 373 |
| 379 // static | 374 // static |
| 380 void Scavenger::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { | 375 void Scavenger::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { |
| 381 SLOW_DCHECK(object->GetIsolate()->heap()->InFromSpace(object)); | 376 SLOW_DCHECK(object->GetIsolate()->heap()->InFromSpace(object)); |
| 382 MapWord first_word = object->map_word(); | 377 MapWord first_word = object->map_word(); |
| 383 SLOW_DCHECK(!first_word.IsForwardingAddress()); | 378 SLOW_DCHECK(!first_word.IsForwardingAddress()); |
| 384 Map* map = first_word.ToMap(); | 379 Map* map = first_word.ToMap(); |
| 385 Scavenger* scavenger = map->GetHeap()->scavenge_collector_; | 380 Scavenger* scavenger = map->GetHeap()->scavenge_collector_; |
| 386 scavenger->scavenging_visitors_table_.GetVisitor(map)(map, p, object); | 381 scavenger->scavenging_visitors_table_.GetVisitor(map)(map, p, object); |
| 387 } | 382 } |
| 388 | 383 |
| 389 | 384 |
| 390 void Scavenger::SelectScavengingVisitorsTable() { | 385 void Scavenger::SelectScavengingVisitorsTable() { |
| 391 bool logging_and_profiling = | 386 bool logging_and_profiling = |
| 392 FLAG_verify_predictable || isolate()->logger()->is_logging() || | 387 FLAG_verify_predictable || isolate()->logger()->is_logging() || |
| 393 isolate()->is_profiling() || | 388 isolate()->is_profiling() || |
| 394 (isolate()->heap_profiler() != NULL && | 389 (isolate()->heap_profiler() != NULL && |
| 395 isolate()->heap_profiler()->is_tracking_object_moves()); | 390 isolate()->heap_profiler()->is_tracking_object_moves()); |
| 396 | 391 |
| 397 if (!heap()->incremental_marking()->IsMarking()) { | 392 if (!heap()->incremental_marking()->IsMarking()) { |
| 398 if (!logging_and_profiling) { | 393 if (!logging_and_profiling) { |
| 399 scavenging_visitors_table_.CopyFrom( | 394 scavenging_visitors_table_.CopyFrom( |
| 400 ScavengingVisitor<IGNORE_MARKS, DEFAULT_PROMOTION, | 395 ScavengingVisitor<IGNORE_MARKS, |
| 401 LOGGING_AND_PROFILING_DISABLED>::GetTable()); | 396 LOGGING_AND_PROFILING_DISABLED>::GetTable()); |
| 402 } else { | 397 } else { |
| 403 scavenging_visitors_table_.CopyFrom( | 398 scavenging_visitors_table_.CopyFrom( |
| 404 ScavengingVisitor<IGNORE_MARKS, DEFAULT_PROMOTION, | 399 ScavengingVisitor<IGNORE_MARKS, |
| 405 LOGGING_AND_PROFILING_ENABLED>::GetTable()); | 400 LOGGING_AND_PROFILING_ENABLED>::GetTable()); |
| 406 } | 401 } |
| 407 } else { | 402 } else { |
| 408 if (!logging_and_profiling) { | 403 if (!logging_and_profiling) { |
| 409 scavenging_visitors_table_.CopyFrom( | 404 scavenging_visitors_table_.CopyFrom( |
| 410 ScavengingVisitor<TRANSFER_MARKS, PROMOTE_MARKED, | 405 ScavengingVisitor<TRANSFER_MARKS, |
| 411 LOGGING_AND_PROFILING_DISABLED>::GetTable()); | 406 LOGGING_AND_PROFILING_DISABLED>::GetTable()); |
| 412 } else { | 407 } else { |
| 413 scavenging_visitors_table_.CopyFrom( | 408 scavenging_visitors_table_.CopyFrom( |
| 414 ScavengingVisitor<TRANSFER_MARKS, PROMOTE_MARKED, | 409 ScavengingVisitor<TRANSFER_MARKS, |
| 415 LOGGING_AND_PROFILING_ENABLED>::GetTable()); | 410 LOGGING_AND_PROFILING_ENABLED>::GetTable()); |
| 416 } | 411 } |
| 417 | 412 |
| 418 if (heap()->incremental_marking()->IsCompacting()) { | 413 if (heap()->incremental_marking()->IsCompacting()) { |
| 419 // When compacting forbid short-circuiting of cons-strings. | 414 // When compacting forbid short-circuiting of cons-strings. |
| 420 // Scavenging code relies on the fact that new space object | 415 // Scavenging code relies on the fact that new space object |
| 421 // can't be evacuated into evacuation candidate but | 416 // can't be evacuated into evacuation candidate but |
| 422 // short-circuiting violates this assumption. | 417 // short-circuiting violates this assumption. |
| 423 scavenging_visitors_table_.Register( | 418 scavenging_visitors_table_.Register( |
| 424 StaticVisitorBase::kVisitShortcutCandidate, | 419 StaticVisitorBase::kVisitShortcutCandidate, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 444 void ScavengeVisitor::ScavengePointer(Object** p) { | 439 void ScavengeVisitor::ScavengePointer(Object** p) { |
| 445 Object* object = *p; | 440 Object* object = *p; |
| 446 if (!heap_->InNewSpace(object)) return; | 441 if (!heap_->InNewSpace(object)) return; |
| 447 | 442 |
| 448 Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 443 Scavenger::ScavengeObject(reinterpret_cast<HeapObject**>(p), |
| 449 reinterpret_cast<HeapObject*>(object)); | 444 reinterpret_cast<HeapObject*>(object)); |
| 450 } | 445 } |
| 451 | 446 |
| 452 } // namespace internal | 447 } // namespace internal |
| 453 } // namespace v8 | 448 } // namespace v8 |
| OLD | NEW |