libraries/v8/mark-compact.cc
// We scavange new space simultaneously with sweeping. This is done in two
// passes.
//
// The first pass migrates all alive objects from one semispace to another or
// promotes them to old space.  Forwarding address is written directly into
// first word of object without any encoding.  If object is dead we write
// NULL as a forwarding address.
//
// The second pass updates pointers to new space in all spaces.  It is possible
// to encounter pointers to dead new space objects during traversal of pointers
// to new space.  We should clear them to avoid encountering them during next
// pointer iteration.  This is an issue if the store buffer overflows and we
// have to scan the entire old space, including dead objects, looking for
// pointers to new space.
We scavange new space simultaneously with sweeping. This is done in two
passes.

The first pass migrates all alive objects from one semispace to another or
promotes them to old space.  Forwarding address is written directly into
first word of object without any encoding.  If object is dead we write
NULL as a forwarding address.

The second pass updates pointers to new space in all spaces.  It is possible
to encounter pointers to dead new space objects during traversal of pointers
to new space.  We should clear them to avoid encountering them during next
pointer iteration.  This is an issue if the store buffer overflows and we
have to scan the entire old space, including dead objects, looking for
pointers to new space.
We scavange new space simultaneously with sweeping . This is done in two passes . The first pass migrates all alive objects from one semispace to another or promotes them to old space . Forwarding address is written directly into first word of object without any encoding . If object is dead we write NULL as a forwarding address . The second pass updates pointers to new space in all spaces . It is possible to encounter pointers to dead new space objects during traversal of pointers to new space . We should clear them to avoid encountering them during next pointer iteration . This is an issue if the store buffer overflows and we have to scan the entire old space including dead objects looking for pointers to new space .
void MarkCompactCollector::MigrateObject(Address dst,
                                         Address src,
                                         int size,
                                         AllocationSpace dest) {
  HeapProfiler* heap_profiler = heap()->isolate()->heap_profiler();
  if (heap_profiler->is_profiling()) {
    heap_profiler->ObjectMoveEvent(src, dst, size);
  }
  ASSERT(heap()->AllowedToBeMigrated(HeapObject::FromAddress(src), dest));
  ASSERT(dest != LO_SPACE && size <= Page::kMaxNonCodeHeapObjectSize);
  if (dest == OLD_POINTER_SPACE) {
    Address src_slot = src;
    Address dst_slot = dst;
    ASSERT(IsAligned(size, kPointerSize));
    for (int remaining = size / kPointerSize; remaining > 0; remaining--) {
      Object* value = Memory::Object_at(src_slot);
      Memory::Object_at(dst_slot) = value;
      if (heap_->InNewSpace(value)) {
        heap_->store_buffer()->Mark(dst_slot);
      } else if (value->IsHeapObject() && IsOnEvacuationCandidate(value)) {
        SlotsBuffer::AddTo(&slots_buffer_allocator_,
                           &migration_slots_buffer_,
                           reinterpret_cast<Object**>(dst_slot),
                           SlotsBuffer::IGNORE_OVERFLOW);
      }
      src_slot += kPointerSize;
      dst_slot += kPointerSize;
    }
    if (compacting_ && HeapObject::FromAddress(dst)->IsJSFunction()) {
      Address code_entry_slot = dst + JSFunction::kCodeEntryOffset;
      Address code_entry = Memory::Address_at(code_entry_slot);
      if (Page::FromAddress(code_entry)->IsEvacuationCandidate()) {
        SlotsBuffer::AddTo(&slots_buffer_allocator_,
                           &migration_slots_buffer_,
                           SlotsBuffer::CODE_ENTRY_SLOT,
                           code_entry_slot,
                           SlotsBuffer::IGNORE_OVERFLOW);
      }
    }
  } else if (dest == CODE_SPACE) {
    PROFILE(isolate(), CodeMoveEvent(src, dst));
    heap()->MoveBlock(dst, src, size);
    SlotsBuffer::AddTo(&slots_buffer_allocator_,
                       &migration_slots_buffer_,
                       SlotsBuffer::RELOCATED_CODE_OBJECT,
                       dst,
                       SlotsBuffer::IGNORE_OVERFLOW);
    Code::cast(HeapObject::FromAddress(dst))->Relocate(dst - src);
  } else {
    ASSERT(dest == OLD_DATA_SPACE || dest == NEW_SPACE);
    heap()->MoveBlock(dst, src, size);
  }
  Memory::Address_at(src) = dst;
}
void MarkCompactCollector :: MigrateObject ( Address dst , Address src , int size , AllocationSpace dest ) { HeapProfiler * heap_profiler = heap ( ) -> isolate ( ) -> heap_profiler ( ) ; if ( heap_profiler -> is_profiling ( ) ) { heap_profiler -> ObjectMoveEvent ( src , dst , size ) ; } ASSERT ( heap ( ) -> AllowedToBeMigrated ( HeapObject :: FromAddress ( src ) , dest ) ) ; ASSERT ( dest != LO_SPACE && size <= Page :: kMaxNonCodeHeapObjectSize ) ; if ( dest == OLD_POINTER_SPACE ) { Address src_slot = src ; Address dst_slot = dst ; ASSERT ( IsAligned ( size , kPointerSize ) ) ; for ( int remaining = size / kPointerSize ; remaining > 0 ; remaining -- ) { Object * value = Memory :: Object_at ( src_slot ) ; Memory :: Object_at ( dst_slot ) = value ; if ( heap_ -> InNewSpace ( value ) ) { heap_ -> store_buffer ( ) -> Mark ( dst_slot ) ; } else if ( value -> IsHeapObject ( ) && IsOnEvacuationCandidate ( value ) ) { SlotsBuffer :: AddTo ( & slots_buffer_allocator_ , & migration_slots_buffer_ , reinterpret_cast < Object * * > ( dst_slot ) , SlotsBuffer :: IGNORE_OVERFLOW ) ; } src_slot += kPointerSize ; dst_slot += kPointerSize ; } if ( compacting_ && HeapObject :: FromAddress ( dst ) -> IsJSFunction ( ) ) { Address code_entry_slot = dst + JSFunction :: kCodeEntryOffset ; Address code_entry = Memory :: Address_at ( code_entry_slot ) ; if ( Page :: FromAddress ( code_entry ) -> IsEvacuationCandidate ( ) ) { SlotsBuffer :: AddTo ( & slots_buffer_allocator_ , & migration_slots_buffer_ , SlotsBuffer :: CODE_ENTRY_SLOT , code_entry_slot , SlotsBuffer :: IGNORE_OVERFLOW ) ; } } } else if ( dest == CODE_SPACE ) { PROFILE ( isolate ( ) , CodeMoveEvent ( src , dst ) ) ; heap ( ) -> MoveBlock ( dst , src , size ) ; SlotsBuffer :: AddTo ( & slots_buffer_allocator_ , & migration_slots_buffer_ , SlotsBuffer :: RELOCATED_CODE_OBJECT , dst , SlotsBuffer :: IGNORE_OVERFLOW ) ; Code :: cast ( HeapObject :: FromAddress ( dst ) ) -> Relocate ( dst - src ) ; } else { ASSERT ( dest == OLD_DATA_SPACE || dest == NEW_SPACE ) ; heap ( ) -> MoveBlock ( dst , src , size ) ; } Memory :: Address_at ( src ) = dst ; }
We scavange new space simultaneously with sweeping.
We scavange new space simultaneously with sweeping .