Commit 3536bbb2 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

[oilpan] Detach V8 garbage colector before running termination GC

Any roots from V8 into Blink need to be cleared before running the termination
garbage collection to ensure that all objects die and finalizers are called.

Bug: chromium:831117
Change-Id: I09042623ceafe141819f4e9b52b15e784dd623a9
Reviewed-on: https://chromium-review.googlesource.com/1025032
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553487}
parent a9570434
...@@ -318,32 +318,68 @@ void V8GCController::CollectAllGarbageForTesting(v8::Isolate* isolate) { ...@@ -318,32 +318,68 @@ void V8GCController::CollectAllGarbageForTesting(v8::Isolate* isolate) {
v8::Isolate::kFullGarbageCollection); v8::Isolate::kFullGarbageCollection);
} }
class DOMWrapperTracer : public v8::PersistentHandleVisitor { namespace {
// Traces all DOM persistent handles using the provided visitor.
class DOMWrapperTracer final : public v8::PersistentHandleVisitor {
public: public:
explicit DOMWrapperTracer(Visitor* visitor) : visitor_(visitor) { explicit DOMWrapperTracer(Visitor* visitor) : visitor_(visitor) {
DCHECK(visitor_); DCHECK(visitor_);
} }
void VisitPersistentHandle(v8::Persistent<v8::Value>* value, void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
uint16_t class_id) override { uint16_t class_id) final {
if (class_id != WrapperTypeInfo::kNodeClassId && if (class_id != WrapperTypeInfo::kNodeClassId &&
class_id != WrapperTypeInfo::kObjectClassId) class_id != WrapperTypeInfo::kObjectClassId)
return; return;
const v8::Persistent<v8::Object>& wrapper = visitor_->Trace(
v8::Persistent<v8::Object>::Cast(*value); ToScriptWrappable(v8::Persistent<v8::Object>::Cast(*value)));
}
ScriptWrappable* script_wrappable = ToScriptWrappable(wrapper); private:
visitor_->Trace(script_wrappable); Visitor* const visitor_;
};
// Purges all DOM persistent handles.
class DOMWrapperPurger final : public v8::PersistentHandleVisitor {
public:
explicit DOMWrapperPurger(v8::Isolate* isolate)
: isolate_(isolate), scope_(isolate) {}
void VisitPersistentHandle(v8::Persistent<v8::Value>* value,
uint16_t class_id) final {
if (class_id != WrapperTypeInfo::kNodeClassId &&
class_id != WrapperTypeInfo::kObjectClassId)
return;
// Clear out wrapper type information, essentially disconnecting the Blink
// wrappable from the V8 wrapper. This way, V8 cannot find the C++ object
// anymore.
int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex};
void* values[] = {nullptr, nullptr};
v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(
isolate_, v8::Persistent<v8::Object>::Cast(*value));
wrapper->SetAlignedPointerInInternalFields(arraysize(indices), indices,
values);
value->Reset();
} }
private: private:
Visitor* visitor_; v8::Isolate* isolate_;
v8::HandleScope scope_;
}; };
} // namespace
void V8GCController::TraceDOMWrappers(v8::Isolate* isolate, Visitor* visitor) { void V8GCController::TraceDOMWrappers(v8::Isolate* isolate, Visitor* visitor) {
DOMWrapperTracer tracer(visitor); DOMWrapperTracer tracer(visitor);
isolate->VisitHandlesWithClassIds(&tracer); isolate->VisitHandlesWithClassIds(&tracer);
} }
void V8GCController::ClearDOMWrappers(v8::Isolate* isolate) {
DOMWrapperPurger purger(isolate);
isolate->VisitHandlesWithClassIds(&purger);
}
} // namespace blink } // namespace blink
...@@ -57,7 +57,12 @@ class CORE_EXPORT V8GCController { ...@@ -57,7 +57,12 @@ class CORE_EXPORT V8GCController {
static Node* OpaqueRootForGC(v8::Isolate*, Node*); static Node* OpaqueRootForGC(v8::Isolate*, Node*);
// Called when Oilpan traces references from V8 wrappers to DOM wrappables.
static void TraceDOMWrappers(v8::Isolate*, Visitor*); static void TraceDOMWrappers(v8::Isolate*, Visitor*);
// Called upon terminating a thread when Oilpan clears references from V8
// wrappers to DOM wrappables.
static void ClearDOMWrappers(v8::Isolate*);
}; };
} // namespace blink } // namespace blink
......
...@@ -115,6 +115,7 @@ void WorkerBackingThread::ShutdownOnBackingThread() { ...@@ -115,6 +115,7 @@ void WorkerBackingThread::ShutdownOnBackingThread() {
Platform::Current()->WillStopWorkerThread(); Platform::Current()->WillStopWorkerThread();
V8PerIsolateData::WillBeDestroyed(isolate_); V8PerIsolateData::WillBeDestroyed(isolate_);
V8GCController::ClearDOMWrappers(isolate_);
// TODO(yhirano): Remove this when https://crbug.com/v8/1428 is fixed. // TODO(yhirano): Remove this when https://crbug.com/v8/1428 is fixed.
if (should_call_gc_on_shutdown_) { if (should_call_gc_on_shutdown_) {
// This statement runs only in tests. // This statement runs only in tests.
......
...@@ -142,6 +142,12 @@ void V8PerIsolateData::WillBeDestroyed(v8::Isolate* isolate) { ...@@ -142,6 +142,12 @@ void V8PerIsolateData::WillBeDestroyed(v8::Isolate* isolate) {
data->ClearEndOfScopeTasks(); data->ClearEndOfScopeTasks();
data->active_script_wrappables_.Clear(); data->active_script_wrappables_.Clear();
// Detach V8's garbage collector.
isolate->SetEmbedderHeapTracer(nullptr);
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() // destroy() clear things that should be cleared after ThreadState::detach()
......
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