Commit b91727ed authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

Revert "[bindings,heap] Prepare PerIsolateData for holding different heap tracer"

This reverts commit 1186c664.

Reason for revert: Temporary reverting to investigate micro benchmark regression.

No-try: true
Bug: chromium:872581

Original change's description:
> [bindings,heap] Prepare PerIsolateData for holding different heap tracer
>
> - Prepare V8PerIsolateData for holding V8HeapController.
> - Harden existing tests to swap in the expected visitor/controller. This way it
>   is possible to test ScriptWrappableVisitor while already running on a different
>   embedder heap tracer.
>
> Change-Id: I169de233a4dd9886d153e7d97ca63e7caee0d809
> Bug: chromium:843903
> Reviewed-on: https://chromium-review.googlesource.com/1160656
> Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
> Reviewed-by: Kentaro Hara <haraken@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#580892}

TBR=haraken@chromium.org,mlippautz@chromium.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: chromium:843903
Change-Id: I75383f8b0fd825fdaf04202df3cc6a2ac312bb9b
Reviewed-on: https://chromium-review.googlesource.com/1170743
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: default avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#582141}
parent 0cca86c6
......@@ -16,123 +16,31 @@
namespace blink {
namespace {
// Temporarily swaps out the underlying v8 heap controller from a given
// v8::Isolate. Gracefully finalized potentially running garbage collections.
class TemporaryV8HeapControllerScope {
WTF_MAKE_NONCOPYABLE(TemporaryV8HeapControllerScope);
STACK_ALLOCATED();
public:
TemporaryV8HeapControllerScope(v8::Isolate* isolate,
std::unique_ptr<V8HeapController> controller)
: isolate_(isolate), saved_controller_(std::move(controller)) {
SwapWithV8PerIsolateDataVisitor();
}
~TemporaryV8HeapControllerScope() { SwapWithV8PerIsolateDataVisitor(); }
V8HeapController* CurrentController() {
return V8PerIsolateData::From(isolate_)->GetV8HeapController();
}
private:
void SwapWithV8PerIsolateDataVisitor() {
V8HeapController* current = CurrentController();
if (current)
current->FinalizeAndCleanup();
V8PerIsolateData::From(isolate_)->SwapV8HeapController(saved_controller_);
isolate_->SetEmbedderHeapTracer(CurrentController());
}
v8::Isolate* const isolate_;
std::unique_ptr<V8HeapController> saved_controller_;
};
class InterceptingScriptWrappableMarkingVisitor
: public blink::ScriptWrappableMarkingVisitor {
public:
InterceptingScriptWrappableMarkingVisitor(v8::Isolate* isolate)
: ScriptWrappableMarkingVisitor(isolate),
marked_wrappers_(new size_t(0)) {}
~InterceptingScriptWrappableMarkingVisitor() override {
delete marked_wrappers_;
}
void Visit(const TraceWrapperV8Reference<v8::Value>&) override {
*marked_wrappers_ += 1;
// Do not actually mark this visitor, as this would call into v8, which
// would require executing an actual GC.
}
size_t NumberOfMarkedWrappers() const { return *marked_wrappers_; }
void Start() { TracePrologue(); }
void End() {
// Gracefully terminate tracing.
AdvanceTracing(
0,
v8::EmbedderHeapTracer::AdvanceTracingActions(
v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
AbortTracing();
}
private:
size_t* marked_wrappers_; // Indirection required because of const override.
};
class InterceptingScriptWrappableMarkingVisitorScope
: public TemporaryV8HeapControllerScope {
WTF_MAKE_NONCOPYABLE(InterceptingScriptWrappableMarkingVisitorScope);
STACK_ALLOCATED();
public:
InterceptingScriptWrappableMarkingVisitorScope(v8::Isolate* isolate)
: TemporaryV8HeapControllerScope(
isolate,
std::unique_ptr<InterceptingScriptWrappableMarkingVisitor>{
new InterceptingScriptWrappableMarkingVisitor(isolate)}) {
Visitor()->Start();
}
virtual ~InterceptingScriptWrappableMarkingVisitorScope() {
Visitor()->End();
}
InterceptingScriptWrappableMarkingVisitor* Visitor() {
return static_cast<InterceptingScriptWrappableMarkingVisitor*>(
CurrentController());
}
};
void PreciselyCollectGarbage() {
static void PreciselyCollectGarbage() {
ThreadState::Current()->CollectAllGarbage();
}
void RunV8Scavenger(v8::Isolate* isolate) {
static void RunV8Scavenger(v8::Isolate* isolate) {
V8GCController::CollectGarbage(isolate, true);
}
void RunV8FullGc(v8::Isolate* isolate) {
static void RunV8FullGc(v8::Isolate* isolate) {
V8GCController::CollectGarbage(isolate, false);
}
} // namespace
TEST(ScriptWrappableMarkingVisitorTest,
ScriptWrappableMarkingVisitorTracesWrappers) {
V8TestingScope testing_scope;
// The graph needs to be set up before starting tracing as otherwise the
// conservative write barrier would trigger.
V8TestingScope scope;
ScriptWrappableMarkingVisitor* visitor =
V8PerIsolateData::From(scope.GetIsolate())
->GetScriptWrappableMarkingVisitor();
DeathAwareScriptWrappable* target = DeathAwareScriptWrappable::Create();
DeathAwareScriptWrappable* dependency = DeathAwareScriptWrappable::Create();
target->SetWrappedDependency(dependency);
InterceptingScriptWrappableMarkingVisitorScope intercepting_scope(
testing_scope.GetIsolate());
ScriptWrappableMarkingVisitor* visitor = intercepting_scope.Visitor();
// The graph needs to be set up before starting tracing as otherwise the
// conservative write barrier would trigger.
visitor->TracePrologue();
HeapObjectHeader* target_header = HeapObjectHeader::FromPayload(target);
HeapObjectHeader* dependency_header =
......@@ -153,6 +61,8 @@ TEST(ScriptWrappableMarkingVisitorTest,
EXPECT_EQ(visitor->MarkingDeque()->size(), 0ul);
EXPECT_TRUE(target_header->IsWrapperHeaderMarked());
EXPECT_TRUE(dependency_header->IsWrapperHeaderMarked());
visitor->AbortTracing();
}
TEST(ScriptWrappableMarkingVisitorTest,
......@@ -235,47 +145,51 @@ TEST(ScriptWrappableMarkingVisitorTest, V8ReportsLiveObjectsDuringFullGc) {
}
TEST(ScriptWrappableMarkingVisitorTest, OilpanClearsHeadersWhenObjectDied) {
V8TestingScope testing_scope;
V8TestingScope scope;
DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::Create();
// The graph needs to be set up before starting tracing as otherwise the
// conservative write barrier would trigger.
InterceptingScriptWrappableMarkingVisitorScope intercepting_scope(
testing_scope.GetIsolate());
ScriptWrappableMarkingVisitor* visitor = intercepting_scope.Visitor();
ScriptWrappableMarkingVisitor* visitor =
V8PerIsolateData::From(scope.GetIsolate())
->GetScriptWrappableMarkingVisitor();
visitor->TracePrologue();
auto* header = HeapObjectHeader::FromPayload(object);
visitor->headers_to_unmark_.push_back(header);
PreciselyCollectGarbage();
EXPECT_FALSE(visitor->headers_to_unmark_.Contains(header));
visitor->AbortTracing();
}
TEST(ScriptWrappableMarkingVisitorTest,
OilpanClearsMarkingDequeWhenObjectDied) {
V8TestingScope testing_scope;
V8TestingScope scope;
DeathAwareScriptWrappable* object = DeathAwareScriptWrappable::Create();
// The graph needs to be set up before starting tracing as otherwise the
// conservative write barrier would trigger.
InterceptingScriptWrappableMarkingVisitorScope intercepting_scope(
testing_scope.GetIsolate());
ScriptWrappableMarkingVisitor* visitor = intercepting_scope.Visitor();
ScriptWrappableMarkingVisitor* visitor =
V8PerIsolateData::From(scope.GetIsolate())
->GetScriptWrappableMarkingVisitor();
visitor->TracePrologue();
visitor->TraceWithWrappers(object);
EXPECT_EQ(visitor->MarkingDeque()->front().RawObjectPointer(), object);
PreciselyCollectGarbage();
EXPECT_EQ(visitor->MarkingDeque()->front().RawObjectPointer(), nullptr);
visitor->AbortTracing();
}
TEST(ScriptWrappableMarkingVisitorTest,
MarkedObjectDoesNothingOnWriteBarrierHitWhenDependencyIsMarkedToo) {
V8TestingScope testing_scope;
InterceptingScriptWrappableMarkingVisitorScope intercepting_scope(
testing_scope.GetIsolate());
ScriptWrappableMarkingVisitor* visitor = intercepting_scope.Visitor();
V8TestingScope scope;
ScriptWrappableMarkingVisitor* visitor =
V8PerIsolateData::From(scope.GetIsolate())
->GetScriptWrappableMarkingVisitor();
visitor->TracePrologue();
DeathAwareScriptWrappable* target = DeathAwareScriptWrappable::Create();
DeathAwareScriptWrappable* dependencies[] = {
......@@ -288,18 +202,23 @@ TEST(ScriptWrappableMarkingVisitorTest,
}
EXPECT_TRUE(visitor->MarkingDeque()->IsEmpty());
target->SetWrappedDependency(dependencies[0]);
target->AddWrappedVectorDependency(dependencies[1]);
target->AddWrappedHashMapDependency(dependencies[2], dependencies[3]);
EXPECT_TRUE(visitor->MarkingDeque()->IsEmpty());
visitor->AbortTracing();
}
TEST(ScriptWrappableMarkingVisitorTest,
MarkedObjectMarksDependencyOnWriteBarrierHitWhenNotMarked) {
V8TestingScope testing_scope;
InterceptingScriptWrappableMarkingVisitorScope intercepting_scope(
testing_scope.GetIsolate());
ScriptWrappableMarkingVisitor* visitor = intercepting_scope.Visitor();
V8TestingScope scope;
ScriptWrappableMarkingVisitor* visitor =
V8PerIsolateData::From(scope.GetIsolate())
->GetScriptWrappableMarkingVisitor();
visitor->TracePrologue();
DeathAwareScriptWrappable* target = DeathAwareScriptWrappable::Create();
DeathAwareScriptWrappable* dependencies[] = {
......@@ -317,6 +236,8 @@ TEST(ScriptWrappableMarkingVisitorTest,
for (int i = 0; i < 4; i++) {
EXPECT_TRUE(visitor->MarkingDequeContains(dependencies[i]));
}
visitor->AbortTracing();
}
namespace {
......@@ -341,6 +262,63 @@ class HandleContainer
TraceWrapperV8Reference<v8::String> handle_;
};
class InterceptingScriptWrappableMarkingVisitor
: public blink::ScriptWrappableMarkingVisitor {
public:
InterceptingScriptWrappableMarkingVisitor(v8::Isolate* isolate)
: ScriptWrappableMarkingVisitor(isolate),
marked_wrappers_(new size_t(0)) {}
~InterceptingScriptWrappableMarkingVisitor() override {
delete marked_wrappers_;
}
void Visit(const TraceWrapperV8Reference<v8::Value>&) override {
*marked_wrappers_ += 1;
// Do not actually mark this visitor, as this would call into v8, which
// would require executing an actual GC.
}
size_t NumberOfMarkedWrappers() const { return *marked_wrappers_; }
void Start() { TracePrologue(); }
void end() {
// Gracefully terminate tracing.
AdvanceTracing(
0,
v8::EmbedderHeapTracer::AdvanceTracingActions(
v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
AbortTracing();
}
private:
size_t* marked_wrappers_; // Indirection required because of const override.
};
class InterceptingScriptWrappableMarkingVisitorScope
: public V8PerIsolateData::TemporaryScriptWrappableVisitorScope {
WTF_MAKE_NONCOPYABLE(InterceptingScriptWrappableMarkingVisitorScope);
STACK_ALLOCATED();
public:
InterceptingScriptWrappableMarkingVisitorScope(v8::Isolate* isolate)
: V8PerIsolateData::TemporaryScriptWrappableVisitorScope(
isolate,
std::unique_ptr<InterceptingScriptWrappableMarkingVisitor>(
new InterceptingScriptWrappableMarkingVisitor(isolate))) {
Visitor()->Start();
}
virtual ~InterceptingScriptWrappableMarkingVisitorScope() {
Visitor()->end();
}
InterceptingScriptWrappableMarkingVisitor* Visitor() {
return reinterpret_cast<InterceptingScriptWrappableMarkingVisitor*>(
CurrentVisitor());
}
};
} // namespace
TEST(ScriptWrappableMarkingVisitorTest, WriteBarrierOnUnmarkedContainer) {
......@@ -378,12 +356,25 @@ TEST(ScriptWrappableMarkingVisitorTest, WriteBarrierTriggersOnMarkedContainer) {
CHECK_EQ(1u, raw_visitor->NumberOfMarkedWrappers());
}
TEST(ScriptWrappableMarkingVisitorTest, VtableAtObjectStart) {
// This test makes sure that the subobject v8::EmbedderHeapTracer is placed
// at the start of a ScriptWrappableMarkingVisitor object. We do this to
// mitigate potential problems that could be caused by LTO when passing
// v8::EmbedderHeapTracer across the API boundary.
V8TestingScope scope;
std::unique_ptr<blink::ScriptWrappableMarkingVisitor> visitor(
new ScriptWrappableMarkingVisitor(scope.GetIsolate()));
CHECK_EQ(
static_cast<void*>(visitor.get()),
static_cast<void*>(dynamic_cast<v8::EmbedderHeapTracer*>(visitor.get())));
}
TEST(ScriptWrappableMarkingVisitor, WriteBarrierForScriptWrappable) {
// Regression test for crbug.com/702490.
V8TestingScope scope;
InterceptingScriptWrappableMarkingVisitorScope intercepting_scope(
InterceptingScriptWrappableMarkingVisitorScope visitor_scope(
scope.GetIsolate());
auto* raw_visitor = intercepting_scope.Visitor();
auto* raw_visitor = visitor_scope.Visitor();
// Mark the ScriptWrappable.
DeathAwareScriptWrappable* target = DeathAwareScriptWrappable::Create();
......@@ -405,6 +396,9 @@ TEST(ScriptWrappableMarkingVisitor, WriteBarrierForScriptWrappable) {
TEST(ScriptWrappableMarkingVisitorTest, WriteBarrierOnHeapVectorSwap1) {
V8TestingScope scope;
ScriptWrappableMarkingVisitor* visitor =
V8PerIsolateData::From(scope.GetIsolate())
->GetScriptWrappableMarkingVisitor();
HeapVector<DeathAwareScriptWrappable::Wrapper> vector1;
DeathAwareScriptWrappable* entry1 = DeathAwareScriptWrappable::Create();
......@@ -413,18 +407,22 @@ TEST(ScriptWrappableMarkingVisitorTest, WriteBarrierOnHeapVectorSwap1) {
DeathAwareScriptWrappable* entry2 = DeathAwareScriptWrappable::Create();
vector2.push_back(entry2);
InterceptingScriptWrappableMarkingVisitorScope intercepting_scope(
scope.GetIsolate());
ScriptWrappableMarkingVisitor* visitor = intercepting_scope.Visitor();
visitor->TracePrologue();
EXPECT_TRUE(visitor->MarkingDeque()->IsEmpty());
swap(vector1, vector2);
EXPECT_TRUE(visitor->MarkingDequeContains(entry1));
EXPECT_TRUE(visitor->MarkingDequeContains(entry2));
visitor->AbortTracing();
}
TEST(ScriptWrappableMarkingVisitorTest, WriteBarrierOnHeapVectorSwap2) {
V8TestingScope scope;
ScriptWrappableMarkingVisitor* visitor =
V8PerIsolateData::From(scope.GetIsolate())
->GetScriptWrappableMarkingVisitor();
HeapVector<DeathAwareScriptWrappable::Wrapper> vector1;
DeathAwareScriptWrappable* entry1 = DeathAwareScriptWrappable::Create();
......@@ -433,15 +431,16 @@ TEST(ScriptWrappableMarkingVisitorTest, WriteBarrierOnHeapVectorSwap2) {
DeathAwareScriptWrappable* entry2 = DeathAwareScriptWrappable::Create();
vector2.push_back(entry2);
InterceptingScriptWrappableMarkingVisitorScope intercepting_scope(
scope.GetIsolate());
ScriptWrappableMarkingVisitor* visitor = intercepting_scope.Visitor();
visitor->TracePrologue();
EXPECT_TRUE(visitor->MarkingDeque()->IsEmpty());
swap(vector1, vector2);
// Only entry2 is held alive by TraceWrapperMember, so we only expect this
// barrier to fire.
EXPECT_TRUE(visitor->MarkingDequeContains(entry2));
visitor->AbortTracing();
}
namespace {
......@@ -496,6 +495,9 @@ class Base : public blink::GarbageCollected<Base>,
TEST(ScriptWrappableMarkingVisitorTest, MixinTracing) {
V8TestingScope scope;
ScriptWrappableMarkingVisitor* visitor =
V8PerIsolateData::From(scope.GetIsolate())
->GetScriptWrappableMarkingVisitor();
DeathAwareScriptWrappable* base_wrapper = DeathAwareScriptWrappable::Create();
DeathAwareScriptWrappable* mixin_wrapper =
......@@ -508,9 +510,7 @@ TEST(ScriptWrappableMarkingVisitorTest, MixinTracing) {
// Make sure that mixin does not point to the object header.
EXPECT_NE(static_cast<void*>(base), static_cast<void*>(mixin));
InterceptingScriptWrappableMarkingVisitorScope intercepting_scope(
scope.GetIsolate());
ScriptWrappableMarkingVisitor* visitor = intercepting_scope.Visitor();
visitor->TracePrologue();
EXPECT_TRUE(visitor->MarkingDeque()->IsEmpty());
......@@ -531,6 +531,7 @@ TEST(ScriptWrappableMarkingVisitorTest, MixinTracing) {
HeapObjectHeader::FromPayload(mixin_wrapper)->IsWrapperHeaderMarked());
mixin_handle = nullptr;
visitor->AbortTracing();
}
} // namespace blink
......@@ -65,7 +65,6 @@
#include "third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
#include "third_party/blink/renderer/platform/heap/v8_heap_controller.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
......@@ -623,11 +622,12 @@ static void HostGetImportMetaProperties(v8::Local<v8::Context> context,
static void InitializeV8Common(v8::Isolate* isolate) {
isolate->AddGCPrologueCallback(V8GCController::GcPrologue);
isolate->AddGCEpilogueCallback(V8GCController::GcEpilogue);
V8PerIsolateData::From(isolate)->SetV8HeapController(
std::unique_ptr<V8HeapController>{
new ScriptWrappableMarkingVisitor(isolate)});
std::unique_ptr<ScriptWrappableMarkingVisitor> visitor(
new ScriptWrappableMarkingVisitor(isolate));
V8PerIsolateData::From(isolate)->SetScriptWrappableMarkingVisitor(
std::move(visitor));
isolate->SetEmbedderHeapTracer(
V8PerIsolateData::From(isolate)->GetV8HeapController());
V8PerIsolateData::From(isolate)->GetScriptWrappableMarkingVisitor());
isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped);
......
......@@ -67,7 +67,6 @@ void ScriptWrappableMarkingVisitor::TraceEpilogue() {
}
void ScriptWrappableMarkingVisitor::AbortTracing() {
CHECK(tracing_in_progress_);
CHECK(ThreadState::Current());
should_cleanup_ = true;
tracing_in_progress_ = false;
......@@ -219,12 +218,10 @@ void ScriptWrappableMarkingVisitor::MarkWrapperHeader(
void ScriptWrappableMarkingVisitor::WriteBarrier(
v8::Isolate* isolate,
const TraceWrapperV8Reference<v8::Value>& dst_object) {
if (!ThreadState::IsAnyWrapperTracing() || dst_object.IsEmpty())
return;
ScriptWrappableMarkingVisitor* visitor = CurrentVisitor(isolate);
if (!visitor->WrapperTracingInProgress())
if (dst_object.IsEmpty() || !visitor->WrapperTracingInProgress())
return;
// Conservatively assume that the source object containing |dst_object| is
// marked.
visitor->Trace(dst_object);
......@@ -234,9 +231,6 @@ void ScriptWrappableMarkingVisitor::WriteBarrier(
v8::Isolate* isolate,
DOMWrapperMap<ScriptWrappable>* wrapper_map,
ScriptWrappable* key) {
if (!ThreadState::IsAnyWrapperTracing())
return;
ScriptWrappableMarkingVisitor* visitor = CurrentVisitor(isolate);
if (!visitor->WrapperTracingInProgress())
return;
......@@ -309,32 +303,24 @@ void ScriptWrappableMarkingVisitor::InvalidateDeadObjectsInMarkingDeque() {
}
}
void ScriptWrappableMarkingVisitor::FinalizeAndCleanup() {
FinalizeTracing();
PerformCleanup();
}
void ScriptWrappableMarkingVisitor::InvalidateDeadObjectsInMarkingDeque(
v8::Isolate* isolate) {
ScriptWrappableMarkingVisitor* script_wrappable_visitor =
static_cast<ScriptWrappableMarkingVisitor*>(
V8PerIsolateData::From(isolate)->GetV8HeapController());
V8PerIsolateData::From(isolate)->GetScriptWrappableMarkingVisitor();
if (script_wrappable_visitor)
script_wrappable_visitor->InvalidateDeadObjectsInMarkingDeque();
}
void ScriptWrappableMarkingVisitor::PerformCleanup(v8::Isolate* isolate) {
ScriptWrappableMarkingVisitor* script_wrappable_visitor =
static_cast<ScriptWrappableMarkingVisitor*>(
V8PerIsolateData::From(isolate)->GetV8HeapController());
V8PerIsolateData::From(isolate)->GetScriptWrappableMarkingVisitor();
if (script_wrappable_visitor)
script_wrappable_visitor->PerformCleanup();
}
ScriptWrappableMarkingVisitor* ScriptWrappableMarkingVisitor::CurrentVisitor(
v8::Isolate* isolate) {
return static_cast<ScriptWrappableMarkingVisitor*>(
V8PerIsolateData::From(isolate)->GetV8HeapController());
return V8PerIsolateData::From(isolate)->GetScriptWrappableMarkingVisitor();
}
bool ScriptWrappableMarkingVisitor::MarkingDequeContains(void* needle) {
......
......@@ -9,7 +9,6 @@
#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h"
#include "third_party/blink/renderer/platform/heap/heap_page.h"
#include "third_party/blink/renderer/platform/heap/threading_traits.h"
#include "third_party/blink/renderer/platform/heap/v8_heap_controller.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
......@@ -30,8 +29,8 @@ class TraceWrapperV8Reference;
// reachable wrappers. V8 calls this visitor during its garbage collection,
// see v8::EmbedderHeapTracer.
class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
: public ScriptWrappableVisitor,
public V8HeapController {
: public v8::EmbedderHeapTracer,
public ScriptWrappableVisitor {
DISALLOW_IMPLICIT_CONSTRUCTORS(ScriptWrappableMarkingVisitor);
public:
......@@ -70,6 +69,7 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
bool WrapperTracingInProgress() const { return tracing_in_progress_; }
// v8::EmbedderHeapTracer interface.
void TracePrologue() override;
void RegisterV8References(const std::vector<std::pair<void*, void*>>&
internal_fields_of_potential_wrappers) override;
......@@ -81,10 +81,8 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
void EnterFinalPause() override;
size_t NumberOfWrappersToTrace() override;
// V8HeapController interface.
void FinalizeAndCleanup() override;
// ScriptWrappableVisitor interface.
void Visit(const TraceWrapperV8Reference<v8::Value>&) override;
void VisitWithWrappers(void*, TraceDescriptor) override;
void Visit(DOMWrapperMap<ScriptWrappable>*,
......
......@@ -114,12 +114,13 @@ inline void V8DOMWrapper::SetNativeInfoInternal(
wrapper->SetAlignedPointerInInternalFields(base::size(indices), indices,
values);
auto* per_isolate_data = V8PerIsolateData::From(isolate);
// We notify V8HeapController about the new wrapper association,
// so the controller can make sure to trace the association (in case it is
// We notify ScriptWrappableVisitor about the new wrapper association,
// so the visitor can make sure to trace the association (in case it is
// currently tracing). Because of some optimizations, V8 will not
// necessarily detect wrappers created during its incremental marking.
per_isolate_data->GetV8HeapController()->RegisterV8References({std::make_pair(
const_cast<WrapperTypeInfo*>(wrapper_type_info), wrappable)});
per_isolate_data->GetScriptWrappableMarkingVisitor()->RegisterV8Reference(
std::make_pair(const_cast<WrapperTypeInfo*>(wrapper_type_info),
wrappable));
}
inline void V8DOMWrapper::ClearNativeInfo(v8::Isolate* isolate,
......
......@@ -153,8 +153,9 @@ void V8PerIsolateData::WillBeDestroyed(v8::Isolate* isolate) {
// Detach V8's garbage collector.
isolate->SetEmbedderHeapTracer(nullptr);
data->v8_heap_controller_->FinalizeAndCleanup();
data->v8_heap_controller_.reset();
if (data->script_wrappable_visitor_->WrapperTracingInProgress())
data->script_wrappable_visitor_->AbortTracing();
data->script_wrappable_visitor_.reset();
}
// destroy() clear things that should be cleared after ThreadState::detach()
......@@ -367,4 +368,16 @@ void V8PerIsolateData::AddActiveScriptWrappable(
active_script_wrappables_->insert(wrappable);
}
void V8PerIsolateData::TemporaryScriptWrappableVisitorScope::
SwapWithV8PerIsolateDataVisitor(
std::unique_ptr<ScriptWrappableMarkingVisitor>& visitor) {
ScriptWrappableMarkingVisitor* current = CurrentVisitor();
if (current)
ScriptWrappableMarkingVisitor::PerformCleanup(isolate_);
V8PerIsolateData::From(isolate_)->script_wrappable_visitor_.swap(
saved_visitor_);
isolate_->SetEmbedderHeapTracer(CurrentVisitor());
}
} // namespace blink
......@@ -33,9 +33,9 @@
#include "gin/public/isolate_holder.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h"
#include "third_party/blink/renderer/platform/bindings/v8_global_value_map.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/v8_heap_controller.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
......@@ -200,19 +200,41 @@ class PLATFORM_EXPORT V8PerIsolateData {
return active_script_wrappables_.Get();
}
void SetV8HeapController(std::unique_ptr<V8HeapController> controller) {
DCHECK(!v8_heap_controller_);
v8_heap_controller_ = std::move(controller);
}
class PLATFORM_EXPORT TemporaryScriptWrappableVisitorScope {
WTF_MAKE_NONCOPYABLE(TemporaryScriptWrappableVisitorScope);
STACK_ALLOCATED();
V8HeapController* GetV8HeapController() const {
return v8_heap_controller_.get();
public:
TemporaryScriptWrappableVisitorScope(
v8::Isolate* isolate,
std::unique_ptr<ScriptWrappableMarkingVisitor> visitor)
: isolate_(isolate), saved_visitor_(std::move(visitor)) {
SwapWithV8PerIsolateDataVisitor(saved_visitor_);
}
~TemporaryScriptWrappableVisitorScope() {
SwapWithV8PerIsolateDataVisitor(saved_visitor_);
}
void SwapV8HeapController(std::unique_ptr<V8HeapController>& other) {
v8_heap_controller_.swap(other);
inline ScriptWrappableMarkingVisitor* CurrentVisitor() {
return V8PerIsolateData::From(isolate_)
->GetScriptWrappableMarkingVisitor();
}
private:
void SwapWithV8PerIsolateDataVisitor(
std::unique_ptr<ScriptWrappableMarkingVisitor>&);
v8::Isolate* isolate_;
std::unique_ptr<ScriptWrappableMarkingVisitor> saved_visitor_;
};
void SetScriptWrappableMarkingVisitor(
std::unique_ptr<ScriptWrappableMarkingVisitor> visitor) {
script_wrappable_visitor_ = std::move(visitor);
}
ScriptWrappableMarkingVisitor* GetScriptWrappableMarkingVisitor() {
return script_wrappable_visitor_.get();
}
int IsNearV8HeapLimitHandled() { return handled_near_v8_heap_limit_; }
void HandledNearV8HeapLimit() { handled_near_v8_heap_limit_ = true; }
......@@ -284,8 +306,7 @@ class PLATFORM_EXPORT V8PerIsolateData {
std::unique_ptr<Data> thread_debugger_;
Persistent<ActiveScriptWrappableSet> active_script_wrappables_;
std::unique_ptr<V8HeapController> v8_heap_controller_;
std::unique_ptr<ScriptWrappableMarkingVisitor> script_wrappable_visitor_;
RuntimeCallStats runtime_call_stats_;
bool handled_near_v8_heap_limit_;
......
......@@ -79,7 +79,6 @@ blink_platform_sources("heap") {
"thread_state.h",
"threading_traits.h",
"trace_traits.h",
"v8_heap_controller.h",
"visitor.h",
"worklist.h",
]
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_HEAP_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_HEAP_CONTROLLER_H_
#include "v8/include/v8.h"
namespace blink {
// Common interface for all V8 heap tracers used in Blink.
class V8HeapController : public v8::EmbedderHeapTracer {
public:
~V8HeapController() override = default;
virtual void FinalizeAndCleanup() = 0;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_HEAP_CONTROLLER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment