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