/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/heap/cppgc/marker.h
283 строки
9 KB
Michaël Zasso
deps: update V8 to 14.1.146.11
04 окт 2025, 19:47
Не верифицирован
04 окт 2025, 19:47
7772a2d
Код
Авторство
О чём код?
// Copyright 2020 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_CPPGC_MARKER_H_ #define V8_HEAP_CPPGC_MARKER_H_ #include <memory> #include "include/cppgc/heap.h" #include "include/cppgc/platform.h" #include "include/cppgc/visitor.h" #include "src/base/macros.h" #include "src/base/platform/time.h" #include "src/heap/base/incremental-marking-schedule.h" #include "src/heap/base/worklist.h" #include "src/heap/cppgc/concurrent-marker.h" #include "src/heap/cppgc/globals.h" #include "src/heap/cppgc/heap-config.h" #include "src/heap/cppgc/marking-state.h" #include "src/heap/cppgc/marking-visitor.h" #include "src/heap/cppgc/marking-worklists.h" #include "src/heap/cppgc/stats-collector.h" #include "src/heap/cppgc/task-handle.h" namespace cppgc { namespace internal { class HeapBase; // Marking algorithm. Example for a valid call sequence creating the marking // phase: // 1. StartMarking() // 2. AdvanceMarkingWithLimits() [Optional, depending on environment.] // 3. EnterAtomicPause() // 4. AdvanceMarkingWithLimits() [Optional] // 5. EnterProcessGlobalAtomicPause() // 6. AdvanceMarkingWithLimits() // 7. LeaveAtomicPause() // // Alternatively, FinishMarking() combines steps 3.-7. // // The marker protects cross-thread roots from being created between 5.-7. This // currently requires entering a process-global atomic pause. class V8_EXPORT_PRIVATE MarkerBase { public: class IncrementalMarkingTask; enum class WriteBarrierType { kDijkstra, kSteele, }; // Pauses concurrent marking if running while this scope is active. class PauseConcurrentMarkingScope final { public: explicit PauseConcurrentMarkingScope(MarkerBase&); ~PauseConcurrentMarkingScope(); private: MarkerBase& marker_; const bool resume_on_exit_; }; virtual ~MarkerBase(); MarkerBase(const MarkerBase&) = delete; MarkerBase& operator=(const MarkerBase&) = delete; template <typename Class> Class& To() { return *static_cast<Class*>(this); } // Signals entering the atomic marking pause. The method // - stops incremental/concurrent marking; // - flushes back any in-construction worklists if needed; // - Updates the MarkingConfig if the stack state has changed; // - marks local roots void EnterAtomicPause(StackState); // Enters the process-global pause. The phase marks cross-thread roots and // acquires a lock that prevents any cross-thread references from being // created. // // The phase is ended with `LeaveAtomicPause()`. void EnterProcessGlobalAtomicPause(); // Re-enable concurrent marking assuming it isn't enabled yet in GC cycle. void ReEnableConcurrentMarking(); // Makes marking progress. The deadlines are only checked every few objects. // - `max_duration`: A maximum marking duration. // - `marked_bytes_limit`: Only process this many bytes. Ignored for // processing concurrent bailout objects. bool AdvanceMarkingWithLimits(v8::base::TimeDelta max_duration, size_t marked_bytes_limit); // Returns the size of the bytes marked in the last invocation of // `AdvanceMarkingWithLimits()`. size_t last_bytes_marked() const { return last_bytes_marked_; } // Signals leaving the atomic marking pause. This method expects no more // objects to be marked and merely updates marking states if needed. void LeaveAtomicPause(); // Initialize marking according to the given config. This method will // trigger incremental/concurrent marking if needed. void StartMarking(); // Combines: // - EnterAtomicPause() // - EnterProcessGlobalAtomicPause() // - AdvanceMarkingWithLimits() // - ProcessWeakness() // - LeaveAtomicPause() void FinishMarking(StackState); void ProcessCrossThreadWeaknessIfNeeded(); void ProcessWeakness(); bool JoinConcurrentMarkingIfNeeded(); void NotifyConcurrentMarkingOfWorkIfNeeded(cppgc::TaskPriority); template <WriteBarrierType type> inline void WriteBarrierForObject(HeapObjectHeader&); HeapBase& heap() { return heap_; } cppgc::Visitor& Visitor() { return visitor(); } bool IsMarking() const { return is_marking_; } void SetMainThreadMarkingDisabledForTesting(bool); void WaitForConcurrentMarkingForTesting(); void ClearAllWorklistsForTesting(); bool IncrementalMarkingStepForTesting(StackState); MarkingWorklists& MarkingWorklistsForTesting() { return marking_worklists_; } MutatorMarkingState& MutatorMarkingStateForTesting() { return mutator_marking_state_; } protected: class IncrementalMarkingAllocationObserver final : public StatsCollector::AllocationObserver { public: static constexpr size_t kMinAllocatedBytesPerStep = 256 * kKB; explicit IncrementalMarkingAllocationObserver(MarkerBase& marker); void AllocatedObjectSizeIncreased(size_t delta) final; private: MarkerBase& marker_; size_t current_allocated_size_ = 0; }; using IncrementalMarkingTaskHandle = SingleThreadedHandle; static constexpr v8::base::TimeDelta kMaximumIncrementalStepDuration = v8::base::TimeDelta::FromMilliseconds(2); MarkerBase(HeapBase&, cppgc::Platform*, MarkingConfig); virtual cppgc::Visitor& visitor() = 0; virtual ConservativeTracingVisitor& conservative_visitor() = 0; virtual heap::base::StackVisitor& stack_visitor() = 0; virtual ConcurrentMarkerBase& concurrent_marker() = 0; virtual heap::base::IncrementalMarkingSchedule& schedule() = 0; // Processes the worklists with given deadlines. The deadlines are only // checked every few objects. // - `time_deadline`: Time deadline that is always respected. // - `marked_bytes_deadline`: Only process this many bytes. Ignored for // processing concurrent bailout objects. bool ProcessWorklistsWithDeadline(v8::base::TimeTicks time_deadline, size_t marked_bytes_deadline); void AdvanceMarkingWithLimitsEpilogue(); void VisitLocalRoots(StackState); void VisitCrossThreadRoots(); void MarkNotFullyConstructedObjects(); virtual void ScheduleIncrementalMarkingTask(); bool IncrementalMarkingStep(StackState); void AdvanceMarkingOnAllocation(); virtual void AdvanceMarkingOnAllocationImpl(); void HandleNotFullyConstructedObjects(); void MarkStrongCrossThreadRoots(); HeapBase& heap_; MarkingConfig config_ = MarkingConfig::Default(); cppgc::Platform* platform_; std::shared_ptr<cppgc::TaskRunner> foreground_task_runner_; IncrementalMarkingTaskHandle incremental_marking_handle_; IncrementalMarkingAllocationObserver incremental_marking_allocation_observer_; MarkingWorklists marking_worklists_; MutatorMarkingState mutator_marking_state_; size_t last_bytes_marked_ = 0; bool is_marking_{false}; bool main_marking_disabled_for_testing_{false}; bool visited_cross_thread_persistents_in_atomic_pause_{false}; bool processed_cross_thread_weakness_{false}; }; class V8_EXPORT_PRIVATE Marker final : public MarkerBase { public: Marker(HeapBase&, cppgc::Platform*, MarkingConfig = MarkingConfig::Default()); protected: cppgc::Visitor& visitor() final { return marking_visitor_; } ConservativeTracingVisitor& conservative_visitor() final { return conservative_marking_visitor_; } heap::base::StackVisitor& stack_visitor() final { return conservative_marking_visitor_; } ConcurrentMarkerBase& concurrent_marker() final { return concurrent_marker_; } heap::base::IncrementalMarkingSchedule& schedule() final { return *schedule_.get(); } private: MutatorMarkingVisitor marking_visitor_; ConservativeMarkingVisitor conservative_marking_visitor_; std::unique_ptr<heap::base::IncrementalMarkingSchedule> schedule_; ConcurrentMarker concurrent_marker_; }; template <MarkerBase::WriteBarrierType type> void MarkerBase::WriteBarrierForObject(HeapObjectHeader& header) { // The barrier optimizes for the bailout cases: // - kDijkstra: Marked objects. // - kSteele: Unmarked objects. switch (type) { case MarkerBase::WriteBarrierType::kDijkstra: if (!header.TryMarkAtomic()) { return; } break; case MarkerBase::WriteBarrierType::kSteele: if (!header.IsMarked<AccessMode::kAtomic>()) { return; } break; } // The barrier fired. Filter out in-construction objects here. This possibly // requires unmarking the object again. if (V8_UNLIKELY(header.IsInConstruction<AccessMode::kNonAtomic>())) { // In construction objects are traced only if they are unmarked. If marking // reaches this object again when it is fully constructed, it will re-mark // it and tracing it as a previously not fully constructed object would know // to bail out. header.Unmark<AccessMode::kAtomic>(); mutator_marking_state_.not_fully_constructed_worklist() .Push<AccessMode::kAtomic>(&header); return; } switch (type) { case MarkerBase::WriteBarrierType::kDijkstra: mutator_marking_state_.write_barrier_worklist().Push(&header); break; case MarkerBase::WriteBarrierType::kSteele: mutator_marking_state_.retrace_marked_objects_worklist().Push(&header); break; } } } // namespace internal } // namespace cppgc #endif // V8_HEAP_CPPGC_MARKER_H_