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#include "src/heap/cppgc/gc-invoker.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <memory> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "include/cppgc/common.h" 101cb0ef41Sopenharmony_ci#include "include/cppgc/platform.h" 111cb0ef41Sopenharmony_ci#include "src/heap/cppgc/heap.h" 121cb0ef41Sopenharmony_ci#include "src/heap/cppgc/task-handle.h" 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_cinamespace cppgc { 151cb0ef41Sopenharmony_cinamespace internal { 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ciclass GCInvoker::GCInvokerImpl final : public GarbageCollector { 181cb0ef41Sopenharmony_ci public: 191cb0ef41Sopenharmony_ci GCInvokerImpl(GarbageCollector*, cppgc::Platform*, cppgc::Heap::StackSupport); 201cb0ef41Sopenharmony_ci ~GCInvokerImpl(); 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci GCInvokerImpl(const GCInvokerImpl&) = delete; 231cb0ef41Sopenharmony_ci GCInvokerImpl& operator=(const GCInvokerImpl&) = delete; 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_ci void CollectGarbage(GarbageCollector::Config) final; 261cb0ef41Sopenharmony_ci void StartIncrementalGarbageCollection(GarbageCollector::Config) final; 271cb0ef41Sopenharmony_ci size_t epoch() const final { return collector_->epoch(); } 281cb0ef41Sopenharmony_ci const EmbedderStackState* override_stack_state() const final { 291cb0ef41Sopenharmony_ci return collector_->override_stack_state(); 301cb0ef41Sopenharmony_ci } 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci private: 331cb0ef41Sopenharmony_ci class GCTask final : public cppgc::Task { 341cb0ef41Sopenharmony_ci public: 351cb0ef41Sopenharmony_ci using Handle = SingleThreadedHandle; 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci static Handle Post(GarbageCollector* collector, cppgc::TaskRunner* runner, 381cb0ef41Sopenharmony_ci GarbageCollector::Config config) { 391cb0ef41Sopenharmony_ci auto task = 401cb0ef41Sopenharmony_ci std::make_unique<GCInvoker::GCInvokerImpl::GCTask>(collector, config); 411cb0ef41Sopenharmony_ci auto handle = task->GetHandle(); 421cb0ef41Sopenharmony_ci runner->PostNonNestableTask(std::move(task)); 431cb0ef41Sopenharmony_ci return handle; 441cb0ef41Sopenharmony_ci } 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci explicit GCTask(GarbageCollector* collector, 471cb0ef41Sopenharmony_ci GarbageCollector::Config config) 481cb0ef41Sopenharmony_ci : collector_(collector), 491cb0ef41Sopenharmony_ci config_(config), 501cb0ef41Sopenharmony_ci handle_(Handle::NonEmptyTag{}), 511cb0ef41Sopenharmony_ci saved_epoch_(collector->epoch()) {} 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci private: 541cb0ef41Sopenharmony_ci void Run() final { 551cb0ef41Sopenharmony_ci CHECK_NULL(collector_->override_stack_state()); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci if (handle_.IsCanceled() || (collector_->epoch() != saved_epoch_)) return; 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci collector_->CollectGarbage(config_); 601cb0ef41Sopenharmony_ci handle_.Cancel(); 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci Handle GetHandle() { return handle_; } 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci GarbageCollector* collector_; 661cb0ef41Sopenharmony_ci GarbageCollector::Config config_; 671cb0ef41Sopenharmony_ci Handle handle_; 681cb0ef41Sopenharmony_ci size_t saved_epoch_; 691cb0ef41Sopenharmony_ci }; 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci GarbageCollector* collector_; 721cb0ef41Sopenharmony_ci cppgc::Platform* platform_; 731cb0ef41Sopenharmony_ci cppgc::Heap::StackSupport stack_support_; 741cb0ef41Sopenharmony_ci GCTask::Handle gc_task_handle_; 751cb0ef41Sopenharmony_ci}; 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ciGCInvoker::GCInvokerImpl::GCInvokerImpl(GarbageCollector* collector, 781cb0ef41Sopenharmony_ci cppgc::Platform* platform, 791cb0ef41Sopenharmony_ci cppgc::Heap::StackSupport stack_support) 801cb0ef41Sopenharmony_ci : collector_(collector), 811cb0ef41Sopenharmony_ci platform_(platform), 821cb0ef41Sopenharmony_ci stack_support_(stack_support) {} 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ciGCInvoker::GCInvokerImpl::~GCInvokerImpl() { 851cb0ef41Sopenharmony_ci if (gc_task_handle_) { 861cb0ef41Sopenharmony_ci gc_task_handle_.Cancel(); 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_civoid GCInvoker::GCInvokerImpl::CollectGarbage(GarbageCollector::Config config) { 911cb0ef41Sopenharmony_ci DCHECK_EQ(config.marking_type, cppgc::Heap::MarkingType::kAtomic); 921cb0ef41Sopenharmony_ci if ((config.stack_state == 931cb0ef41Sopenharmony_ci GarbageCollector::Config::StackState::kNoHeapPointers) || 941cb0ef41Sopenharmony_ci (stack_support_ == 951cb0ef41Sopenharmony_ci cppgc::Heap::StackSupport::kSupportsConservativeStackScan)) { 961cb0ef41Sopenharmony_ci collector_->CollectGarbage(config); 971cb0ef41Sopenharmony_ci } else if (platform_->GetForegroundTaskRunner() && 981cb0ef41Sopenharmony_ci platform_->GetForegroundTaskRunner()->NonNestableTasksEnabled()) { 991cb0ef41Sopenharmony_ci if (!gc_task_handle_) { 1001cb0ef41Sopenharmony_ci // Force a precise GC since it will run in a non-nestable task. 1011cb0ef41Sopenharmony_ci config.stack_state = 1021cb0ef41Sopenharmony_ci GarbageCollector::Config::StackState::kNoHeapPointers; 1031cb0ef41Sopenharmony_ci DCHECK_NE(cppgc::Heap::StackSupport::kSupportsConservativeStackScan, 1041cb0ef41Sopenharmony_ci stack_support_); 1051cb0ef41Sopenharmony_ci gc_task_handle_ = GCTask::Post( 1061cb0ef41Sopenharmony_ci collector_, platform_->GetForegroundTaskRunner().get(), config); 1071cb0ef41Sopenharmony_ci } 1081cb0ef41Sopenharmony_ci } 1091cb0ef41Sopenharmony_ci} 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_civoid GCInvoker::GCInvokerImpl::StartIncrementalGarbageCollection( 1121cb0ef41Sopenharmony_ci GarbageCollector::Config config) { 1131cb0ef41Sopenharmony_ci DCHECK_NE(config.marking_type, cppgc::Heap::MarkingType::kAtomic); 1141cb0ef41Sopenharmony_ci if ((stack_support_ != 1151cb0ef41Sopenharmony_ci cppgc::Heap::StackSupport::kSupportsConservativeStackScan) && 1161cb0ef41Sopenharmony_ci (!platform_->GetForegroundTaskRunner() || 1171cb0ef41Sopenharmony_ci !platform_->GetForegroundTaskRunner()->NonNestableTasksEnabled())) { 1181cb0ef41Sopenharmony_ci // In this configuration the GC finalization can only be triggered through 1191cb0ef41Sopenharmony_ci // ForceGarbageCollectionSlow. If incremental GC is started, there is no 1201cb0ef41Sopenharmony_ci // way to know how long it will remain enabled (and the write barrier with 1211cb0ef41Sopenharmony_ci // it). For that reason, we do not support running incremental GCs in this 1221cb0ef41Sopenharmony_ci // configuration. 1231cb0ef41Sopenharmony_ci return; 1241cb0ef41Sopenharmony_ci } 1251cb0ef41Sopenharmony_ci // No need to postpone starting incremental GC since the stack is not scanned 1261cb0ef41Sopenharmony_ci // until GC finalization. 1271cb0ef41Sopenharmony_ci collector_->StartIncrementalGarbageCollection(config); 1281cb0ef41Sopenharmony_ci} 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ciGCInvoker::GCInvoker(GarbageCollector* collector, cppgc::Platform* platform, 1311cb0ef41Sopenharmony_ci cppgc::Heap::StackSupport stack_support) 1321cb0ef41Sopenharmony_ci : impl_(std::make_unique<GCInvoker::GCInvokerImpl>(collector, platform, 1331cb0ef41Sopenharmony_ci stack_support)) {} 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ciGCInvoker::~GCInvoker() = default; 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_civoid GCInvoker::CollectGarbage(GarbageCollector::Config config) { 1381cb0ef41Sopenharmony_ci impl_->CollectGarbage(config); 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_civoid GCInvoker::StartIncrementalGarbageCollection( 1421cb0ef41Sopenharmony_ci GarbageCollector::Config config) { 1431cb0ef41Sopenharmony_ci impl_->StartIncrementalGarbageCollection(config); 1441cb0ef41Sopenharmony_ci} 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_cisize_t GCInvoker::epoch() const { return impl_->epoch(); } 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ciconst EmbedderStackState* GCInvoker::override_stack_state() const { 1491cb0ef41Sopenharmony_ci return impl_->override_stack_state(); 1501cb0ef41Sopenharmony_ci} 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci} // namespace internal 1531cb0ef41Sopenharmony_ci} // namespace cppgc 154