LCOV - code coverage report
Current view: top level - src/heap - mark-compact-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 182 190 95.8 %
Date: 2019-01-20 Functions: 12 12 100.0 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_HEAP_MARK_COMPACT_INL_H_
       6             : #define V8_HEAP_MARK_COMPACT_INL_H_
       7             : 
       8             : #include "src/assembler-inl.h"
       9             : #include "src/base/bits.h"
      10             : #include "src/heap/mark-compact.h"
      11             : #include "src/heap/objects-visiting-inl.h"
      12             : #include "src/heap/remembered-set.h"
      13             : #include "src/objects/js-collection-inl.h"
      14             : #include "src/objects/js-weak-refs-inl.h"
      15             : #include "src/objects/slots-inl.h"
      16             : #include "src/transitions.h"
      17             : 
      18             : namespace v8 {
      19             : namespace internal {
      20             : 
      21             : template <typename ConcreteState, AccessMode access_mode>
      22             : bool MarkingStateBase<ConcreteState, access_mode>::GreyToBlack(HeapObject obj) {
      23   769609469 :   MemoryChunk* p = MemoryChunk::FromHeapObject(obj);
      24   769831999 :   MarkBit markbit = MarkBitFrom(p, obj->address());
      25   777633672 :   if (!Marking::GreyToBlack<access_mode>(markbit)) return false;
      26   747938608 :   static_cast<ConcreteState*>(this)->IncrementLiveBytes(p, obj->Size());
      27             :   return true;
      28             : }
      29             : 
      30             : template <typename ConcreteState, AccessMode access_mode>
      31             : bool MarkingStateBase<ConcreteState, access_mode>::WhiteToGrey(HeapObject obj) {
      32             :   return Marking::WhiteToGrey<access_mode>(MarkBitFrom(obj));
      33             : }
      34             : 
      35             : template <typename ConcreteState, AccessMode access_mode>
      36             : bool MarkingStateBase<ConcreteState, access_mode>::WhiteToBlack(
      37             :     HeapObject obj) {
      38     3693496 :   return WhiteToGrey(obj) && GreyToBlack(obj);
      39             : }
      40             : 
      41             : template <FixedArrayVisitationMode fixed_array_mode,
      42             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
      43             : MarkingVisitor<fixed_array_mode, retaining_path_mode,
      44    83597451 :                MarkingState>::MarkingVisitor(MarkCompactCollector* collector,
      45             :                                              MarkingState* marking_state)
      46    83597460 :     : heap_(collector->heap()),
      47             :       collector_(collector),
      48             :       marking_state_(marking_state),
      49   250792363 :       mark_compact_epoch_(collector->epoch()) {}
      50             : 
      51             : template <FixedArrayVisitationMode fixed_array_mode,
      52             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
      53             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
      54             :                    MarkingState>::VisitBytecodeArray(Map map,
      55             :                                                      BytecodeArray array) {
      56     1789328 :   int size = BytecodeArray::BodyDescriptor::SizeOf(map, array);
      57     1789328 :   BytecodeArray::BodyDescriptor::IterateBody(map, array, size, this);
      58             : 
      59     1789328 :   if (!heap_->is_current_gc_forced()) {
      60     1674246 :     array->MakeOlder();
      61             :   }
      62             :   return size;
      63             : }
      64             : 
      65             : template <FixedArrayVisitationMode fixed_array_mode,
      66             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
      67             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
      68             :                    MarkingState>::VisitDescriptorArray(Map map,
      69             :                                                        DescriptorArray array) {
      70     4585141 :   int size = DescriptorArray::BodyDescriptor::SizeOf(map, array);
      71             :   VisitPointers(array, array->GetFirstPointerSlot(),
      72     4585140 :                 array->GetDescriptorSlot(0));
      73     4585140 :   VisitDescriptors(array, array->number_of_descriptors());
      74             :   return size;
      75             : }
      76             : 
      77             : template <FixedArrayVisitationMode fixed_array_mode,
      78             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
      79             : int MarkingVisitor<fixed_array_mode, retaining_path_mode, MarkingState>::
      80             :     VisitSharedFunctionInfo(Map map, SharedFunctionInfo shared_info) {
      81    19495519 :   int size = SharedFunctionInfo::BodyDescriptor::SizeOf(map, shared_info);
      82    19495519 :   SharedFunctionInfo::BodyDescriptor::IterateBody(map, shared_info, size, this);
      83             : 
      84             :   // If the SharedFunctionInfo has old bytecode, mark it as flushable,
      85             :   // otherwise visit the function data field strongly.
      86    19495519 :   if (shared_info->ShouldFlushBytecode()) {
      87         116 :     collector_->AddBytecodeFlushingCandidate(shared_info);
      88             :   } else {
      89             :     VisitPointer(shared_info,
      90             :                  HeapObject::RawField(shared_info,
      91    19495403 :                                       SharedFunctionInfo::kFunctionDataOffset));
      92             :   }
      93             :   return size;
      94             : }
      95             : 
      96             : template <FixedArrayVisitationMode fixed_array_mode,
      97             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
      98             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
      99             :                    MarkingState>::VisitFixedArray(Map map, FixedArray object) {
     100             :   return (fixed_array_mode == FixedArrayVisitationMode::kRegular)
     101             :              ? Parent::VisitFixedArray(map, object)
     102             :              : VisitFixedArrayIncremental(map, object);
     103             : }
     104             : 
     105             : template <FixedArrayVisitationMode fixed_array_mode,
     106             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     107             : template <typename T>
     108             : V8_INLINE int
     109             : MarkingVisitor<fixed_array_mode, retaining_path_mode,
     110             :                MarkingState>::VisitEmbedderTracingSubclass(Map map, T object) {
     111      223634 :   if (heap_->local_embedder_heap_tracer()->InUse()) {
     112          30 :     marking_worklist()->embedder()->Push(MarkCompactCollectorBase::kMainThread,
     113             :                                          object);
     114             :   }
     115      223634 :   int size = T::BodyDescriptor::SizeOf(map, object);
     116      223634 :   T::BodyDescriptor::IterateBody(map, object, size, this);
     117             :   return size;
     118             : }
     119             : 
     120             : template <FixedArrayVisitationMode fixed_array_mode,
     121             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     122             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
     123             :                    MarkingState>::VisitJSApiObject(Map map, JSObject object) {
     124             :   return VisitEmbedderTracingSubclass(map, object);
     125             : }
     126             : 
     127             : template <FixedArrayVisitationMode fixed_array_mode,
     128             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     129             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
     130             :                    MarkingState>::VisitJSArrayBuffer(Map map,
     131             :                                                      JSArrayBuffer object) {
     132             :   return VisitEmbedderTracingSubclass(map, object);
     133             : }
     134             : 
     135             : template <FixedArrayVisitationMode fixed_array_mode,
     136             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     137             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
     138             :                    MarkingState>::VisitJSDataView(Map map, JSDataView object) {
     139             :   return VisitEmbedderTracingSubclass(map, object);
     140             : }
     141             : 
     142             : template <FixedArrayVisitationMode fixed_array_mode,
     143             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     144             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
     145             :                    MarkingState>::VisitJSTypedArray(Map map,
     146             :                                                     JSTypedArray object) {
     147             :   return VisitEmbedderTracingSubclass(map, object);
     148             : }
     149             : 
     150             : template <FixedArrayVisitationMode fixed_array_mode,
     151             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     152             : int MarkingVisitor<fixed_array_mode, retaining_path_mode, MarkingState>::
     153        5021 :     VisitEphemeronHashTable(Map map, EphemeronHashTable table) {
     154       16219 :   collector_->AddEphemeronHashTable(table);
     155             : 
     156       70172 :   for (int i = 0; i < table->Capacity(); i++) {
     157             :     ObjectSlot key_slot =
     158       70172 :         table->RawFieldOfElementAt(EphemeronHashTable::EntryToIndex(i));
     159       70172 :     HeapObject key = HeapObject::cast(table->KeyAt(i));
     160             :     collector_->RecordSlot(table, key_slot, key);
     161             : 
     162             :     ObjectSlot value_slot =
     163       70172 :         table->RawFieldOfElementAt(EphemeronHashTable::EntryToValueIndex(i));
     164             : 
     165       75084 :     if (marking_state()->IsBlackOrGrey(key)) {
     166             :       VisitPointer(table, value_slot);
     167             : 
     168             :     } else {
     169         506 :       Object value_obj = *value_slot;
     170             : 
     171        1012 :       if (value_obj->IsHeapObject()) {
     172             :         HeapObject value = HeapObject::cast(value_obj);
     173             :         collector_->RecordSlot(table, value_slot, value);
     174             : 
     175             :         // Revisit ephemerons with both key and value unreachable at end
     176             :         // of concurrent marking cycle.
     177         237 :         if (marking_state()->IsWhite(value)) {
     178          85 :           collector_->AddEphemeron(key, value);
     179             :         }
     180             :       }
     181             :     }
     182             :   }
     183             : 
     184       16219 :   return table->SizeFromMap(map);
     185             : }
     186             : 
     187             : template <FixedArrayVisitationMode fixed_array_mode,
     188             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     189             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
     190             :                    MarkingState>::VisitMap(Map meta_map, Map map) {
     191     2127795 :   int size = Map::BodyDescriptor::SizeOf(meta_map, map);
     192    11632700 :   if (map->CanTransition()) {
     193             :     // Maps that can transition share their descriptor arrays and require
     194             :     // special visiting logic to avoid memory leaks.
     195             :     // Since descriptor arrays are potentially shared, ensure that only the
     196             :     // descriptors that belong to this map are marked. The first time a
     197             :     // non-empty descriptor array is marked, its header is also visited. The
     198             :     // slot holding the descriptor array will be implicitly recorded when the
     199             :     // pointer fields of this map are visited.
     200    11551351 :     DescriptorArray descriptors = map->instance_descriptors();
     201             :     MarkDescriptorArrayBlack(map, descriptors);
     202    11551356 :     int number_of_own_descriptors = map->NumberOfOwnDescriptors();
     203    11551355 :     if (number_of_own_descriptors) {
     204             :       DCHECK_LE(number_of_own_descriptors,
     205             :                 descriptors->number_of_descriptors());
     206             :       VisitDescriptors(descriptors, number_of_own_descriptors);
     207             :     }
     208             :     // Mark the pointer fields of the Map. Since the transitions array has
     209             :     // been marked already, it is fine that one of these fields contains a
     210             :     // pointer to it.
     211             :   }
     212    11632704 :   Map::BodyDescriptor::IterateBody(meta_map, map, size, this);
     213             :   return size;
     214             : }
     215             : 
     216             : template <FixedArrayVisitationMode fixed_array_mode,
     217             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     218             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
     219             :                    MarkingState>::VisitTransitionArray(Map map,
     220             :                                                        TransitionArray array) {
     221      258785 :   int size = TransitionArray::BodyDescriptor::SizeOf(map, array);
     222      258785 :   TransitionArray::BodyDescriptor::IterateBody(map, array, size, this);
     223      258785 :   collector_->AddTransitionArray(array);
     224             :   return size;
     225             : }
     226             : 
     227             : template <FixedArrayVisitationMode fixed_array_mode,
     228             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     229             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
     230             :                    MarkingState>::VisitJSWeakRef(Map map, JSWeakRef weak_ref) {
     231         314 :   if (weak_ref->target()->IsHeapObject()) {
     232         157 :     HeapObject target = HeapObject::cast(weak_ref->target());
     233         294 :     if (marking_state()->IsBlackOrGrey(target)) {
     234             :       // Record the slot inside the JSWeakRef, since the IterateBody below
     235             :       // won't visit it.
     236             :       ObjectSlot slot =
     237          62 :           HeapObject::RawField(weak_ref, JSWeakCell::kTargetOffset);
     238             :       collector_->RecordSlot(weak_ref, slot, target);
     239             :     } else {
     240             :       // JSWeakRef points to a potentially dead object. We have to process
     241             :       // them when we know the liveness of the whole transitive closure.
     242          95 :       collector_->AddWeakRef(weak_ref);
     243             :     }
     244             :   }
     245         157 :   int size = JSWeakRef::BodyDescriptor::SizeOf(map, weak_ref);
     246         157 :   JSWeakRef::BodyDescriptor::IterateBody(map, weak_ref, size, this);
     247             :   return size;
     248             : }
     249             : 
     250             : template <FixedArrayVisitationMode fixed_array_mode,
     251             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     252             : int MarkingVisitor<fixed_array_mode, retaining_path_mode,
     253             :                    MarkingState>::VisitJSWeakCell(Map map,
     254             :                                                   JSWeakCell weak_cell) {
     255         336 :   if (weak_cell->target()->IsHeapObject()) {
     256         168 :     HeapObject target = HeapObject::cast(weak_cell->target());
     257         336 :     if (marking_state()->IsBlackOrGrey(target)) {
     258             :       // Record the slot inside the JSWeakCell, since the IterateBody below
     259             :       // won't visit it.
     260             :       ObjectSlot slot =
     261          52 :           HeapObject::RawField(weak_cell, JSWeakCell::kTargetOffset);
     262             :       collector_->RecordSlot(weak_cell, slot, target);
     263             :     } else {
     264             :       // JSWeakCell points to a potentially dead object. We have to process
     265             :       // them when we know the liveness of the whole transitive closure.
     266         116 :       collector_->AddWeakCell(weak_cell);
     267             :     }
     268             :   }
     269         168 :   int size = JSWeakCell::BodyDescriptor::SizeOf(map, weak_cell);
     270         168 :   JSWeakCell::BodyDescriptor::IterateBody(map, weak_cell, size, this);
     271             :   return size;
     272             : }
     273             : 
     274             : // class template arguments
     275             : template <FixedArrayVisitationMode fixed_array_mode,
     276             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     277             : // method template arguments
     278             : template <typename TSlot>
     279             : void MarkingVisitor<fixed_array_mode, retaining_path_mode,
     280             :                     MarkingState>::VisitPointerImpl(HeapObject host,
     281    25966351 :                                                     TSlot slot) {
     282             :   static_assert(std::is_same<TSlot, ObjectSlot>::value ||
     283             :                     std::is_same<TSlot, MaybeObjectSlot>::value,
     284             :                 "Only ObjectSlot and MaybeObjectSlot are expected here");
     285  3286843661 :   typename TSlot::TObject object = *slot;
     286  3286843579 :   HeapObject target_object;
     287  3286843579 :   if (object.GetHeapObjectIfStrong(&target_object)) {
     288  5988564245 :     collector_->RecordSlot(host, HeapObjectSlot(slot), target_object);
     289             :     MarkObject(host, target_object);
     290   141828675 :   } else if (TSlot::kCanBeWeak && object.GetHeapObjectIfWeak(&target_object)) {
     291    59891743 :     if (marking_state()->IsBlackOrGrey(target_object)) {
     292             :       // Weak references with live values are directly processed here to reduce
     293             :       // the processing time of weak cells during the main GC pause.
     294    46810825 :       collector_->RecordSlot(host, HeapObjectSlot(slot), target_object);
     295             :     } else {
     296             :       // If we do not know about liveness of values of weak cells, we have to
     297             :       // process them when we know the liveness of the whole transitive
     298             :       // closure.
     299    10519980 :       collector_->AddWeakReference(host, HeapObjectSlot(slot));
     300             :     }
     301             :   }
     302             : }
     303             : 
     304             : // class template arguments
     305             : template <FixedArrayVisitationMode fixed_array_mode,
     306             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     307             : // method template arguments
     308             : template <typename TSlot>
     309             : void MarkingVisitor<fixed_array_mode, retaining_path_mode,
     310             :                     MarkingState>::VisitPointersImpl(HeapObject host,
     311             :                                                      TSlot start, TSlot end) {
     312  3454448747 :   for (TSlot p = start; p < end; ++p) {
     313             :     VisitPointer(host, p);
     314             :   }
     315             : }
     316             : 
     317             : template <FixedArrayVisitationMode fixed_array_mode,
     318             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     319     2451291 : void MarkingVisitor<fixed_array_mode, retaining_path_mode,
     320             :                     MarkingState>::VisitEmbeddedPointer(Code host,
     321     4834599 :                                                         RelocInfo* rinfo) {
     322             :   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
     323             :   HeapObject object = HeapObject::cast(rinfo->target_object());
     324     2451291 :   collector_->RecordRelocSlot(host, rinfo, object);
     325     4834599 :   if (!marking_state()->IsBlackOrGrey(object)) {
     326      228919 :     if (host->IsWeakObject(object)) {
     327       68694 :       collector_->AddWeakObjectInCode(object, host);
     328             :     } else {
     329             :       MarkObject(host, object);
     330             :     }
     331             :   }
     332     2451291 : }
     333             : 
     334             : template <FixedArrayVisitationMode fixed_array_mode,
     335             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     336       47180 : void MarkingVisitor<fixed_array_mode, retaining_path_mode,
     337             :                     MarkingState>::VisitCodeTarget(Code host,
     338       47180 :                                                    RelocInfo* rinfo) {
     339             :   DCHECK(RelocInfo::IsCodeTargetMode(rinfo->rmode()));
     340       47180 :   Code target = Code::GetCodeFromTargetAddress(rinfo->target_address());
     341       47180 :   collector_->RecordRelocSlot(host, rinfo, target);
     342             :   MarkObject(host, target);
     343       47180 : }
     344             : 
     345             : template <FixedArrayVisitationMode fixed_array_mode,
     346             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     347             : void MarkingVisitor<fixed_array_mode, retaining_path_mode, MarkingState>::
     348    12678604 :     MarkDescriptorArrayBlack(HeapObject host, DescriptorArray descriptors) {
     349             :   // Note that WhiteToBlack is not sufficient here because it fails if the
     350             :   // descriptor array is grey. So we need to do two steps: WhiteToGrey and
     351             :   // GreyToBlack. Alternatively, we could check WhiteToGrey || WhiteToBlack.
     352    12678604 :   if (marking_state()->WhiteToGrey(descriptors)) {
     353     3974663 :     if (retaining_path_mode == TraceRetainingPathMode::kEnabled &&
     354     3974663 :         V8_UNLIKELY(FLAG_track_retaining_path)) {
     355           0 :       heap_->AddRetainer(host, descriptors);
     356             :     }
     357             :   }
     358    21367715 :   if (marking_state()->GreyToBlack(descriptors)) {
     359             :     VisitPointers(descriptors, descriptors->GetFirstPointerSlot(),
     360     7106981 :                   descriptors->GetDescriptorSlot(0));
     361             :   }
     362             :   DCHECK(marking_state()->IsBlack(descriptors));
     363             : }
     364             : 
     365             : template <FixedArrayVisitationMode fixed_array_mode,
     366             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     367             : void MarkingVisitor<fixed_array_mode, retaining_path_mode,
     368             :                     MarkingState>::MarkObject(HeapObject host,
     369  2536371899 :                                               HeapObject object) {
     370  5392675645 :   if (marking_state()->WhiteToGrey(object)) {
     371   138186143 :     marking_worklist()->Push(object);
     372   112166501 :     if (retaining_path_mode == TraceRetainingPathMode::kEnabled &&
     373   112166501 :         V8_UNLIKELY(FLAG_track_retaining_path)) {
     374           0 :       heap_->AddRetainer(host, object);
     375             :     }
     376             :   }
     377             : }
     378             : 
     379             : template <FixedArrayVisitationMode fixed_array_mode,
     380             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     381             : int MarkingVisitor<fixed_array_mode, retaining_path_mode, MarkingState>::
     382       49237 :     VisitFixedArrayIncremental(Map map, FixedArray object) {
     383     2400799 :   MemoryChunk* chunk = MemoryChunk::FromHeapObject(object);
     384     2400799 :   int size = FixedArray::BodyDescriptor::SizeOf(map, object);
     385     2400799 :   if (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR)) {
     386             :     DCHECK(FLAG_use_marking_progress_bar);
     387             :     DCHECK(heap_->IsLargeObject(object));
     388             :     int start =
     389       49489 :         Max(FixedArray::BodyDescriptor::kStartOffset, chunk->progress_bar());
     390       49489 :     int end = Min(size, start + kProgressBarScanningChunk);
     391       49489 :     if (start < end) {
     392             :       VisitPointers(object, HeapObject::RawField(object, start),
     393       49484 :                     HeapObject::RawField(object, end));
     394       49484 :       chunk->set_progress_bar(end);
     395       49484 :       if (end < size) {
     396             :         DCHECK(marking_state()->IsBlack(object));
     397             :         // The object can be pushed back onto the marking worklist only after
     398             :         // progress bar was updated.
     399       49237 :         marking_worklist()->Push(object);
     400       49237 :         heap_->incremental_marking()->NotifyIncompleteScanOfObject(
     401       49237 :             size - (end - start));
     402             :       }
     403             :     }
     404             :   } else {
     405     2351309 :     FixedArray::BodyDescriptor::IterateBody(map, object, size, this);
     406             :   }
     407             :   return size;
     408             : }
     409             : 
     410             : template <FixedArrayVisitationMode fixed_array_mode,
     411             :           TraceRetainingPathMode retaining_path_mode, typename MarkingState>
     412             : void MarkingVisitor<fixed_array_mode, retaining_path_mode, MarkingState>::
     413             :     VisitDescriptors(DescriptorArray descriptors,
     414             :                      int number_of_own_descriptors) {
     415             :   // Updating the number of marked descriptor is supported only for black
     416             :   // descriptor arrays.
     417             :   DCHECK(marking_state()->IsBlack(descriptors));
     418    12304905 :   int16_t new_marked = static_cast<int16_t>(number_of_own_descriptors);
     419             :   int16_t old_marked = descriptors->UpdateNumberOfMarkedDescriptors(
     420    16890044 :       mark_compact_epoch_, new_marked);
     421    16890047 :   if (old_marked < new_marked) {
     422             :     VisitPointers(descriptors,
     423    10491141 :                   MaybeObjectSlot(descriptors->GetDescriptorSlot(old_marked)),
     424    31473426 :                   MaybeObjectSlot(descriptors->GetDescriptorSlot(new_marked)));
     425             :   }
     426             : }
     427             : 
     428             : void MarkCompactCollector::MarkObject(HeapObject host, HeapObject obj) {
     429   157164705 :   if (marking_state()->WhiteToGrey(obj)) {
     430     3347847 :     marking_worklist()->Push(obj);
     431     3347847 :     if (V8_UNLIKELY(FLAG_track_retaining_path)) {
     432           0 :       heap_->AddRetainer(host, obj);
     433             :     }
     434             :   }
     435             : }
     436             : 
     437             : void MarkCompactCollector::MarkRootObject(Root root, HeapObject obj) {
     438   286485344 :   if (marking_state()->WhiteToGrey(obj)) {
     439   155258737 :     marking_worklist()->Push(obj);
     440   155258737 :     if (V8_UNLIKELY(FLAG_track_retaining_path)) {
     441           0 :       heap_->AddRetainingRoot(root, obj);
     442             :     }
     443             :   }
     444             : }
     445             : 
     446             : #ifdef ENABLE_MINOR_MC
     447             : 
     448             : void MinorMarkCompactCollector::MarkRootObject(HeapObject obj) {
     449           0 :   if (Heap::InNewSpace(obj) && non_atomic_marking_state_.WhiteToGrey(obj)) {
     450           0 :     worklist_->Push(kMainThread, obj);
     451             :   }
     452             : }
     453             : 
     454             : #endif
     455             : 
     456             : void MarkCompactCollector::MarkExternallyReferencedObject(HeapObject obj) {
     457           5 :   if (marking_state()->WhiteToGrey(obj)) {
     458           5 :     marking_worklist()->Push(obj);
     459           5 :     if (V8_UNLIKELY(FLAG_track_retaining_path)) {
     460           0 :       heap_->AddRetainingRoot(Root::kWrapperTracing, obj);
     461             :     }
     462             :   }
     463             : }
     464             : 
     465             : void MarkCompactCollector::RecordSlot(HeapObject object, ObjectSlot slot,
     466             :                                       HeapObject target) {
     467  1159265884 :   RecordSlot(object, HeapObjectSlot(slot), target);
     468             : }
     469             : 
     470             : void MarkCompactCollector::RecordSlot(HeapObject object, HeapObjectSlot slot,
     471             :                                       HeapObject target) {
     472  6474127078 :   Page* target_page = Page::FromHeapObject(target);
     473  6478029034 :   Page* source_page = Page::FromHeapObject(object);
     474  6527878253 :   if (target_page->IsEvacuationCandidate<AccessMode::ATOMIC>() &&
     475    48043940 :       !source_page->ShouldSkipEvacuationSlotRecording<AccessMode::ATOMIC>()) {
     476    34039179 :     RememberedSet<OLD_TO_OLD>::Insert(source_page, slot.address());
     477             :   }
     478             : }
     479             : 
     480      258785 : void MarkCompactCollector::AddTransitionArray(TransitionArray array) {
     481      292163 :   weak_objects_.transition_arrays.Push(kMainThread, array);
     482      258785 : }
     483             : 
     484         116 : void MarkCompactCollector::AddBytecodeFlushingCandidate(
     485             :     SharedFunctionInfo flush_candidate) {
     486         116 :   weak_objects_.bytecode_flushing_candidates.Push(kMainThread, flush_candidate);
     487         116 : }
     488             : 
     489             : template <LiveObjectIterationMode mode>
     490     4912044 : LiveObjectRange<mode>::iterator::iterator(MemoryChunk* chunk, Bitmap* bitmap,
     491             :                                           Address start)
     492             :     : chunk_(chunk),
     493             :       one_word_filler_map_(
     494             :           ReadOnlyRoots(chunk->heap()).one_pointer_filler_map()),
     495             :       two_word_filler_map_(
     496             :           ReadOnlyRoots(chunk->heap()).two_pointer_filler_map()),
     497             :       free_space_map_(ReadOnlyRoots(chunk->heap()).free_space_map()),
     498     7981882 :       it_(chunk, bitmap) {
     499             :   it_.Advance(Bitmap::IndexToCell(
     500     1227812 :       Bitmap::CellAlignIndex(chunk_->AddressToMarkbitIndex(start))));
     501     1227812 :   if (!it_.Done()) {
     502      614045 :     cell_base_ = it_.CurrentCellBase();
     503      614045 :     current_cell_ = *it_.CurrentCell();
     504      614045 :     AdvanceToNextValidObject();
     505             :   }
     506     1228233 : }
     507             : 
     508             : template <LiveObjectIterationMode mode>
     509             : typename LiveObjectRange<mode>::iterator& LiveObjectRange<mode>::iterator::
     510             : operator++() {
     511   740101629 :   AdvanceToNextValidObject();
     512             :   return *this;
     513             : }
     514             : 
     515             : template <LiveObjectIterationMode mode>
     516             : typename LiveObjectRange<mode>::iterator LiveObjectRange<mode>::iterator::
     517             : operator++(int) {
     518             :   iterator retval = *this;
     519             :   ++(*this);
     520             :   return retval;
     521             : }
     522             : 
     523             : template <LiveObjectIterationMode mode>
     524   737878382 : void LiveObjectRange<mode>::iterator::AdvanceToNextValidObject() {
     525  2037892776 :   while (!it_.Done()) {
     526     4717473 :     HeapObject object;
     527             :     int size = 0;
     528  1304127037 :     while (current_cell_ != 0) {
     529             :       uint32_t trailing_zeros = base::bits::CountTrailingZeros(current_cell_);
     530   737879328 :       Address addr = cell_base_ + trailing_zeros * kTaggedSize;
     531             : 
     532             :       // Clear the first bit of the found object..
     533   737879328 :       current_cell_ &= ~(1u << trailing_zeros);
     534             : 
     535             :       uint32_t second_bit_index = 0;
     536   737879328 :       if (trailing_zeros >= Bitmap::kBitIndexMask) {
     537             :         second_bit_index = 0x1;
     538             :         // The overlapping case; there has to exist a cell after the current
     539             :         // cell.
     540             :         // However, if there is a black area at the end of the page, and the
     541             :         // last word is a one word filler, we are not allowed to advance. In
     542             :         // that case we can return immediately.
     543  2182829839 :         if (!it_.Advance()) {
     544             :           DCHECK(HeapObject::FromAddress(addr)->map() == one_word_filler_map_);
     545           0 :           current_object_ = HeapObject();
     546             :           return;
     547             :         }
     548    23135434 :         cell_base_ = it_.CurrentCellBase();
     549    23135434 :         current_cell_ = *it_.CurrentCell();
     550             :       } else {
     551   719652278 :         second_bit_index = 1u << (trailing_zeros + 1);
     552             :       }
     553             : 
     554             :       Map map;
     555   742787712 :       if (current_cell_ & second_bit_index) {
     556             :         // We found a black object. If the black object is within a black area,
     557             :         // make sure that we skip all set bits in the black area until the
     558             :         // object ends.
     559   741393833 :         HeapObject black_object = HeapObject::FromAddress(addr);
     560             :         map = Map::cast(ObjectSlot(addr).Acquire_Load());
     561   736956850 :         size = black_object->SizeFromMap(map);
     562   733332933 :         Address end = addr + size - kTaggedSize;
     563             :         // One word filler objects do not borrow the second mark bit. We have
     564             :         // to jump over the advancing and clearing part.
     565             :         // Note that we know that we are at a one word filler when
     566             :         // object_start + object_size - kTaggedSize == object_start.
     567   733332933 :         if (addr != end) {
     568             :           DCHECK_EQ(chunk_, MemoryChunk::FromAddress(end));
     569   732637048 :           uint32_t end_mark_bit_index = chunk_->AddressToMarkbitIndex(end);
     570             :           unsigned int end_cell_index =
     571   732637048 :               end_mark_bit_index >> Bitmap::kBitsPerCellLog2;
     572             :           MarkBit::CellType end_index_mask =
     573   732637048 :               1u << Bitmap::IndexInCell(end_mark_bit_index);
     574   732637048 :           if (it_.Advance(end_cell_index)) {
     575   110122245 :             cell_base_ = it_.CurrentCellBase();
     576   110122245 :             current_cell_ = *it_.CurrentCell();
     577             :           }
     578             : 
     579             :           // Clear all bits in current_cell, including the end index.
     580   732637048 :           current_cell_ &= ~(end_index_mask + end_index_mask - 1);
     581             :         }
     582             : 
     583             :         if (mode == kBlackObjects || mode == kAllLiveObjects) {
     584   733332928 :           object = black_object;
     585             :         }
     586             :       } else if ((mode == kGreyObjects || mode == kAllLiveObjects)) {
     587             :         map = Map::cast(ObjectSlot(addr).Acquire_Load());
     588           5 :         object = HeapObject::FromAddress(addr);
     589           5 :         size = object->SizeFromMap(map);
     590             :       }
     591             : 
     592             :       // We found a live object.
     593   734788516 :       if (!object.is_null()) {
     594             :         // Do not use IsFiller() here. This may cause a data race for reading
     595             :         // out the instance type when a new map concurrently is written into
     596             :         // this object while iterating over the object.
     597   734033695 :         if (map == one_word_filler_map_ || map == two_word_filler_map_ ||
     598             :             map == free_space_map_) {
     599             :           // There are two reasons why we can get black or grey fillers:
     600             :           // 1) Black areas together with slack tracking may result in black one
     601             :           // word filler objects.
     602             :           // 2) Left trimming may leave black or grey fillers behind because we
     603             :           // do not clear the old location of the object start.
     604             :           // We filter these objects out in the iterator.
     605           6 :           object = HeapObject();
     606             :         } else {
     607             :           break;
     608             :         }
     609             :       }
     610             :     }
     611             : 
     612  1296308618 :     if (current_cell_ == 0) {
     613   621868034 :       if (it_.Advance()) {
     614   621208471 :         cell_base_ = it_.CurrentCellBase();
     615   621208471 :         current_cell_ = *it_.CurrentCell();
     616             :       }
     617             :     }
     618  1296308618 :     if (!object.is_null()) {
     619   734172606 :       current_object_ = object;
     620   734172606 :       current_size_ = size;
     621   734172606 :       return;
     622             :     }
     623             :   }
     624      614964 :   current_object_ = HeapObject();
     625             : }
     626             : 
     627             : template <LiveObjectIterationMode mode>
     628             : typename LiveObjectRange<mode>::iterator LiveObjectRange<mode>::begin() {
     629      614328 :   return iterator(chunk_, bitmap_, start_);
     630             : }
     631             : 
     632             : template <LiveObjectIterationMode mode>
     633             : typename LiveObjectRange<mode>::iterator LiveObjectRange<mode>::end() {
     634      614519 :   return iterator(chunk_, bitmap_, end_);
     635             : }
     636             : 
     637     1933605 : Isolate* MarkCompactCollectorBase::isolate() { return heap()->isolate(); }
     638             : 
     639             : }  // namespace internal
     640             : }  // namespace v8
     641             : 
     642             : #endif  // V8_HEAP_MARK_COMPACT_INL_H_

Generated by: LCOV version 1.10