blob: 8243e9e36625ea47810e448b161defeb17710c4f [file] [log] [blame]
// 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-js/cpp-heap.h"
#include "include/cppgc/platform.h"
#include "include/v8-platform.h"
#include "include/v8.h"
#include "src/base/macros.h"
#include "src/base/platform/time.h"
#include "src/execution/isolate.h"
#include "src/flags/flags.h"
#include "src/heap/base/stack.h"
#include "src/heap/cppgc-js/unified-heap-marking-state.h"
#include "src/heap/cppgc-js/unified-heap-marking-visitor.h"
#include "src/heap/cppgc/gc-info-table.h"
#include "src/heap/cppgc/heap-base.h"
#include "src/heap/cppgc/heap-object-header.h"
#include "src/heap/cppgc/marker.h"
#include "src/heap/cppgc/marking-state.h"
#include "src/heap/cppgc/marking-visitor.h"
#include "src/heap/cppgc/object-allocator.h"
#include "src/heap/cppgc/prefinalizer-handler.h"
#include "src/heap/cppgc/stats-collector.h"
#include "src/heap/cppgc/sweeper.h"
#include "src/heap/marking-worklist.h"
#include "src/heap/sweeper.h"
#include "src/init/v8.h"
namespace v8 {
namespace internal {
namespace {
class CppgcPlatformAdapter final : public cppgc::Platform {
public:
explicit CppgcPlatformAdapter(v8::Isolate* isolate)
: platform_(V8::GetCurrentPlatform()), isolate_(isolate) {}
CppgcPlatformAdapter(const CppgcPlatformAdapter&) = delete;
CppgcPlatformAdapter& operator=(const CppgcPlatformAdapter&) = delete;
PageAllocator* GetPageAllocator() final {
return platform_->GetPageAllocator();
}
double MonotonicallyIncreasingTime() final {
return platform_->MonotonicallyIncreasingTime();
}
std::shared_ptr<TaskRunner> GetForegroundTaskRunner() final {
return platform_->GetForegroundTaskRunner(isolate_);
}
std::unique_ptr<JobHandle> PostJob(TaskPriority priority,
std::unique_ptr<JobTask> job_task) final {
return platform_->PostJob(priority, std::move(job_task));
}
private:
v8::Platform* platform_;
v8::Isolate* isolate_;
};
class UnifiedHeapMarker final : public cppgc::internal::MarkerBase {
public:
explicit UnifiedHeapMarker(Heap& v8_heap, cppgc::internal::HeapBase& heap);
~UnifiedHeapMarker() final = default;
void AddObject(void*);
protected:
cppgc::Visitor& visitor() final { return marking_visitor_; }
cppgc::internal::ConservativeTracingVisitor& conservative_visitor() final {
return conservative_marking_visitor_;
}
::heap::base::StackVisitor& stack_visitor() final {
return conservative_marking_visitor_;
}
private:
UnifiedHeapMarkingState unified_heap_mutator_marking_state_;
UnifiedHeapMarkingVisitor marking_visitor_;
cppgc::internal::ConservativeMarkingVisitor conservative_marking_visitor_;
};
UnifiedHeapMarker::UnifiedHeapMarker(Heap& v8_heap,
cppgc::internal::HeapBase& heap)
: cppgc::internal::MarkerBase(heap),
unified_heap_mutator_marking_state_(v8_heap),
marking_visitor_(heap, mutator_marking_state_,
unified_heap_mutator_marking_state_),
conservative_marking_visitor_(heap, mutator_marking_state_,
marking_visitor_) {}
void UnifiedHeapMarker::AddObject(void* object) {
mutator_marking_state_.MarkAndPush(
cppgc::internal::HeapObjectHeader::FromPayload(object));
}
} // namespace
CppHeap::CppHeap(v8::Isolate* isolate, size_t custom_spaces)
: cppgc::internal::HeapBase(std::make_shared<CppgcPlatformAdapter>(isolate),
custom_spaces),
isolate_(*reinterpret_cast<Isolate*>(isolate)) {
CHECK(!FLAG_incremental_marking_wrappers);
}
void CppHeap::RegisterV8References(
const std::vector<std::pair<void*, void*> >& embedder_fields) {
DCHECK(marker_);
for (auto& tuple : embedder_fields) {
// First field points to type.
// Second field points to object.
static_cast<UnifiedHeapMarker*>(marker_.get())->AddObject(tuple.second);
}
marking_done_ = false;
}
void CppHeap::TracePrologue(TraceFlags flags) {
marker_.reset(new UnifiedHeapMarker(*isolate_.heap(), AsBase()));
const UnifiedHeapMarker::MarkingConfig marking_config{
UnifiedHeapMarker::MarkingConfig::CollectionType::kMajor,
cppgc::Heap::StackState::kNoHeapPointers,
UnifiedHeapMarker::MarkingConfig::MarkingType::kAtomic};
marker_->StartMarking(marking_config);
marking_done_ = false;
}
bool CppHeap::AdvanceTracing(double deadline_in_ms) {
marking_done_ = marker_->AdvanceMarkingWithDeadline(
v8::base::TimeDelta::FromMillisecondsD(deadline_in_ms));
return marking_done_;
}
bool CppHeap::IsTracingDone() { return marking_done_; }
void CppHeap::EnterFinalPause(EmbedderStackState stack_state) {
const UnifiedHeapMarker::MarkingConfig marking_config{
UnifiedHeapMarker::MarkingConfig::CollectionType::kMajor,
cppgc::Heap::StackState::kNoHeapPointers,
UnifiedHeapMarker::MarkingConfig::MarkingType::kAtomic};
marker_->EnterAtomicPause(marking_config);
}
void CppHeap::TraceEpilogue(TraceSummary* trace_summary) {
CHECK(marking_done_);
marker_->LeaveAtomicPause();
{
// Pre finalizers are forbidden from allocating objects
cppgc::internal::ObjectAllocator::NoAllocationScope no_allocation_scope_(
object_allocator_);
marker()->ProcessWeakness();
prefinalizer_handler()->InvokePreFinalizers();
}
marker_.reset();
// TODO(chromium:1056170): replace build flag with dedicated flag.
#if DEBUG
VerifyMarking(cppgc::Heap::StackState::kNoHeapPointers);
#endif
{
NoGCScope no_gc(*this);
sweeper().Start(cppgc::internal::Sweeper::Config::kAtomic);
}
}
} // namespace internal
} // namespace v8