blob: 403a06089a116cb780bb439efe8766fec204e54a [file]
// Copyright 2019 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.
#ifndef V8_HEAP_MARKING_VISITOR_H_
#define V8_HEAP_MARKING_VISITOR_H_
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/heap/marking-state.h"
#include "src/heap/marking-worklist.h"
#include "src/heap/objects-visiting.h"
#include "src/heap/pretenuring-handler.h"
#include "src/heap/spaces.h"
#include "src/heap/weak-object-worklists.h"
#include "src/objects/string.h"
namespace v8 {
namespace internal {
struct EphemeronMarking {
std::vector<HeapObject> newly_discovered;
bool newly_discovered_overflowed;
size_t newly_discovered_limit;
};
// The base class for all marking visitors. It implements marking logic with
// support of bytecode flushing, embedder tracing, weak and references.
//
// Derived classes are expected to provide the following:
// - ConcreteVisitor::marking_state method,
// - ConcreteVisitor::retaining_path_mode method,
// - ConcreteVisitor::RecordSlot method,
// - ConcreteVisitor::RecordRelocSlot method,
// These methods capture the difference between the concurrent and main thread
// marking visitors. For example, the concurrent visitor has to use the
// snapshotting protocol to visit JSObject and left-trimmable FixedArrays.
template <typename ConcreteVisitor, typename MarkingState>
class MarkingVisitorBase : public ConcurrentHeapVisitor<int, ConcreteVisitor> {
public:
MarkingVisitorBase(MarkingWorklists::Local* local_marking_worklists,
WeakObjects::Local* local_weak_objects, Heap* heap,
unsigned mark_compact_epoch,
base::EnumSet<CodeFlushMode> code_flush_mode,
bool trace_embedder_fields,
bool should_keep_ages_unchanged)
: ConcurrentHeapVisitor<int, ConcreteVisitor>(heap->isolate()),
local_marking_worklists_(local_marking_worklists),
local_weak_objects_(local_weak_objects),
heap_(heap),
mark_compact_epoch_(mark_compact_epoch),
code_flush_mode_(code_flush_mode),
trace_embedder_fields_(trace_embedder_fields),
should_keep_ages_unchanged_(should_keep_ages_unchanged),
should_mark_shared_heap_(heap->isolate()->is_shared_space_isolate())
#ifdef V8_ENABLE_SANDBOX
,
external_pointer_table_(&heap->isolate()->external_pointer_table()),
shared_external_pointer_table_(
&heap->isolate()->shared_external_pointer_table())
#endif // V8_ENABLE_SANDBOX
{
}
V8_INLINE int VisitBytecodeArray(Map map, BytecodeArray object);
V8_INLINE int VisitDescriptorArrayStrongly(Map map, DescriptorArray object);
V8_INLINE int VisitDescriptorArray(Map map, DescriptorArray object);
V8_INLINE int VisitEphemeronHashTable(Map map, EphemeronHashTable object);
V8_INLINE int VisitFixedArray(Map map, FixedArray object);
V8_INLINE int VisitJSApiObject(Map map, JSObject object);
V8_INLINE int VisitJSArrayBuffer(Map map, JSArrayBuffer object);
V8_INLINE int VisitJSDataViewOrRabGsabDataView(
Map map, JSDataViewOrRabGsabDataView object);
V8_INLINE int VisitJSFunction(Map map, JSFunction object);
V8_INLINE int VisitJSTypedArray(Map map, JSTypedArray object);
V8_INLINE int VisitJSWeakRef(Map map, JSWeakRef object);
V8_INLINE int VisitMap(Map map, Map object);
V8_INLINE int VisitSharedFunctionInfo(Map map, SharedFunctionInfo object);
V8_INLINE int VisitTransitionArray(Map map, TransitionArray object);
V8_INLINE int VisitWeakCell(Map map, WeakCell object);
// ObjectVisitor overrides.
void VisitMapPointer(HeapObject host) final {
Map map = host.map(ObjectVisitorWithCageBases::cage_base());
ProcessStrongHeapObject(host, host.map_slot(), map);
}
V8_INLINE void VisitPointer(HeapObject host, ObjectSlot p) final {
VisitPointersImpl(host, p, p + 1);
}
V8_INLINE void VisitPointer(HeapObject host, MaybeObjectSlot p) final {
VisitPointersImpl(host, p, p + 1);
}
V8_INLINE void VisitPointers(HeapObject host, ObjectSlot start,
ObjectSlot end) final {
VisitPointersImpl(host, start, end);
}
V8_INLINE void VisitPointers(HeapObject host, MaybeObjectSlot start,
MaybeObjectSlot end) final {
VisitPointersImpl(host, start, end);
}
V8_INLINE void VisitCodePointer(Code host, CodeObjectSlot slot) final {
VisitCodePointerImpl(host, slot);
}
V8_INLINE void VisitEmbeddedPointer(InstructionStream host,
RelocInfo* rinfo) final;
V8_INLINE void VisitCodeTarget(InstructionStream host,
RelocInfo* rinfo) final;
void VisitCustomWeakPointers(HeapObject host, ObjectSlot start,
ObjectSlot end) final {
// Weak list pointers should be ignored during marking. The lists are
// reconstructed after GC.
}
V8_INLINE void VisitExternalPointer(HeapObject host, ExternalPointerSlot slot,
ExternalPointerTag tag) final;
void SynchronizePageAccess(HeapObject heap_object) {
#ifdef THREAD_SANITIZER
// This is needed because TSAN does not process the memory fence
// emitted after page initialization.
BasicMemoryChunk::FromHeapObject(heap_object)->SynchronizedHeapLoad();
#endif
}
bool ShouldMarkObject(HeapObject object) const {
if (object.InReadOnlySpace()) return false;
if (should_mark_shared_heap_) return true;
return !object.InAnySharedSpace();
}
// Marks the object grey and pushes it on the marking work list.
V8_INLINE void MarkObject(HeapObject host, HeapObject obj);
V8_INLINE static constexpr bool ShouldVisitReadOnlyMapPointer() {
return false;
}
protected:
ConcreteVisitor* concrete_visitor() {
return static_cast<ConcreteVisitor*>(this);
}
template <typename THeapObjectSlot>
void ProcessStrongHeapObject(HeapObject host, THeapObjectSlot slot,
HeapObject heap_object);
template <typename THeapObjectSlot>
void ProcessWeakHeapObject(HeapObject host, THeapObjectSlot slot,
HeapObject heap_object);
template <typename TSlot>
V8_INLINE void VisitPointerImpl(HeapObject host, TSlot p);
template <typename TSlot>
V8_INLINE void VisitPointersImpl(HeapObject host, TSlot start, TSlot end);
// Similar to VisitPointersImpl() but using code cage base for loading from
// the slot.
V8_INLINE void VisitCodePointerImpl(Code host, CodeObjectSlot slot);
V8_INLINE void VisitDescriptorsForMap(Map map);
template <typename T>
int VisitEmbedderTracingSubclass(Map map, T object);
template <typename T>
int VisitEmbedderTracingSubClassWithEmbedderTracing(Map map, T object);
template <typename T>
int VisitEmbedderTracingSubClassNoEmbedderTracing(Map map, T object);
V8_INLINE int VisitFixedArrayWithProgressBar(Map map, FixedArray object,
ProgressBar& progress_bar);
V8_INLINE int VisitFixedArrayRegularly(Map map, FixedArray object);
V8_INLINE void AddStrongReferenceForReferenceSummarizer(HeapObject host,
HeapObject obj) {
concrete_visitor()
->marking_state()
->AddStrongReferenceForReferenceSummarizer(host, obj);
}
V8_INLINE void AddWeakReferenceForReferenceSummarizer(HeapObject host,
HeapObject obj) {
concrete_visitor()->marking_state()->AddWeakReferenceForReferenceSummarizer(
host, obj);
}
constexpr bool CanUpdateValuesInHeap() {
return !MarkingState::kCollectRetainers;
}
MarkingWorklists::Local* const local_marking_worklists_;
WeakObjects::Local* const local_weak_objects_;
Heap* const heap_;
const unsigned mark_compact_epoch_;
const base::EnumSet<CodeFlushMode> code_flush_mode_;
const bool trace_embedder_fields_;
const bool should_keep_ages_unchanged_;
const bool should_mark_shared_heap_;
#ifdef V8_ENABLE_SANDBOX
ExternalPointerTable* const external_pointer_table_;
ExternalPointerTable* const shared_external_pointer_table_;
#endif // V8_ENABLE_SANDBOX
};
template <typename ConcreteVisitor, typename MarkingState>
class YoungGenerationMarkingVisitorBase
: public NewSpaceVisitor<ConcreteVisitor> {
public:
YoungGenerationMarkingVisitorBase(Isolate* isolate,
MarkingWorklists::Local* worklists_local);
~YoungGenerationMarkingVisitorBase() override {
DCHECK(local_pretenuring_feedback_.empty());
}
V8_INLINE void VisitPointers(HeapObject host, ObjectSlot start,
ObjectSlot end) final {
concrete_visitor()->VisitPointersImpl(host, start, end);
}
V8_INLINE void VisitPointers(HeapObject host, MaybeObjectSlot start,
MaybeObjectSlot end) final {
concrete_visitor()->VisitPointersImpl(host, start, end);
}
V8_INLINE void VisitPointer(HeapObject host, ObjectSlot p) final {
concrete_visitor()->VisitPointersImpl(host, p, p + 1);
}
V8_INLINE void VisitPointer(HeapObject host, MaybeObjectSlot p) final {
concrete_visitor()->VisitPointersImpl(host, p, p + 1);
}
V8_INLINE int VisitJSApiObject(Map map, JSObject object);
V8_INLINE int VisitJSArrayBuffer(Map map, JSArrayBuffer object);
V8_INLINE int VisitJSDataViewOrRabGsabDataView(
Map map, JSDataViewOrRabGsabDataView object);
V8_INLINE int VisitJSTypedArray(Map map, JSTypedArray object);
V8_INLINE int VisitJSObject(Map map, JSObject object);
V8_INLINE int VisitJSObjectFast(Map map, JSObject object);
template <typename T, typename TBodyDescriptor = typename T::BodyDescriptor>
V8_INLINE int VisitJSObjectSubclass(Map map, T object);
V8_INLINE void Finalize();
protected:
ConcreteVisitor* concrete_visitor() {
return static_cast<ConcreteVisitor*>(this);
}
template <typename T>
int VisitEmbedderTracingSubClassWithEmbedderTracing(Map map, T object);
template <typename TObject>
V8_INLINE void VisitObjectImpl(TObject object);
private:
MarkingWorklists::Local* worklists_local_;
PretenuringHandler* const pretenuring_handler_;
PretenuringHandler::PretenuringFeedbackMap local_pretenuring_feedback_;
};
} // namespace internal
} // namespace v8
#endif // V8_HEAP_MARKING_VISITOR_H_