// Copyright 2016 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/embedder-tracing.h" #include "src/base/logging.h" #include "src/objects/embedder-data-slot.h" #include "src/objects/js-objects-inl.h" namespace v8 { namespace internal { void LocalEmbedderHeapTracer::SetRemoteTracer(EmbedderHeapTracer* tracer) { if (remote_tracer_) remote_tracer_->isolate_ = nullptr; remote_tracer_ = tracer; if (remote_tracer_) remote_tracer_->isolate_ = reinterpret_cast<v8::Isolate*>(isolate_); } void LocalEmbedderHeapTracer::TracePrologue() { if (!InUse()) return; num_v8_marking_worklist_was_empty_ = 0; embedder_worklist_empty_ = false; remote_tracer_->TracePrologue(); } void LocalEmbedderHeapTracer::TraceEpilogue() { if (!InUse()) return; remote_tracer_->TraceEpilogue(); } void LocalEmbedderHeapTracer::EnterFinalPause() { if (!InUse()) return; remote_tracer_->EnterFinalPause(embedder_stack_state_); // Resetting to state unknown as there may be follow up garbage collections // triggered from callbacks that have a different stack state. embedder_stack_state_ = EmbedderHeapTracer::kUnknown; } bool LocalEmbedderHeapTracer::Trace(double deadline) { if (!InUse()) return true; return remote_tracer_->AdvanceTracing(deadline); } bool LocalEmbedderHeapTracer::IsRemoteTracingDone() { return !InUse() || remote_tracer_->IsTracingDone(); } void LocalEmbedderHeapTracer::SetEmbedderStackStateForNextFinalization( EmbedderHeapTracer::EmbedderStackState stack_state) { if (!InUse()) return; embedder_stack_state_ = stack_state; } LocalEmbedderHeapTracer::ProcessingScope::ProcessingScope( LocalEmbedderHeapTracer* tracer) : tracer_(tracer) { wrapper_cache_.reserve(kWrapperCacheSize); } LocalEmbedderHeapTracer::ProcessingScope::~ProcessingScope() { if (!wrapper_cache_.empty()) { tracer_->remote_tracer()->RegisterV8References(std::move(wrapper_cache_)); } } void LocalEmbedderHeapTracer::ProcessingScope::TracePossibleWrapper( JSObject js_object) { DCHECK(js_object->IsApiWrapper()); if (js_object->GetEmbedderFieldCount() < 2) return; void* pointer0; void* pointer1; if (EmbedderDataSlot(js_object, 0).ToAlignedPointer(&pointer0) && pointer0 && EmbedderDataSlot(js_object, 1).ToAlignedPointer(&pointer1)) { wrapper_cache_.push_back({pointer0, pointer1}); } FlushWrapperCacheIfFull(); } void LocalEmbedderHeapTracer::ProcessingScope::FlushWrapperCacheIfFull() { if (wrapper_cache_.size() == wrapper_cache_.capacity()) { tracer_->remote_tracer()->RegisterV8References(std::move(wrapper_cache_)); wrapper_cache_.clear(); wrapper_cache_.reserve(kWrapperCacheSize); } } void LocalEmbedderHeapTracer::ProcessingScope::AddWrapperInfoForTesting( WrapperInfo info) { wrapper_cache_.push_back(info); FlushWrapperCacheIfFull(); } } // namespace internal } // namespace v8