11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_HEAP_CPPGC_JS_CPP_HEAP_H_ 61cb0ef41Sopenharmony_ci#define V8_HEAP_CPPGC_JS_CPP_HEAP_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#if CPPGC_IS_STANDALONE 91cb0ef41Sopenharmony_cistatic_assert( 101cb0ef41Sopenharmony_ci false, "V8 targets can not be built with cppgc_is_standalone set to true."); 111cb0ef41Sopenharmony_ci#endif 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci#include "include/v8-callbacks.h" 141cb0ef41Sopenharmony_ci#include "include/v8-cppgc.h" 151cb0ef41Sopenharmony_ci#include "include/v8-metrics.h" 161cb0ef41Sopenharmony_ci#include "src/base/flags.h" 171cb0ef41Sopenharmony_ci#include "src/base/macros.h" 181cb0ef41Sopenharmony_ci#include "src/base/optional.h" 191cb0ef41Sopenharmony_ci#include "src/heap/cppgc/heap-base.h" 201cb0ef41Sopenharmony_ci#include "src/heap/cppgc/marker.h" 211cb0ef41Sopenharmony_ci#include "src/heap/cppgc/stats-collector.h" 221cb0ef41Sopenharmony_ci#include "src/logging/metrics.h" 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_cinamespace v8 { 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ciclass Isolate; 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_cinamespace internal { 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ciclass CppMarkingState; 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci// A C++ heap implementation used with V8 to implement unified heap. 331cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE CppHeap final 341cb0ef41Sopenharmony_ci : public cppgc::internal::HeapBase, 351cb0ef41Sopenharmony_ci public v8::CppHeap, 361cb0ef41Sopenharmony_ci public cppgc::internal::StatsCollector::AllocationObserver { 371cb0ef41Sopenharmony_ci public: 381cb0ef41Sopenharmony_ci enum GarbageCollectionFlagValues : uint8_t { 391cb0ef41Sopenharmony_ci kNoFlags = 0, 401cb0ef41Sopenharmony_ci kReduceMemory = 1 << 1, 411cb0ef41Sopenharmony_ci kForced = 1 << 2, 421cb0ef41Sopenharmony_ci }; 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci using GarbageCollectionFlags = base::Flags<GarbageCollectionFlagValues>; 451cb0ef41Sopenharmony_ci using StackState = cppgc::internal::GarbageCollector::Config::StackState; 461cb0ef41Sopenharmony_ci using CollectionType = 471cb0ef41Sopenharmony_ci cppgc::internal::GarbageCollector::Config::CollectionType; 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci class MetricRecorderAdapter final : public cppgc::internal::MetricRecorder { 501cb0ef41Sopenharmony_ci public: 511cb0ef41Sopenharmony_ci static constexpr int kMaxBatchedEvents = 16; 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci explicit MetricRecorderAdapter(CppHeap& cpp_heap) : cpp_heap_(cpp_heap) {} 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci void AddMainThreadEvent(const GCCycle& cppgc_event) final; 561cb0ef41Sopenharmony_ci void AddMainThreadEvent(const MainThreadIncrementalMark& cppgc_event) final; 571cb0ef41Sopenharmony_ci void AddMainThreadEvent( 581cb0ef41Sopenharmony_ci const MainThreadIncrementalSweep& cppgc_event) final; 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci void FlushBatchedIncrementalEvents(); 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci // The following methods are only used for reporting nested cpp events 631cb0ef41Sopenharmony_ci // through V8. Standalone events are reported directly. 641cb0ef41Sopenharmony_ci bool FullGCMetricsReportPending() const; 651cb0ef41Sopenharmony_ci bool YoungGCMetricsReportPending() const; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci const base::Optional<cppgc::internal::MetricRecorder::GCCycle> 681cb0ef41Sopenharmony_ci ExtractLastFullGcEvent(); 691cb0ef41Sopenharmony_ci const base::Optional<cppgc::internal::MetricRecorder::GCCycle> 701cb0ef41Sopenharmony_ci ExtractLastYoungGcEvent(); 711cb0ef41Sopenharmony_ci const base::Optional< 721cb0ef41Sopenharmony_ci cppgc::internal::MetricRecorder::MainThreadIncrementalMark> 731cb0ef41Sopenharmony_ci ExtractLastIncrementalMarkEvent(); 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci void ClearCachedEvents(); 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci private: 781cb0ef41Sopenharmony_ci Isolate* GetIsolate() const; 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci v8::metrics::Recorder::ContextId GetContextId() const; 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci CppHeap& cpp_heap_; 831cb0ef41Sopenharmony_ci v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalMark 841cb0ef41Sopenharmony_ci incremental_mark_batched_events_; 851cb0ef41Sopenharmony_ci v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalSweep 861cb0ef41Sopenharmony_ci incremental_sweep_batched_events_; 871cb0ef41Sopenharmony_ci base::Optional<cppgc::internal::MetricRecorder::GCCycle> 881cb0ef41Sopenharmony_ci last_full_gc_event_; 891cb0ef41Sopenharmony_ci base::Optional<cppgc::internal::MetricRecorder::GCCycle> 901cb0ef41Sopenharmony_ci last_young_gc_event_; 911cb0ef41Sopenharmony_ci base::Optional<cppgc::internal::MetricRecorder::MainThreadIncrementalMark> 921cb0ef41Sopenharmony_ci last_incremental_mark_event_; 931cb0ef41Sopenharmony_ci }; 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci class PauseConcurrentMarkingScope final { 961cb0ef41Sopenharmony_ci public: 971cb0ef41Sopenharmony_ci explicit PauseConcurrentMarkingScope(CppHeap*); 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci private: 1001cb0ef41Sopenharmony_ci base::Optional<cppgc::internal::MarkerBase::PauseConcurrentMarkingScope> 1011cb0ef41Sopenharmony_ci pause_scope_; 1021cb0ef41Sopenharmony_ci }; 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_ci static CppHeap* From(v8::CppHeap* heap) { 1051cb0ef41Sopenharmony_ci return static_cast<CppHeap*>(heap); 1061cb0ef41Sopenharmony_ci } 1071cb0ef41Sopenharmony_ci static const CppHeap* From(const v8::CppHeap* heap) { 1081cb0ef41Sopenharmony_ci return static_cast<const CppHeap*>(heap); 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci CppHeap( 1121cb0ef41Sopenharmony_ci v8::Platform* platform, 1131cb0ef41Sopenharmony_ci const std::vector<std::unique_ptr<cppgc::CustomSpaceBase>>& custom_spaces, 1141cb0ef41Sopenharmony_ci const v8::WrapperDescriptor& wrapper_descriptor); 1151cb0ef41Sopenharmony_ci ~CppHeap() final; 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci CppHeap(const CppHeap&) = delete; 1181cb0ef41Sopenharmony_ci CppHeap& operator=(const CppHeap&) = delete; 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci HeapBase& AsBase() { return *this; } 1211cb0ef41Sopenharmony_ci const HeapBase& AsBase() const { return *this; } 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci void AttachIsolate(Isolate* isolate); 1241cb0ef41Sopenharmony_ci void DetachIsolate(); 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci void Terminate(); 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci void EnableDetachedGarbageCollectionsForTesting(); 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci void CollectGarbageForTesting(CollectionType, StackState); 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci void CollectCustomSpaceStatisticsAtLastGC( 1331cb0ef41Sopenharmony_ci std::vector<cppgc::CustomSpaceIndex>, 1341cb0ef41Sopenharmony_ci std::unique_ptr<CustomSpaceStatisticsReceiver>); 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci void FinishSweepingIfRunning(); 1371cb0ef41Sopenharmony_ci void FinishSweepingIfOutOfWork(); 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci void InitializeTracing( 1401cb0ef41Sopenharmony_ci cppgc::internal::GarbageCollector::Config::CollectionType, 1411cb0ef41Sopenharmony_ci GarbageCollectionFlags); 1421cb0ef41Sopenharmony_ci void StartTracing(); 1431cb0ef41Sopenharmony_ci bool AdvanceTracing(double max_duration); 1441cb0ef41Sopenharmony_ci bool IsTracingDone(); 1451cb0ef41Sopenharmony_ci void TraceEpilogue(); 1461cb0ef41Sopenharmony_ci void EnterFinalPause(cppgc::EmbedderStackState stack_state); 1471cb0ef41Sopenharmony_ci bool FinishConcurrentMarkingIfNeeded(); 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci void RunMinorGC(StackState); 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci // StatsCollector::AllocationObserver interface. 1521cb0ef41Sopenharmony_ci void AllocatedObjectSizeIncreased(size_t) final; 1531cb0ef41Sopenharmony_ci void AllocatedObjectSizeDecreased(size_t) final; 1541cb0ef41Sopenharmony_ci void ResetAllocatedObjectSize(size_t) final {} 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci MetricRecorderAdapter* GetMetricRecorder() const; 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci v8::WrapperDescriptor wrapper_descriptor() const { 1591cb0ef41Sopenharmony_ci return wrapper_descriptor_; 1601cb0ef41Sopenharmony_ci } 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci Isolate* isolate() const { return isolate_; } 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci std::unique_ptr<CppMarkingState> CreateCppMarkingState(); 1651cb0ef41Sopenharmony_ci std::unique_ptr<CppMarkingState> CreateCppMarkingStateForMutatorThread(); 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci private: 1681cb0ef41Sopenharmony_ci void FinalizeIncrementalGarbageCollectionIfNeeded( 1691cb0ef41Sopenharmony_ci cppgc::Heap::StackState) final { 1701cb0ef41Sopenharmony_ci // For unified heap, CppHeap shouldn't finalize independently (i.e. 1711cb0ef41Sopenharmony_ci // finalization is not needed) thus this method is left empty. 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci void ReportBufferedAllocationSizeIfPossible(); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci void StartIncrementalGarbageCollectionForTesting() final; 1771cb0ef41Sopenharmony_ci void FinalizeIncrementalGarbageCollectionForTesting( 1781cb0ef41Sopenharmony_ci cppgc::EmbedderStackState) final; 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci MarkingType SelectMarkingType() const; 1811cb0ef41Sopenharmony_ci SweepingType SelectSweepingType() const; 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci Isolate* isolate_ = nullptr; 1841cb0ef41Sopenharmony_ci bool marking_done_ = false; 1851cb0ef41Sopenharmony_ci // |collection_type_| is initialized when marking is in progress. 1861cb0ef41Sopenharmony_ci base::Optional<cppgc::internal::GarbageCollector::Config::CollectionType> 1871cb0ef41Sopenharmony_ci collection_type_; 1881cb0ef41Sopenharmony_ci GarbageCollectionFlags current_gc_flags_; 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci // Buffered allocated bytes. Reporting allocated bytes to V8 can trigger a GC 1911cb0ef41Sopenharmony_ci // atomic pause. Allocated bytes are buffer in case this is temporarily 1921cb0ef41Sopenharmony_ci // prohibited. 1931cb0ef41Sopenharmony_ci int64_t buffered_allocated_bytes_ = 0; 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci v8::WrapperDescriptor wrapper_descriptor_; 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci bool in_detached_testing_mode_ = false; 1981cb0ef41Sopenharmony_ci bool force_incremental_marking_for_testing_ = false; 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci bool is_in_v8_marking_step_ = false; 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci friend class MetricRecorderAdapter; 2031cb0ef41Sopenharmony_ci}; 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ciDEFINE_OPERATORS_FOR_FLAGS(CppHeap::GarbageCollectionFlags) 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci} // namespace internal 2081cb0ef41Sopenharmony_ci} // namespace v8 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci#endif // V8_HEAP_CPPGC_JS_CPP_HEAP_H_ 211