// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/heap/incremental-marking.h"

#include "src/compilation-cache.h"
#include "src/conversions.h"
#include "src/heap/concurrent-marking.h"
#include "src/heap/embedder-tracing.h"
#include "src/heap/gc-idle-time-handler.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/heap-inl.h"
#include "src/heap/incremental-marking-inl.h"
#include "src/heap/mark-compact-inl.h"
#include "src/heap/object-stats.h"
#include "src/heap/objects-visiting-inl.h"
#include "src/heap/objects-visiting.h"
#include "src/heap/sweeper.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/slots-inl.h"
#include "src/tracing/trace-event.h"
#include "src/v8.h"
#include "src/visitors.h"
#include "src/vm-state-inl.h"

namespace v8 {
namespace internal {

using IncrementalMarkingMarkingVisitor =
    MarkingVisitor<FixedArrayVisitationMode::kIncremental,
                   TraceRetainingPathMode::kDisabled,
                   IncrementalMarking::MarkingState>;

void IncrementalMarking::Observer::Step(int bytes_allocated, Address addr,
                                        size_t size) {
  Heap* heap = incremental_marking_.heap();
  VMState<GC> state(heap->isolate());
  RuntimeCallTimerScope runtime_timer(
      heap->isolate(),
      RuntimeCallCounterId::kGC_Custom_IncrementalMarkingObserver);
  incremental_marking_.AdvanceIncrementalMarkingOnAllocation();
  if (incremental_marking_.black_allocation() && addr != kNullAddress) {
    // AdvanceIncrementalMarkingOnAllocation can start black allocation.
    // Ensure that the new object is marked black.
    HeapObject object = HeapObject::FromAddress(addr);
    if (incremental_marking_.marking_state()->IsWhite(object) &&
        !(Heap::InNewSpace(object) || heap->new_lo_space()->Contains(object))) {
      if (heap->IsLargeObject(object)) {
        incremental_marking_.marking_state()->WhiteToBlack(object);
      } else {
        Page::FromAddress(addr)->CreateBlackArea(addr, addr + size);
      }
    }
  }
}

IncrementalMarking::IncrementalMarking(
    Heap* heap, MarkCompactCollector::MarkingWorklist* marking_worklist,
    WeakObjects* weak_objects)
    : heap_(heap),
      marking_worklist_(marking_worklist),
      weak_objects_(weak_objects),
      initial_old_generation_size_(0),
      bytes_marked_ahead_of_schedule_(0),
      bytes_marked_concurrently_(0),
      unscanned_bytes_of_large_object_(0),
      is_compacting_(false),
      should_hurry_(false),
      was_activated_(false),
      black_allocation_(false),
      finalize_marking_completed_(false),
      trace_wrappers_toggle_(false),
      request_type_(NONE),
      new_generation_observer_(*this, kYoungGenerationAllocatedThreshold),
      old_generation_observer_(*this, kOldGenerationAllocatedThreshold) {
  DCHECK_NOT_NULL(marking_worklist_);
  SetState(STOPPED);
}

bool IncrementalMarking::BaseRecordWrite(HeapObject obj, Object value) {
  HeapObject value_heap_obj = HeapObject::cast(value);
  DCHECK(!marking_state()->IsImpossible(value_heap_obj));
  DCHECK(!marking_state()->IsImpossible(obj));
#ifdef V8_CONCURRENT_MARKING
  // The write barrier stub generated with V8_CONCURRENT_MARKING does not
  // check the color of the source object.
  const bool need_recording = true;
#else
  const bool need_recording = marking_state()->IsBlack(obj);
#endif

  if (need_recording && WhiteToGreyAndPush(value_heap_obj)) {
    RestartIfNotMarking();
  }
  return is_compacting_ && need_recording;
}

void IncrementalMarking::RecordWriteSlow(HeapObject obj, HeapObjectSlot slot,
                                         Object value) {
  if (BaseRecordWrite(obj, value) && slot.address() != kNullAddress) {
    // Object is not going to be rescanned we need to record the slot.
    heap_->mark_compact_collector()->RecordSlot(obj, slot,
                                                HeapObject::cast(value));
  }
}

int IncrementalMarking::RecordWriteFromCode(Address raw_obj,
                                            Address slot_address,
                                            Isolate* isolate) {
  HeapObject obj = HeapObject::cast(Object(raw_obj));
  MaybeObjectSlot slot(slot_address);
  isolate->heap()->incremental_marking()->RecordMaybeWeakWrite(obj, slot,
                                                               *slot);
  // Called by RecordWriteCodeStubAssembler, which doesnt accept void type
  return 0;
}

void IncrementalMarking::RecordWriteIntoCode(Code host, RelocInfo* rinfo,
                                             HeapObject value) {
  DCHECK(IsMarking());
  if (BaseRecordWrite(host, value)) {
    // Object is not going to be rescanned.  We need to record the slot.
    heap_->mark_compact_collector()->RecordRelocSlot(host, rinfo, value);
  }
}

bool IncrementalMarking::WhiteToGreyAndPush(HeapObject obj) {
  if (marking_state()->WhiteToGrey(obj)) {
    marking_worklist()->Push(obj);
    return true;
  }
  return false;
}

void IncrementalMarking::MarkBlackAndPush(HeapObject obj) {
  // Marking left-trimmable fixed array black is unsafe because left-trimming
  // re-pushes only grey arrays onto the marking worklist.
  DCHECK(!obj->IsFixedArray() && !obj->IsFixedDoubleArray());
  // Color the object black and push it into the bailout deque.
  marking_state()->WhiteToGrey(obj);
  if (marking_state()->GreyToBlack(obj)) {
    if (FLAG_concurrent_marking) {
      marking_worklist()->PushBailout(obj);
    } else {
      marking_worklist()->Push(obj);
    }
  }
}

void IncrementalMarking::NotifyLeftTrimming(HeapObject from, HeapObject to) {
  DCHECK(IsMarking());
  DCHECK(MemoryChunk::FromAddress(from->address())->SweepingDone());
  DCHECK_EQ(MemoryChunk::FromAddress(from->address()),
            MemoryChunk::FromAddress(to->address()));
  DCHECK_NE(from, to);

  MarkBit old_mark_bit = marking_state()->MarkBitFrom(from);
  MarkBit new_mark_bit = marking_state()->MarkBitFrom(to);

  if (black_allocation() && Marking::IsBlack<kAtomicity>(new_mark_bit)) {
    // Nothing to do if the object is in black area.
    return;
  }

  bool marked_black_due_to_left_trimming = false;
  if (FLAG_concurrent_marking) {
    // We need to mark the array black before overwriting its map and length
    // so that the concurrent marker does not observe inconsistent state.
    Marking::WhiteToGrey<kAtomicity>(old_mark_bit);
    if (Marking::GreyToBlack<kAtomicity>(old_mark_bit)) {
      // The concurrent marker will not mark the array. We need to push the
      // new array start in marking deque to ensure that it will be marked.
      marked_black_due_to_left_trimming = true;
    }
    DCHECK(Marking::IsBlack<kAtomicity>(old_mark_bit));
  }

  if (Marking::IsBlack<kAtomicity>(old_mark_bit) &&
      !marked_black_due_to_left_trimming) {
    // The array was black before left trimming or was marked black by the
    // concurrent marker. Simply transfer the color.
    if (from->address() + kTaggedSize == to->address()) {
      // The old and the new markbits overlap. The |to| object has the
      // grey color. To make it black, we need to set the second bit.
      DCHECK(new_mark_bit.Get<kAtomicity>());
      new_mark_bit.Next().Set<kAtomicity>();
    } else {
      bool success = Marking::WhiteToBlack<kAtomicity>(new_mark_bit);
      DCHECK(success);
      USE(success);
    }
  } else if (Marking::IsGrey<kAtomicity>(old_mark_bit) ||
             marked_black_due_to_left_trimming) {
    // The array was already grey or was marked black by this function.
    // Mark the new array grey and push it to marking deque.
    if (from->address() + kTaggedSize == to->address()) {
      // The old and the new markbits overlap. The |to| object is either white
      // or grey.  Set the first bit to make sure that it is grey.
      new_mark_bit.Set<kAtomicity>();
      DCHECK(!new_mark_bit.Next().Get<kAtomicity>());
    } else {
      bool success = Marking::WhiteToGrey<kAtomicity>(new_mark_bit);
      DCHECK(success);
      USE(success);
    }
    // Subsequent left-trimming will re-push only grey arrays.
    // Ensure that this array is grey.
    DCHECK(Marking::IsGrey<kAtomicity>(new_mark_bit));
    marking_worklist()->PushBailout(to);
    RestartIfNotMarking();
  }
}

class IncrementalMarkingRootMarkingVisitor : public RootVisitor {
 public:
  explicit IncrementalMarkingRootMarkingVisitor(
      IncrementalMarking* incremental_marking)
      : heap_(incremental_marking->heap()) {}

  void VisitRootPointer(Root root, const char* description,
                        FullObjectSlot p) override {
    MarkObjectByPointer(p);
  }

  void VisitRootPointers(Root root, const char* description,
                         FullObjectSlot start, FullObjectSlot end) override {
    for (FullObjectSlot p = start; p < end; ++p) MarkObjectByPointer(p);
  }

 private:
  void MarkObjectByPointer(FullObjectSlot p) {
    Object obj = *p;
    if (!obj->IsHeapObject()) return;

    heap_->incremental_marking()->WhiteToGreyAndPush(HeapObject::cast(obj));
  }

  Heap* heap_;
};

void IncrementalMarking::DeactivateIncrementalWriteBarrierForSpace(
    PagedSpace* space) {
  for (Page* p : *space) {
    p->SetOldGenerationPageFlags(false);
  }
}


void IncrementalMarking::DeactivateIncrementalWriteBarrierForSpace(
    NewSpace* space) {
  for (Page* p : *space) {
    p->SetYoungGenerationPageFlags(false);
  }
}


void IncrementalMarking::DeactivateIncrementalWriteBarrier() {
  DeactivateIncrementalWriteBarrierForSpace(heap_->old_space());
  DeactivateIncrementalWriteBarrierForSpace(heap_->map_space());
  DeactivateIncrementalWriteBarrierForSpace(heap_->code_space());
  DeactivateIncrementalWriteBarrierForSpace(heap_->new_space());

  for (LargePage* p : *heap_->lo_space()) {
    p->SetOldGenerationPageFlags(false);
  }

  for (LargePage* p : *heap_->code_lo_space()) {
    p->SetOldGenerationPageFlags(false);
  }
}


void IncrementalMarking::ActivateIncrementalWriteBarrier(PagedSpace* space) {
  for (Page* p : *space) {
    p->SetOldGenerationPageFlags(true);
  }
}


void IncrementalMarking::ActivateIncrementalWriteBarrier(NewSpace* space) {
  for (Page* p : *space) {
    p->SetYoungGenerationPageFlags(true);
  }
}


void IncrementalMarking::ActivateIncrementalWriteBarrier() {
  ActivateIncrementalWriteBarrier(heap_->old_space());
  ActivateIncrementalWriteBarrier(heap_->map_space());
  ActivateIncrementalWriteBarrier(heap_->code_space());
  ActivateIncrementalWriteBarrier(heap_->new_space());

  for (LargePage* p : *heap_->lo_space()) {
    p->SetOldGenerationPageFlags(true);
  }

  for (LargePage* p : *heap_->code_lo_space()) {
    p->SetOldGenerationPageFlags(true);
  }
}


bool IncrementalMarking::WasActivated() { return was_activated_; }


bool IncrementalMarking::CanBeActivated() {
  // Only start incremental marking in a safe state: 1) when incremental
  // marking is turned on, 2) when we are currently not in a GC, and
  // 3) when we are currently not serializing or deserializing the heap.
  return FLAG_incremental_marking && heap_->gc_state() == Heap::NOT_IN_GC &&
         heap_->deserialization_complete() &&
         !heap_->isolate()->serializer_enabled();
}


void IncrementalMarking::Deactivate() {
  DeactivateIncrementalWriteBarrier();
}

void IncrementalMarking::Start(GarbageCollectionReason gc_reason) {
  if (FLAG_trace_incremental_marking) {
    int old_generation_size_mb =
        static_cast<int>(heap()->OldGenerationSizeOfObjects() / MB);
    int old_generation_limit_mb =
        static_cast<int>(heap()->old_generation_allocation_limit() / MB);
    heap()->isolate()->PrintWithTimestamp(
        "[IncrementalMarking] Start (%s): old generation %dMB, limit %dMB, "
        "slack %dMB\n",
        Heap::GarbageCollectionReasonToString(gc_reason),
        old_generation_size_mb, old_generation_limit_mb,
        Max(0, old_generation_limit_mb - old_generation_size_mb));
  }
  DCHECK(FLAG_incremental_marking);
  DCHECK(state_ == STOPPED);
  DCHECK(heap_->gc_state() == Heap::NOT_IN_GC);
  DCHECK(!heap_->isolate()->serializer_enabled());

  Counters* counters = heap_->isolate()->counters();

  counters->incremental_marking_reason()->AddSample(
      static_cast<int>(gc_reason));
  HistogramTimerScope incremental_marking_scope(
      counters->gc_incremental_marking_start());
  TRACE_EVENT0("v8", "V8.GCIncrementalMarkingStart");
  TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_INCREMENTAL_START);
  heap_->tracer()->NotifyIncrementalMarkingStart();

  start_time_ms_ = heap()->MonotonicallyIncreasingTimeInMs();
  initial_old_generation_size_ = heap_->OldGenerationSizeOfObjects();
  old_generation_allocation_counter_ = heap_->OldGenerationAllocationCounter();
  bytes_allocated_ = 0;
  bytes_marked_ahead_of_schedule_ = 0;
  bytes_marked_concurrently_ = 0;
  should_hurry_ = false;
  was_activated_ = true;

  if (!heap_->mark_compact_collector()->sweeping_in_progress()) {
    StartMarking();
  } else {
    if (FLAG_trace_incremental_marking) {
      heap()->isolate()->PrintWithTimestamp(
          "[IncrementalMarking] Start sweeping.\n");
    }
    SetState(SWEEPING);
  }

  heap_->AddAllocationObserversToAllSpaces(&old_generation_observer_,
                                           &new_generation_observer_);
  incremental_marking_job()->Start(heap_);
}


void IncrementalMarking::StartMarking() {
  if (heap_->isolate()->serializer_enabled()) {
    // Black allocation currently starts when we start incremental marking,
    // but we cannot enable black allocation while deserializing. Hence, we
    // have to delay the start of incremental marking in that case.
    if (FLAG_trace_incremental_marking) {
      heap()->isolate()->PrintWithTimestamp(
          "[IncrementalMarking] Start delayed - serializer\n");
    }
    return;
  }
  if (FLAG_trace_incremental_marking) {
    heap()->isolate()->PrintWithTimestamp(
        "[IncrementalMarking] Start marking\n");
  }

  is_compacting_ =
      !FLAG_never_compact && heap_->mark_compact_collector()->StartCompaction();

  SetState(MARKING);

  {
    TRACE_GC(heap()->tracer(),
             GCTracer::Scope::MC_INCREMENTAL_EMBEDDER_PROLOGUE);
    heap_->local_embedder_heap_tracer()->TracePrologue();
  }

  ActivateIncrementalWriteBarrier();

// Marking bits are cleared by the sweeper.
#ifdef VERIFY_HEAP
  if (FLAG_verify_heap) {
    heap_->mark_compact_collector()->VerifyMarkbitsAreClean();
  }
#endif

  heap_->isolate()->compilation_cache()->MarkCompactPrologue();

#ifdef V8_CONCURRENT_MARKING
  // The write-barrier does not check the color of the source object.
  // Start black allocation earlier to ensure faster marking progress.
  if (!black_allocation_) {
    StartBlackAllocation();
  }
#endif

  // Mark strong roots grey.
  IncrementalMarkingRootMarkingVisitor visitor(this);
  heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG);

  if (FLAG_concurrent_marking && !heap_->IsTearingDown()) {
    heap_->concurrent_marking()->ScheduleTasks();
  }

  // Ready to start incremental marking.
  if (FLAG_trace_incremental_marking) {
    heap()->isolate()->PrintWithTimestamp("[IncrementalMarking] Running\n");
  }
}

void IncrementalMarking::StartBlackAllocation() {
  DCHECK(FLAG_black_allocation);
  DCHECK(!black_allocation_);
  DCHECK(IsMarking());
  black_allocation_ = true;
  heap()->old_space()->MarkLinearAllocationAreaBlack();
  heap()->map_space()->MarkLinearAllocationAreaBlack();
  heap()->code_space()->MarkLinearAllocationAreaBlack();
  if (FLAG_trace_incremental_marking) {
    heap()->isolate()->PrintWithTimestamp(
        "[IncrementalMarking] Black allocation started\n");
  }
}

void IncrementalMarking::PauseBlackAllocation() {
  DCHECK(FLAG_black_allocation);
  DCHECK(IsMarking());
  heap()->old_space()->UnmarkLinearAllocationArea();
  heap()->map_space()->UnmarkLinearAllocationArea();
  heap()->code_space()->UnmarkLinearAllocationArea();
  if (FLAG_trace_incremental_marking) {
    heap()->isolate()->PrintWithTimestamp(
        "[IncrementalMarking] Black allocation paused\n");
  }
  black_allocation_ = false;
}

void IncrementalMarking::FinishBlackAllocation() {
  if (black_allocation_) {
    black_allocation_ = false;
    if (FLAG_trace_incremental_marking) {
      heap()->isolate()->PrintWithTimestamp(
          "[IncrementalMarking] Black allocation finished\n");
    }
  }
}

void IncrementalMarking::MarkRoots() {
  DCHECK(!finalize_marking_completed_);
  DCHECK(IsMarking());

  IncrementalMarkingRootMarkingVisitor visitor(this);
  heap_->IterateStrongRoots(&visitor, VISIT_ONLY_STRONG);
}

bool IncrementalMarking::ShouldRetainMap(Map map, int age) {
  if (age == 0) {
    // The map has aged. Do not retain this map.
    return false;
  }
  Object constructor = map->GetConstructor();
  if (!constructor->IsHeapObject() ||
      marking_state()->IsWhite(HeapObject::cast(constructor))) {
    // The constructor is dead, no new objects with this map can
    // be created. Do not retain this map.
    return false;
  }
  return true;
}


void IncrementalMarking::RetainMaps() {
  // Do not retain dead maps if flag disables it or there is
  // - memory pressure (reduce_memory_footprint_),
  // - GC is requested by tests or dev-tools (abort_incremental_marking_).
  bool map_retaining_is_disabled = heap()->ShouldReduceMemory() ||
                                   FLAG_retain_maps_for_n_gc == 0;
  WeakArrayList retained_maps = heap()->retained_maps();
  int length = retained_maps->length();
  // The number_of_disposed_maps separates maps in the retained_maps
  // array that were created before and after context disposal.
  // We do not age and retain disposed maps to avoid memory leaks.
  int number_of_disposed_maps = heap()->number_of_disposed_maps_;
  for (int i = 0; i < length; i += 2) {
    MaybeObject value = retained_maps->Get(i);
    HeapObject map_heap_object;
    if (!value->GetHeapObjectIfWeak(&map_heap_object)) {
      continue;
    }
    int age = retained_maps->Get(i + 1).ToSmi().value();
    int new_age;
    Map map = Map::cast(map_heap_object);
    if (i >= number_of_disposed_maps && !map_retaining_is_disabled &&
        marking_state()->IsWhite(map)) {
      if (ShouldRetainMap(map, age)) {
        WhiteToGreyAndPush(map);
      }
      Object prototype = map->prototype();
      if (age > 0 && prototype->IsHeapObject() &&
          marking_state()->IsWhite(HeapObject::cast(prototype))) {
        // The prototype is not marked, age the map.
        new_age = age - 1;
      } else {
        // The prototype and the constructor are marked, this map keeps only
        // transition tree alive, not JSObjects. Do not age the map.
        new_age = age;
      }
    } else {
      new_age = FLAG_retain_maps_for_n_gc;
    }
    // Compact the array and update the age.
    if (new_age != age) {
      retained_maps->Set(i + 1, MaybeObject::FromSmi(Smi::FromInt(new_age)));
    }
  }
}

void IncrementalMarking::FinalizeIncrementally() {
  TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_INCREMENTAL_FINALIZE_BODY);
  DCHECK(!finalize_marking_completed_);
  DCHECK(IsMarking());

  double start = heap_->MonotonicallyIncreasingTimeInMs();

  // After finishing incremental marking, we try to discover all unmarked
  // objects to reduce the marking load in the final pause.
  // 1) We scan and mark the roots again to find all changes to the root set.
  // 2) Age and retain maps embedded in optimized code.
  MarkRoots();

  // Map retaining is needed for perfromance, not correctness,
  // so we can do it only once at the beginning of the finalization.
  RetainMaps();

  finalize_marking_completed_ = true;

  if (FLAG_black_allocation && !heap()->ShouldReduceMemory() &&
      !black_allocation_) {
    // TODO(hpayer): Move to an earlier point as soon as we make faster marking
    // progress.
    StartBlackAllocation();
  }

  if (FLAG_trace_incremental_marking) {
    double end = heap_->MonotonicallyIncreasingTimeInMs();
    double delta = end - start;
    heap()->isolate()->PrintWithTimestamp(
        "[IncrementalMarking] Finalize incrementally spent %.1f ms.\n", delta);
  }
}

void IncrementalMarking::UpdateMarkingWorklistAfterScavenge() {
  if (!IsMarking()) return;

  Map filler_map = ReadOnlyRoots(heap_).one_pointer_filler_map();

#ifdef ENABLE_MINOR_MC
  MinorMarkCompactCollector::MarkingState* minor_marking_state =
      heap()->minor_mark_compact_collector()->marking_state();
#else
  void* minor_marking_state = nullptr;
#endif  // ENABLE_MINOR_MC

  marking_worklist()->Update([
#ifdef DEBUG
                                 // this is referred inside DCHECK.
                                 this,
#endif
                                 filler_map, minor_marking_state](
                                 HeapObject obj, HeapObject* out) -> bool {
    DCHECK(obj->IsHeapObject());
    // Only pointers to from space have to be updated.
    if (Heap::InFromSpace(obj)) {
      MapWord map_word = obj->map_word();
      if (!map_word.IsForwardingAddress()) {
        // There may be objects on the marking deque that do not exist anymore,
        // e.g. left trimmed objects or objects from the root set (frames).
        // If these object are dead at scavenging time, their marking deque
        // entries will not point to forwarding addresses. Hence, we can discard
        // them.
        return false;
      }
      HeapObject dest = map_word.ToForwardingAddress();
      DCHECK_IMPLIES(marking_state()->IsWhite(obj), obj->IsFiller());
      *out = dest;
      return true;
    } else if (Heap::InToSpace(obj)) {
      // The object may be on a page that was moved in new space.
      DCHECK(
          Page::FromAddress(obj->address())->IsFlagSet(Page::SWEEP_TO_ITERATE));
#ifdef ENABLE_MINOR_MC
      if (minor_marking_state->IsGrey(obj)) {
        *out = obj;
        return true;
      }
#endif  // ENABLE_MINOR_MC
      return false;
    } else {
      // The object may be on a page that was moved from new to old space. Only
      // applicable during minor MC garbage collections.
      if (Page::FromAddress(obj->address())
              ->IsFlagSet(Page::SWEEP_TO_ITERATE)) {
#ifdef ENABLE_MINOR_MC
        if (minor_marking_state->IsGrey(obj)) {
          *out = obj;
          return true;
        }
#endif  // ENABLE_MINOR_MC
        return false;
      }
      DCHECK_IMPLIES(marking_state()->IsWhite(obj), obj->IsFiller());
      // Skip one word filler objects that appear on the
      // stack when we perform in place array shift.
      if (obj->map() != filler_map) {
        *out = obj;
        return true;
      }
      return false;
    }
  });

  UpdateWeakReferencesAfterScavenge();
}

namespace {
template <typename T>
T ForwardingAddress(T heap_obj) {
  MapWord map_word = heap_obj->map_word();

  if (map_word.IsForwardingAddress()) {
    return T::cast(map_word.ToForwardingAddress());
  } else if (Heap::InNewSpace(heap_obj)) {
    return T();
  } else {
    return heap_obj;
  }
}
}  // namespace

void IncrementalMarking::UpdateWeakReferencesAfterScavenge() {
  weak_objects_->weak_references.Update(
      [](std::pair<HeapObject, HeapObjectSlot> slot_in,
         std::pair<HeapObject, HeapObjectSlot>* slot_out) -> bool {
        HeapObject heap_obj = slot_in.first;
        HeapObject forwarded = ForwardingAddress(heap_obj);

        if (!forwarded.is_null()) {
          ptrdiff_t distance_to_slot =
              slot_in.second.address() - slot_in.first.ptr();
          Address new_slot = forwarded.ptr() + distance_to_slot;
          slot_out->first = forwarded;
          slot_out->second = HeapObjectSlot(new_slot);
          return true;
        }

        return false;
      });
  weak_objects_->weak_objects_in_code.Update(
      [](std::pair<HeapObject, Code> slot_in,
         std::pair<HeapObject, Code>* slot_out) -> bool {
        HeapObject heap_obj = slot_in.first;
        HeapObject forwarded = ForwardingAddress(heap_obj);

        if (!forwarded.is_null()) {
          slot_out->first = forwarded;
          slot_out->second = slot_in.second;
          return true;
        }

        return false;
      });
  weak_objects_->ephemeron_hash_tables.Update(
      [](EphemeronHashTable slot_in, EphemeronHashTable* slot_out) -> bool {
        EphemeronHashTable forwarded = ForwardingAddress(slot_in);

        if (!forwarded.is_null()) {
          *slot_out = forwarded;
          return true;
        }

        return false;
      });

  auto ephemeron_updater = [](Ephemeron slot_in, Ephemeron* slot_out) -> bool {
    HeapObject key = slot_in.key;
    HeapObject value = slot_in.value;
    HeapObject forwarded_key = ForwardingAddress(key);
    HeapObject forwarded_value = ForwardingAddress(value);

    if (!forwarded_key.is_null() && !forwarded_value.is_null()) {
      *slot_out = Ephemeron{forwarded_key, forwarded_value};
      return true;
    }

    return false;
  };

  weak_objects_->current_ephemerons.Update(ephemeron_updater);
  weak_objects_->next_ephemerons.Update(ephemeron_updater);
  weak_objects_->discovered_ephemerons.Update(ephemeron_updater);
#ifdef DEBUG
  weak_objects_->bytecode_flushing_candidates.Iterate(
      [](SharedFunctionInfo candidate) {
        DCHECK(!Heap::InNewSpace(candidate));
      });
#endif
}

void IncrementalMarking::UpdateMarkedBytesAfterScavenge(
    size_t dead_bytes_in_new_space) {
  if (!IsMarking()) return;
  bytes_marked_ahead_of_schedule_ -=
      Min(bytes_marked_ahead_of_schedule_, dead_bytes_in_new_space);
}

bool IncrementalMarking::IsFixedArrayWithProgressBar(HeapObject obj) {
  if (!obj->IsFixedArray()) return false;
  MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
  return chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR);
}

int IncrementalMarking::VisitObject(Map map, HeapObject obj) {
  DCHECK(marking_state()->IsGrey(obj) || marking_state()->IsBlack(obj));
  if (!marking_state()->GreyToBlack(obj)) {
    // The object can already be black in these cases:
    // 1. The object is a fixed array with the progress bar.
    // 2. The object is a JSObject that was colored black before
    //    unsafe layout change.
    // 3. The object is a string that was colored black before
    //    unsafe layout change.
    // 4. The object is materizalized by the deoptimizer.
    // 5. The object is a descriptor array marked black by
    //    the descriptor array marking barrier.
    DCHECK(obj->IsHashTable() || obj->IsPropertyArray() ||
           obj->IsFixedArray() || obj->IsContext() || obj->IsJSObject() ||
           obj->IsString() || obj->IsDescriptorArray());
  }
  DCHECK(marking_state()->IsBlack(obj));
  WhiteToGreyAndPush(map);
  IncrementalMarkingMarkingVisitor visitor(heap()->mark_compact_collector(),
                                           marking_state());
  return visitor.Visit(map, obj);
}

void IncrementalMarking::ProcessBlackAllocatedObject(HeapObject obj) {
  if (IsMarking() && marking_state()->IsBlack(obj)) {
    RevisitObject(obj);
  }
}

void IncrementalMarking::RevisitObject(HeapObject obj) {
  DCHECK(IsMarking());
  DCHECK(FLAG_concurrent_marking || marking_state()->IsBlack(obj));
  Page* page = Page::FromAddress(obj->address());
  if (page->owner()->identity() == LO_SPACE) {
    page->ResetProgressBar();
  }
  Map map = obj->map();
  WhiteToGreyAndPush(map);
  IncrementalMarkingMarkingVisitor visitor(heap()->mark_compact_collector(),
                                           marking_state());
  visitor.Visit(map, obj);
}

void IncrementalMarking::VisitDescriptors(HeapObject host,
                                          DescriptorArray descriptors,
                                          int number_of_own_descriptors) {
  IncrementalMarkingMarkingVisitor visitor(heap()->mark_compact_collector(),
                                           marking_state());
  // This is necessary because the Scavenger records slots only for the
  // promoted black objects and the marking visitor of DescriptorArray skips
  // the descriptors marked by the visitor.VisitDescriptors() below.
  visitor.MarkDescriptorArrayBlack(host, descriptors);
  visitor.VisitDescriptors(descriptors, number_of_own_descriptors);
}

template <WorklistToProcess worklist_to_process>
intptr_t IncrementalMarking::ProcessMarkingWorklist(
    intptr_t bytes_to_process, ForceCompletionAction completion) {
  intptr_t bytes_processed = 0;
  while (bytes_processed < bytes_to_process || completion == FORCE_COMPLETION) {
    HeapObject obj;
    if (worklist_to_process == WorklistToProcess::kBailout) {
      obj = marking_worklist()->PopBailout();
    } else {
      obj = marking_worklist()->Pop();
    }
    if (obj.is_null()) break;
    // Left trimming may result in white, grey, or black filler objects on the
    // marking deque. Ignore these objects.
    if (obj->IsFiller()) {
      DCHECK(!marking_state()->IsImpossible(obj));
      continue;
    }
    unscanned_bytes_of_large_object_ = 0;
    int size = VisitObject(obj->map(), obj);
    bytes_processed += size - unscanned_bytes_of_large_object_;
  }
  return bytes_processed;
}

void IncrementalMarking::EmbedderStep(double duration_ms) {
  constexpr size_t kObjectsToProcessBeforeInterrupt = 500;

  TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_INCREMENTAL_EMBEDDER_TRACING);
  double deadline = heap_->MonotonicallyIncreasingTimeInMs() + duration_ms;
  bool empty_worklist;
  do {
    {
      LocalEmbedderHeapTracer::ProcessingScope scope(
          heap_->local_embedder_heap_tracer());
      HeapObject object;
      size_t cnt = 0;
      empty_worklist = true;
      while (marking_worklist()->embedder()->Pop(0, &object)) {
        scope.TracePossibleWrapper(JSObject::cast(object));
        if (++cnt == kObjectsToProcessBeforeInterrupt) {
          cnt = 0;
          empty_worklist = false;
          break;
        }
      }
    }
    heap_->local_embedder_heap_tracer()->Trace(deadline);
  } while (!empty_worklist &&
           (heap_->MonotonicallyIncreasingTimeInMs() < deadline));
  heap_->local_embedder_heap_tracer()->SetEmbedderWorklistEmpty(empty_worklist);
}

void IncrementalMarking::Hurry() {
  // A scavenge may have pushed new objects on the marking deque (due to black
  // allocation) even in COMPLETE state. This may happen if scavenges are
  // forced e.g. in tests. It should not happen when COMPLETE was set when
  // incremental marking finished and a regular GC was triggered after that
  // because should_hurry_ will force a full GC.
  if (!marking_worklist()->IsEmpty()) {
    double start = 0.0;
    if (FLAG_trace_incremental_marking) {
      start = heap_->MonotonicallyIncreasingTimeInMs();
      if (FLAG_trace_incremental_marking) {
        heap()->isolate()->PrintWithTimestamp("[IncrementalMarking] Hurry\n");
      }
    }
    // TODO(gc) hurry can mark objects it encounters black as mutator
    // was stopped.
    ProcessMarkingWorklist(0, FORCE_COMPLETION);
    SetState(COMPLETE);
    if (FLAG_trace_incremental_marking) {
      double end = heap_->MonotonicallyIncreasingTimeInMs();
      double delta = end - start;
      if (FLAG_trace_incremental_marking) {
        heap()->isolate()->PrintWithTimestamp(
            "[IncrementalMarking] Complete (hurry), spent %d ms.\n",
            static_cast<int>(delta));
      }
    }
  }
}


void IncrementalMarking::Stop() {
  if (IsStopped()) return;
  if (FLAG_trace_incremental_marking) {
    int old_generation_size_mb =
        static_cast<int>(heap()->OldGenerationSizeOfObjects() / MB);
    int old_generation_limit_mb =
        static_cast<int>(heap()->old_generation_allocation_limit() / MB);
    heap()->isolate()->PrintWithTimestamp(
        "[IncrementalMarking] Stopping: old generation %dMB, limit %dMB, "
        "overshoot %dMB\n",
        old_generation_size_mb, old_generation_limit_mb,
        Max(0, old_generation_size_mb - old_generation_limit_mb));
  }

  SpaceIterator it(heap_);
  while (it.has_next()) {
    Space* space = it.next();
    if (space == heap_->new_space()) {
      space->RemoveAllocationObserver(&new_generation_observer_);
    } else {
      space->RemoveAllocationObserver(&old_generation_observer_);
    }
  }

  IncrementalMarking::set_should_hurry(false);
  heap_->isolate()->stack_guard()->ClearGC();
  SetState(STOPPED);
  is_compacting_ = false;
  FinishBlackAllocation();
}


void IncrementalMarking::Finalize() {
  Hurry();
  Stop();
}


void IncrementalMarking::FinalizeMarking(CompletionAction action) {
  DCHECK(!finalize_marking_completed_);
  if (FLAG_trace_incremental_marking) {
    heap()->isolate()->PrintWithTimestamp(
        "[IncrementalMarking] requesting finalization of incremental "
        "marking.\n");
  }
  request_type_ = FINALIZATION;
  if (action == GC_VIA_STACK_GUARD) {
    heap_->isolate()->stack_guard()->RequestGC();
  }
}


void IncrementalMarking::MarkingComplete(CompletionAction action) {
  SetState(COMPLETE);
  // We will set the stack guard to request a GC now.  This will mean the rest
  // of the GC gets performed as soon as possible (we can't do a GC here in a
  // record-write context).  If a few things get allocated between now and then
  // that shouldn't make us do a scavenge and keep being incremental, so we set
  // the should-hurry flag to indicate that there can't be much work left to do.
  set_should_hurry(true);
  if (FLAG_trace_incremental_marking) {
    heap()->isolate()->PrintWithTimestamp(
        "[IncrementalMarking] Complete (normal).\n");
  }
  request_type_ = COMPLETE_MARKING;
  if (action == GC_VIA_STACK_GUARD) {
    heap_->isolate()->stack_guard()->RequestGC();
  }
}


void IncrementalMarking::Epilogue() {
  was_activated_ = false;
  finalize_marking_completed_ = false;
}

bool IncrementalMarking::ShouldDoEmbedderStep() {
  return state_ == MARKING && FLAG_incremental_marking_wrappers &&
         heap_->local_embedder_heap_tracer()->InUse();
}

double IncrementalMarking::AdvanceIncrementalMarking(
    double deadline_in_ms, CompletionAction completion_action,
    StepOrigin step_origin) {
  HistogramTimerScope incremental_marking_scope(
      heap_->isolate()->counters()->gc_incremental_marking());
  TRACE_EVENT0("v8", "V8.GCIncrementalMarking");
  TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL);
  DCHECK(!IsStopped());

  double remaining_time_in_ms = 0.0;
  do {
    if (ShouldDoEmbedderStep() && trace_wrappers_toggle_) {
      EmbedderStep(kStepSizeInMs);
    } else {
      const intptr_t step_size_in_bytes =
          GCIdleTimeHandler::EstimateMarkingStepSize(
              kStepSizeInMs,
              heap()->tracer()->IncrementalMarkingSpeedInBytesPerMillisecond());
      Step(step_size_in_bytes, completion_action, step_origin);
    }
    trace_wrappers_toggle_ = !trace_wrappers_toggle_;
    remaining_time_in_ms =
        deadline_in_ms - heap()->MonotonicallyIncreasingTimeInMs();
  } while (remaining_time_in_ms > kStepSizeInMs && !IsComplete() &&
           !marking_worklist()->IsEmpty());
  return remaining_time_in_ms;
}


void IncrementalMarking::FinalizeSweeping() {
  DCHECK(state_ == SWEEPING);
  if (heap_->mark_compact_collector()->sweeping_in_progress() &&
      (!FLAG_concurrent_sweeping ||
       !heap_->mark_compact_collector()->sweeper()->AreSweeperTasksRunning())) {
    heap_->mark_compact_collector()->EnsureSweepingCompleted();
  }
  if (!heap_->mark_compact_collector()->sweeping_in_progress()) {
#ifdef DEBUG
    heap_->VerifyCountersAfterSweeping();
#endif
    StartMarking();
  }
}

size_t IncrementalMarking::StepSizeToKeepUpWithAllocations() {
  // Update bytes_allocated_ based on the allocation counter.
  size_t current_counter = heap_->OldGenerationAllocationCounter();
  bytes_allocated_ += current_counter - old_generation_allocation_counter_;
  old_generation_allocation_counter_ = current_counter;
  return bytes_allocated_;
}

size_t IncrementalMarking::StepSizeToMakeProgress() {
  const size_t kTargetStepCount = 256;
  const size_t kTargetStepCountAtOOM = 32;
  const size_t kMaxStepSizeInByte = 256 * KB;
  size_t oom_slack = heap()->new_space()->Capacity() + 64 * MB;

  if (!heap()->CanExpandOldGeneration(oom_slack)) {
    return heap()->OldGenerationSizeOfObjects() / kTargetStepCountAtOOM;
  }

  return Min(Max(initial_old_generation_size_ / kTargetStepCount,
                 IncrementalMarking::kMinStepSizeInBytes),
             kMaxStepSizeInByte);
}

void IncrementalMarking::AdvanceIncrementalMarkingOnAllocation() {
  // Code using an AlwaysAllocateScope assumes that the GC state does not
  // change; that implies that no marking steps must be performed.
  if (heap_->gc_state() != Heap::NOT_IN_GC || !FLAG_incremental_marking ||
      (state_ != SWEEPING && state_ != MARKING) || heap_->always_allocate()) {
    return;
  }

  HistogramTimerScope incremental_marking_scope(
      heap_->isolate()->counters()->gc_incremental_marking());
  TRACE_EVENT0("v8", "V8.GCIncrementalMarking");
  TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL);

  double embedder_step_time_ms = 0.0;
  if (ShouldDoEmbedderStep() && trace_wrappers_toggle_) {
    double start = heap_->MonotonicallyIncreasingTimeInMs();
    EmbedderStep(kMaxStepSizeInMs);
    embedder_step_time_ms = heap_->MonotonicallyIncreasingTimeInMs() - start;
  }
  trace_wrappers_toggle_ = !trace_wrappers_toggle_;

  size_t bytes_to_process =
      StepSizeToKeepUpWithAllocations() + StepSizeToMakeProgress();
  if (bytes_to_process >= IncrementalMarking::kMinStepSizeInBytes &&
      embedder_step_time_ms < kMaxStepSizeInMs) {
    StepOnAllocation(bytes_to_process,
                     kMaxStepSizeInMs - embedder_step_time_ms);
  }
}

void IncrementalMarking::StepOnAllocation(size_t bytes_to_process,
                                          double max_step_size) {
  // The first step after Scavenge will see many allocated bytes.
  // Cap the step size to distribute the marking work more uniformly.
  size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(
      max_step_size,
      heap()->tracer()->IncrementalMarkingSpeedInBytesPerMillisecond());
  bytes_to_process = Min(bytes_to_process, step_size);
  size_t bytes_processed = 0;
  if (FLAG_concurrent_marking) {
    bytes_processed = Step(bytes_to_process, GC_VIA_STACK_GUARD,
                           StepOrigin::kV8, WorklistToProcess::kBailout);
    bytes_to_process = (bytes_processed >= bytes_to_process)
                           ? 0
                           : bytes_to_process - bytes_processed;
    size_t current_bytes_marked_concurrently =
        heap()->concurrent_marking()->TotalMarkedBytes();
    // The concurrent_marking()->TotalMarkedBytes() is not monothonic for a
    // short period of time when a concurrent marking task is finishing.
    if (current_bytes_marked_concurrently > bytes_marked_concurrently_) {
      bytes_marked_ahead_of_schedule_ +=
          current_bytes_marked_concurrently - bytes_marked_concurrently_;
      bytes_marked_concurrently_ = current_bytes_marked_concurrently;
    }
  }
  if (bytes_marked_ahead_of_schedule_ >= bytes_to_process) {
    // Steps performed in tasks and concurrently have put us ahead of
    // schedule. We skip processing of marking dequeue here and thus shift
    // marking time from inside V8 to standalone tasks.
    bytes_marked_ahead_of_schedule_ -= bytes_to_process;
    bytes_processed += bytes_to_process;
    bytes_to_process = IncrementalMarking::kMinStepSizeInBytes;
  }
  bytes_processed += Step(bytes_to_process, GC_VIA_STACK_GUARD, StepOrigin::kV8,
                          WorklistToProcess::kAll);
  bytes_allocated_ -= Min(bytes_allocated_, bytes_processed);
}

size_t IncrementalMarking::Step(size_t bytes_to_process,
                                CompletionAction action, StepOrigin step_origin,
                                WorklistToProcess worklist_to_process) {
  double start = heap_->MonotonicallyIncreasingTimeInMs();

  if (state_ == SWEEPING) {
    TRACE_GC(heap_->tracer(), GCTracer::Scope::MC_INCREMENTAL_SWEEPING);
    FinalizeSweeping();
  }

  size_t bytes_processed = 0;
  if (state_ == MARKING) {
    if (FLAG_concurrent_marking) {
      heap_->new_space()->ResetOriginalTop();
      // It is safe to merge back all objects that were on hold to the shared
      // work list at Step because we are at a safepoint where all objects
      // are properly initialized.
      marking_worklist()->shared()->MergeGlobalPool(
          marking_worklist()->on_hold());
    }

// Only print marking worklist in debug mode to save ~40KB of code size.
#ifdef DEBUG
    if (FLAG_trace_incremental_marking && FLAG_trace_concurrent_marking &&
        FLAG_trace_gc_verbose) {
      marking_worklist()->Print();
    }
#endif

    if (worklist_to_process == WorklistToProcess::kBailout) {
      bytes_processed =
          ProcessMarkingWorklist<WorklistToProcess::kBailout>(bytes_to_process);
    } else {
      bytes_processed =
          ProcessMarkingWorklist<WorklistToProcess::kAll>(bytes_to_process);
    }

    if (step_origin == StepOrigin::kTask) {
      bytes_marked_ahead_of_schedule_ += bytes_processed;
    }

    if (marking_worklist()->IsEmpty()) {
      if (heap_->local_embedder_heap_tracer()
              ->ShouldFinalizeIncrementalMarking()) {
        if (!finalize_marking_completed_) {
          FinalizeMarking(action);
        } else {
          MarkingComplete(action);
        }
      } else {
        heap_->local_embedder_heap_tracer()->NotifyV8MarkingWorklistWasEmpty();
      }
    }
  }
  if (FLAG_concurrent_marking) {
    heap_->concurrent_marking()->RescheduleTasksIfNeeded();
  }

  double end = heap_->MonotonicallyIncreasingTimeInMs();
  double duration = (end - start);
  // Note that we report zero bytes here when sweeping was in progress or
  // when we just started incremental marking. In these cases we did not
  // process the marking deque.
  heap_->tracer()->AddIncrementalMarkingStep(duration, bytes_processed);
  if (FLAG_trace_incremental_marking) {
    heap_->isolate()->PrintWithTimestamp(
        "[IncrementalMarking] Step %s %" PRIuS "KB (%" PRIuS "KB) in %.1f\n",
        step_origin == StepOrigin::kV8 ? "in v8" : "in task",
        bytes_processed / KB, bytes_to_process / KB, duration);
  }
  if (FLAG_trace_concurrent_marking) {
    heap_->isolate()->PrintWithTimestamp(
        "Concurrently marked %" PRIuS "KB\n",
        heap_->concurrent_marking()->TotalMarkedBytes() / KB);
  }
  return bytes_processed;
}

}  // namespace internal
}  // namespace v8
