%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
// 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. #include "src/heap/cppgc/gc-invoker.h" #include <memory> #include "include/cppgc/platform.h" #include "src/heap/cppgc/heap.h" #include "src/heap/cppgc/task-handle.h" namespace cppgc { namespace internal { class GCInvoker::GCInvokerImpl final : public GarbageCollector { public: GCInvokerImpl(GarbageCollector*, cppgc::Platform*, cppgc::Heap::StackSupport); ~GCInvokerImpl(); GCInvokerImpl(const GCInvokerImpl&) = delete; GCInvokerImpl& operator=(const GCInvokerImpl&) = delete; void CollectGarbage(GarbageCollector::Config) final; void StartIncrementalGarbageCollection(GarbageCollector::Config) final; size_t epoch() const final { return collector_->epoch(); } private: class GCTask final : public cppgc::Task { public: using Handle = SingleThreadedHandle; static Handle Post(GarbageCollector* collector, cppgc::TaskRunner* runner, GarbageCollector::Config config) { auto task = std::make_unique<GCInvoker::GCInvokerImpl::GCTask>(collector, config); auto handle = task->GetHandle(); runner->PostNonNestableTask(std::move(task)); return handle; } explicit GCTask(GarbageCollector* collector, GarbageCollector::Config config) : collector_(collector), config_(config), handle_(Handle::NonEmptyTag{}), saved_epoch_(collector->epoch()) {} private: void Run() final { if (handle_.IsCanceled() || (collector_->epoch() != saved_epoch_)) return; collector_->CollectGarbage(config_); handle_.Cancel(); } Handle GetHandle() { return handle_; } GarbageCollector* collector_; GarbageCollector::Config config_; Handle handle_; size_t saved_epoch_; }; GarbageCollector* collector_; cppgc::Platform* platform_; cppgc::Heap::StackSupport stack_support_; GCTask::Handle gc_task_handle_; }; GCInvoker::GCInvokerImpl::GCInvokerImpl(GarbageCollector* collector, cppgc::Platform* platform, cppgc::Heap::StackSupport stack_support) : collector_(collector), platform_(platform), stack_support_(stack_support) {} GCInvoker::GCInvokerImpl::~GCInvokerImpl() { if (gc_task_handle_) { gc_task_handle_.Cancel(); } } void GCInvoker::GCInvokerImpl::CollectGarbage(GarbageCollector::Config config) { DCHECK_EQ(config.marking_type, cppgc::Heap::MarkingType::kAtomic); if ((config.stack_state == GarbageCollector::Config::StackState::kNoHeapPointers) || (stack_support_ == cppgc::Heap::StackSupport::kSupportsConservativeStackScan)) { collector_->CollectGarbage(config); } else if (platform_->GetForegroundTaskRunner() && platform_->GetForegroundTaskRunner()->NonNestableTasksEnabled()) { if (!gc_task_handle_) { // Force a precise GC since it will run in a non-nestable task. config.stack_state = GarbageCollector::Config::StackState::kNoHeapPointers; gc_task_handle_ = GCTask::Post( collector_, platform_->GetForegroundTaskRunner().get(), config); } } } void GCInvoker::GCInvokerImpl::StartIncrementalGarbageCollection( GarbageCollector::Config config) { DCHECK_NE(config.marking_type, cppgc::Heap::MarkingType::kAtomic); if ((stack_support_ != cppgc::Heap::StackSupport::kSupportsConservativeStackScan) && (!platform_->GetForegroundTaskRunner() || !platform_->GetForegroundTaskRunner()->NonNestableTasksEnabled())) { // In this configuration the GC finalization can only be triggered through // ForceGarbageCollectionSlow. If incremental GC is started, there is no // way to know how long it will remain enabled (and the write barrier with // it). For that reason, we do not support running incremental GCs in this // configuration. return; } // No need to postpone starting incremental GC since the stack is not scanned // until GC finalization. collector_->StartIncrementalGarbageCollection(config); } GCInvoker::GCInvoker(GarbageCollector* collector, cppgc::Platform* platform, cppgc::Heap::StackSupport stack_support) : impl_(std::make_unique<GCInvoker::GCInvokerImpl>(collector, platform, stack_support)) {} GCInvoker::~GCInvoker() = default; void GCInvoker::CollectGarbage(GarbageCollector::Config config) { impl_->CollectGarbage(config); } void GCInvoker::StartIncrementalGarbageCollection( GarbageCollector::Config config) { impl_->StartIncrementalGarbageCollection(config); } size_t GCInvoker::epoch() const { return impl_->epoch(); } } // namespace internal } // namespace cppgc