Commit 8ce74234 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

bindings: Move DOMDataStore on Oilpan's heap

This change moves DOMDataStore on Oilpan's heap and models wrappable->wrapper
connections using an ephemeron hash map for non-main worlds.

Previously, DOMDataStore would be off heap and the that maintains the references
would use Untraced<> as well as custom Trace() methods for non-GCed objects.
That also required callbacks on the references to manually remove the entries to
compact the hash map.

With ephemerons:
- The hashmap is kept compact (unused buckets are deleted) by the GC which
  allows us to avoid callbacks on references.
- There are no more GC plugin exceptions.
- All trace methods will be on garbage collection objects.
- There's no need to trace through all DOM worlds for each ScriptWrappable in
  its trace method.
- References will show up in heap snapshots.

Bug: 1013212
Change-Id: Id3475707d34191f9f3b6b099c2495ee0150d982e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1849677
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#705062}
parent da91f1d8
...@@ -401,6 +401,7 @@ jumbo_component("platform") { ...@@ -401,6 +401,7 @@ jumbo_component("platform") {
"bindings/callback_method_retriever.cc", "bindings/callback_method_retriever.cc",
"bindings/callback_method_retriever.h", "bindings/callback_method_retriever.h",
"bindings/custom_wrappable.h", "bindings/custom_wrappable.h",
"bindings/dom_data_store.cc",
"bindings/dom_data_store.h", "bindings/dom_data_store.h",
"bindings/dom_wrapper_world.cc", "bindings/dom_wrapper_world.cc",
"bindings/dom_wrapper_world.h", "bindings/dom_wrapper_world.h",
......
// Copyright 2019 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.
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
namespace blink {
DOMDataStore::DOMDataStore(v8::Isolate* isolate, bool is_main_world)
: is_main_world_(is_main_world) {}
void DOMDataStore::Dispose() {
for (const auto& it : wrapper_map_) {
// Explicitly reset references so that a following V8 GC will not find them
// and treat them as roots. There's optimizations (see
// EmbedderHeapTracer::IsRootForNonTracingGC) that would not treat them as
// roots and then Blink would not be able to find and remove them from a DOM
// world. Explicitly resetting on disposal avoids that problem
it.value->ref.Clear();
}
}
void DOMDataStore::WrappedReference::Trace(Visitor* visitor) {
visitor->Trace(ref);
}
void DOMDataStore::Trace(Visitor* visitor) {
visitor->Trace(wrapper_map_);
}
} // namespace blink
...@@ -48,9 +48,7 @@ namespace blink { ...@@ -48,9 +48,7 @@ namespace blink {
// wrappers and provides an API to perform common operations with this map and // wrappers and provides an API to perform common operations with this map and
// manage wrappers in a single world. Each world (DOMWrapperWorld) holds a // manage wrappers in a single world. Each world (DOMWrapperWorld) holds a
// single map instance to hold wrappers only for that world. // single map instance to hold wrappers only for that world.
class DOMDataStore { class DOMDataStore final : public GarbageCollected<DOMDataStore> {
USING_FAST_MALLOC(DOMDataStore);
public: public:
static DOMDataStore& Current(v8::Isolate* isolate) { static DOMDataStore& Current(v8::Isolate* isolate) {
return DOMWrapperWorld::Current(isolate).DomDataStore(); return DOMWrapperWorld::Current(isolate).DomDataStore();
...@@ -110,20 +108,17 @@ class DOMDataStore { ...@@ -110,20 +108,17 @@ class DOMDataStore {
return Current(isolate).ContainsWrapper(object); return Current(isolate).ContainsWrapper(object);
} }
DOMDataStore(v8::Isolate* isolate, bool is_main_world) DOMDataStore(v8::Isolate* isolate, bool is_main_world);
: is_main_world_(is_main_world) {
// We never use |wrapper_map_| when it's the main world. // Clears all references.
if (!is_main_world) { void Dispose();
wrapper_map_.emplace();
}
}
v8::Local<v8::Object> Get(ScriptWrappable* object, v8::Isolate* isolate) { v8::Local<v8::Object> Get(ScriptWrappable* object, v8::Isolate* isolate) {
if (is_main_world_) if (is_main_world_)
return object->MainWorldWrapper(isolate); return object->MainWorldWrapper(isolate);
auto it = wrapper_map_->find(object); auto it = wrapper_map_.find(object);
if (it != wrapper_map_->end()) if (it != wrapper_map_.end())
return it->value.NewLocal(isolate); return it->value->ref.NewLocal(isolate);
return v8::Local<v8::Object>(); return v8::Local<v8::Object>();
} }
...@@ -136,41 +131,40 @@ class DOMDataStore { ...@@ -136,41 +131,40 @@ class DOMDataStore {
if (is_main_world_) if (is_main_world_)
return object->SetWrapper(isolate, wrapper_type_info, wrapper); return object->SetWrapper(isolate, wrapper_type_info, wrapper);
auto result = wrapper_map_->insert(object, Value(isolate, wrapper)); auto result = wrapper_map_.insert(
object, MakeGarbageCollected<WrappedReference>(isolate, wrapper));
if (LIKELY(result.is_new_entry)) { if (LIKELY(result.is_new_entry)) {
wrapper_type_info->ConfigureWrapper(&result.stored_value->value.Get()); wrapper_type_info->ConfigureWrapper(
result.stored_value->value.Get().SetFinalizationCallback( &result.stored_value->value->ref.Get());
this, RemoveEntryFromMap);
} else { } else {
DCHECK(!result.stored_value->value.IsEmpty()); DCHECK(!result.stored_value->value->ref.IsEmpty());
wrapper = result.stored_value->value.NewLocal(isolate); wrapper = result.stored_value->value->ref.NewLocal(isolate);
} }
return result.is_new_entry; return result.is_new_entry;
} }
void Trace(const ScriptWrappable* script_wrappable, Visitor* visitor) { bool UnsetSpecificWrapperIfSet(
DCHECK(wrapper_map_); ScriptWrappable* object,
auto it = const v8::TracedReference<v8::Object>& handle) {
wrapper_map_->find(const_cast<ScriptWrappable*>(script_wrappable)); DCHECK(!is_main_world_);
if (it != wrapper_map_->end()) { const auto& it = wrapper_map_.find(object);
visitor->Trace( if (it != wrapper_map_.end()) {
static_cast<TraceWrapperV8Reference<v8::Object>&>(it->value)); if (it->value->ref.Get() == handle) {
it->value->ref.Clear();
wrapper_map_.erase(it);
return true;
} }
} }
return false;
// Dissociates a wrapper, if any, from |script_wrappable|.
void UnsetWrapperIfAny(ScriptWrappable* script_wrappable) {
DCHECK(!is_main_world_);
wrapper_map_->erase(script_wrappable);
} }
bool SetReturnValueFrom(v8::ReturnValue<v8::Value> return_value, bool SetReturnValueFrom(v8::ReturnValue<v8::Value> return_value,
ScriptWrappable* object) { ScriptWrappable* object) {
if (is_main_world_) if (is_main_world_)
return object->SetReturnValue(return_value); return object->SetReturnValue(return_value);
auto it = wrapper_map_->find(object); auto it = wrapper_map_.find(object);
if (it != wrapper_map_->end()) { if (it != wrapper_map_.end()) {
return_value.Set(it->value.Get()); return_value.Set(it->value->ref.Get());
return true; return true;
} }
return false; return false;
...@@ -179,10 +173,12 @@ class DOMDataStore { ...@@ -179,10 +173,12 @@ class DOMDataStore {
bool ContainsWrapper(const ScriptWrappable* object) { bool ContainsWrapper(const ScriptWrappable* object) {
if (is_main_world_) if (is_main_world_)
return object->ContainsWrapper(); return object->ContainsWrapper();
return wrapper_map_->find(const_cast<ScriptWrappable*>(object)) != return wrapper_map_.find(const_cast<ScriptWrappable*>(object)) !=
wrapper_map_->end(); wrapper_map_.end();
} }
virtual void Trace(Visitor*);
private: private:
// We can use a wrapper stored in a ScriptWrappable when we're in the main // We can use a wrapper stored in a ScriptWrappable when we're in the main
// world. This method does the fast check if we're in the main world. If this // world. This method does the fast check if we're in the main world. If this
...@@ -203,58 +199,25 @@ class DOMDataStore { ...@@ -203,58 +199,25 @@ class DOMDataStore {
return wrappable->IsEqualTo(holder); return wrappable->IsEqualTo(holder);
} }
static void RemoveEntryFromMap(const v8::WeakCallbackInfo<void>& data) { // Wrapper around TraceWrapperV8Reference to allow use in ephemeron hash map
DOMDataStore* store = reinterpret_cast<DOMDataStore*>(data.GetParameter()); // below.
ScriptWrappable* key = reinterpret_cast<ScriptWrappable*>( class PLATFORM_EXPORT WrappedReference final
data.GetInternalField(kV8DOMWrapperObjectIndex)); : public GarbageCollected<WrappedReference> {
const auto& it = store->wrapper_map_->find(key);
DCHECK_NE(store->wrapper_map_->end(), it);
store->wrapper_map_->erase(it);
WrapperTypeInfo::WrapperDestroyed();
}
// Specialization of TraceWrapperV8Reference to avoid write barriers on move
// operations. This is correct as entries are never moved out of the storage
// but only moved for rehashing purposes.
//
// We need to avoid write barriers to allow resizing of the hashmap backing
// during V8 garbage collections. The resize is triggered when entries are
// removed which happens in a phase where V8 prohibits any API calls. To work
// around that we just don't emit write barriers for moving.
class DOMWorldWrapperReference : public TraceWrapperV8Reference<v8::Object> {
public: public:
DOMWorldWrapperReference() = default; WrappedReference() = default;
// Regular write barrier for constructor is emitted by WrappedReference(v8::Isolate* isolate, v8::Local<v8::Object> handle)
// TraceWrapperV8Reference. : ref(isolate, handle) {}
DOMWorldWrapperReference(v8::Isolate* isolate, v8::Local<v8::Object> handle)
: TraceWrapperV8Reference(isolate, handle) {}
~DOMWorldWrapperReference() { virtual void Trace(Visitor*);
// Destruction of a reference should clear it immediately.
Clear();
}
// Move support without write barrier. TraceWrapperV8Reference<v8::Object> ref;
DOMWorldWrapperReference(DOMWorldWrapperReference&& other)
: TraceWrapperV8Reference() {
handle_ = std::move(other.handle_);
}
DOMWorldWrapperReference& operator=(DOMWorldWrapperReference&& rhs) {
handle_ = std::move(rhs.handle_);
return *this;
}
}; };
// UntracedMember is safe here as the map is not keeping ScriptWrappable alive
// but merely adding additional edges from Blink to V8.
using Key = UntracedMember<ScriptWrappable>;
using Value = DOMWorldWrapperReference;
using MapType = WTF::HashMap<Key, Value>;
bool is_main_world_; bool is_main_world_;
GC_PLUGIN_IGNORE( // Ephemeron map: WrappedReference will be kept alive as long as
"Avoid dispatch on Visitor by looking up value in DOMDataStore::Trace.") // ScriptWrappable is alive.
base::Optional<MapType> wrapper_map_; HeapHashMap<WeakMember<ScriptWrappable>, Member<WrappedReference>>
wrapper_map_;
DISALLOW_COPY_AND_ASSIGN(DOMDataStore); DISALLOW_COPY_AND_ASSIGN(DOMDataStore);
}; };
......
...@@ -73,7 +73,8 @@ DOMWrapperWorld::DOMWrapperWorld(v8::Isolate* isolate, ...@@ -73,7 +73,8 @@ DOMWrapperWorld::DOMWrapperWorld(v8::Isolate* isolate,
int32_t world_id) int32_t world_id)
: world_type_(world_type), : world_type_(world_type),
world_id_(world_id), world_id_(world_id),
dom_data_store_(std::make_unique<DOMDataStore>(isolate, IsMainWorld())) { dom_data_store_(
MakeGarbageCollected<DOMDataStore>(isolate, IsMainWorld())) {
switch (world_type_) { switch (world_type_) {
case WorldType::kMain: case WorldType::kMain:
// The main world is managed separately from worldMap(). See worldMap(). // The main world is managed separately from worldMap(). See worldMap().
...@@ -109,16 +110,6 @@ void DOMWrapperWorld::AllWorldsInCurrentThread( ...@@ -109,16 +110,6 @@ void DOMWrapperWorld::AllWorldsInCurrentThread(
worlds.push_back(world); worlds.push_back(world);
} }
void DOMWrapperWorld::Trace(const ScriptWrappable* script_wrappable,
Visitor* visitor) {
// Marking for worlds other than the main world.
for (DOMWrapperWorld* world : GetWorldMap().Values()) {
DOMDataStore& data_store = world->DomDataStore();
if (data_store.ContainsWrapper(script_wrappable))
data_store.Trace(script_wrappable, visitor);
}
}
DOMWrapperWorld::~DOMWrapperWorld() { DOMWrapperWorld::~DOMWrapperWorld() {
DCHECK(!IsMainWorld()); DCHECK(!IsMainWorld());
if (IsMainThread()) if (IsMainThread())
...@@ -131,7 +122,8 @@ DOMWrapperWorld::~DOMWrapperWorld() { ...@@ -131,7 +122,8 @@ DOMWrapperWorld::~DOMWrapperWorld() {
} }
void DOMWrapperWorld::Dispose() { void DOMWrapperWorld::Dispose() {
dom_data_store_.reset(); dom_data_store_->Dispose();
dom_data_store_.Clear();
DCHECK(GetWorldMap().Contains(world_id_)); DCHECK(GetWorldMap().Contains(world_id_));
GetWorldMap().erase(world_id_); GetWorldMap().erase(world_id_);
} }
...@@ -238,17 +230,6 @@ int DOMWrapperWorld::GenerateWorldIdForType(WorldType world_type) { ...@@ -238,17 +230,6 @@ int DOMWrapperWorld::GenerateWorldIdForType(WorldType world_type) {
return kInvalidWorldId; return kInvalidWorldId;
} }
void DOMWrapperWorld::DissociateDOMWindowWrappersInAllWorlds(
ScriptWrappable* script_wrappable) {
DCHECK(script_wrappable);
DCHECK(IsMainThread());
script_wrappable->UnsetWrapperIfAny();
for (auto*& world : GetWorldMap().Values())
world->DomDataStore().UnsetWrapperIfAny(script_wrappable);
}
bool DOMWrapperWorld::HasWrapperInAnyWorldInMainThread( bool DOMWrapperWorld::HasWrapperInAnyWorldInMainThread(
ScriptWrappable* script_wrappable) { ScriptWrappable* script_wrappable) {
DCHECK(IsMainThread()); DCHECK(IsMainThread());
...@@ -263,4 +244,16 @@ bool DOMWrapperWorld::HasWrapperInAnyWorldInMainThread( ...@@ -263,4 +244,16 @@ bool DOMWrapperWorld::HasWrapperInAnyWorldInMainThread(
return false; return false;
} }
// static
bool DOMWrapperWorld::UnsetNonMainWorldWrapperIfSet(
ScriptWrappable* object,
const v8::TracedReference<v8::Object>& handle) {
for (DOMWrapperWorld* world : GetWorldMap().Values()) {
DOMDataStore& data_store = world->DomDataStore();
if (data_store.UnsetSpecificWrapperIfSet(object, handle))
return true;
}
return false;
}
} // namespace blink } // namespace blink
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/web_isolated_world_ids.h" #include "third_party/blink/public/platform/web_isolated_world_ids.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h"
...@@ -104,9 +105,6 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { ...@@ -104,9 +105,6 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
static void AllWorldsInCurrentThread( static void AllWorldsInCurrentThread(
Vector<scoped_refptr<DOMWrapperWorld>>& worlds); Vector<scoped_refptr<DOMWrapperWorld>>& worlds);
// Traces wrappers corresponding to the ScriptWrappable in DOM data stores.
static void Trace(const ScriptWrappable*, Visitor*);
static DOMWrapperWorld& World(v8::Local<v8::Context> context) { static DOMWrapperWorld& World(v8::Local<v8::Context> context) {
return ScriptState::From(context)->World(); return ScriptState::From(context)->World();
} }
...@@ -142,7 +140,16 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { ...@@ -142,7 +140,16 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
int GetWorldId() const { return world_id_; } int GetWorldId() const { return world_id_; }
DOMDataStore& DomDataStore() const { return *dom_data_store_; } DOMDataStore& DomDataStore() const { return *dom_data_store_; }
// Clear the reference pointing from |object| to |handle| in any world.
static bool UnsetSpecificWrapperIfSet(
ScriptWrappable* object,
const v8::TracedReference<v8::Object>& handle);
private: private:
static bool UnsetNonMainWorldWrapperIfSet(
ScriptWrappable* object,
const v8::TracedReference<v8::Object>& handle);
DOMWrapperWorld(v8::Isolate*, WorldType, int32_t world_id); DOMWrapperWorld(v8::Isolate*, WorldType, int32_t world_id);
static unsigned number_of_non_main_worlds_in_main_thread_; static unsigned number_of_non_main_worlds_in_main_thread_;
...@@ -152,35 +159,23 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { ...@@ -152,35 +159,23 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
// out of DOMWrapperWorld. // out of DOMWrapperWorld.
static int GenerateWorldIdForType(WorldType); static int GenerateWorldIdForType(WorldType);
// Dissociates all wrappers in all worlds associated with |script_wrappable|.
//
// Do not use this function except for DOMWindow. Only DOMWindow needs to
// dissociate wrappers from the ScriptWrappable because of the following two
// reasons.
//
// Reason 1) Case of the main world
// A DOMWindow may be collected by Blink GC *before* V8 GC collects the
// wrapper because the wrapper object associated with a DOMWindow is a global
// proxy, which remains after navigations. We don't want V8 GC to reset the
// weak persistent handle to a wrapper within the DOMWindow
// (ScriptWrappable::main_world_wrapper_) *after* Blink GC collects the
// DOMWindow because it's use-after-free. Thus, we need to dissociate the
// wrapper in advance.
//
// Reason 2) Case of isolated worlds
// As same, a DOMWindow may be collected before the wrapper gets collected.
// A DOMWrapperMap supports mapping from ScriptWrappable* to v8::Global<T>,
// and we don't want to leave an entry of an already-dead DOMWindow* to the
// persistent handle for the global proxy object, especially considering that
// the address to the already-dead DOMWindow* may be re-used.
friend class DOMWindow;
static void DissociateDOMWindowWrappersInAllWorlds(ScriptWrappable*);
const WorldType world_type_; const WorldType world_type_;
const int32_t world_id_; const int32_t world_id_;
std::unique_ptr<DOMDataStore> dom_data_store_; Persistent<DOMDataStore> dom_data_store_;
}; };
// static
inline bool DOMWrapperWorld::UnsetSpecificWrapperIfSet(
ScriptWrappable* object,
const v8::TracedReference<v8::Object>& handle) {
// Fast path for main world.
if (object->UnsetMainWorldWrapperIfSet(handle))
return true;
// Slow path: |object| may point to |handle| in any non-main DOM world.
return DOMWrapperWorld::UnsetNonMainWorldWrapperIfSet(object, handle);
}
} // namespace blink } // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_DOM_WRAPPER_WORLD_H_ #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_DOM_WRAPPER_WORLD_H_
...@@ -40,7 +40,6 @@ v8::Local<v8::Object> ScriptWrappable::AssociateWithWrapper( ...@@ -40,7 +40,6 @@ v8::Local<v8::Object> ScriptWrappable::AssociateWithWrapper(
void ScriptWrappable::Trace(Visitor* visitor) { void ScriptWrappable::Trace(Visitor* visitor) {
visitor->Trace(main_world_wrapper_); visitor->Trace(main_world_wrapper_);
DOMWrapperWorld::Trace(this, visitor);
} }
const char* ScriptWrappable::NameInHeapSnapshot() const { const char* ScriptWrappable::NameInHeapSnapshot() const {
......
...@@ -128,14 +128,6 @@ class PLATFORM_EXPORT ScriptWrappable ...@@ -128,14 +128,6 @@ class PLATFORM_EXPORT ScriptWrappable
return true; return true;
} }
// Dissociates the wrapper, if any, from this instance.
void UnsetWrapperIfAny() {
if (ContainsWrapper()) {
main_world_wrapper_.Get().Reset();
WrapperTypeInfo::WrapperDestroyed();
}
}
bool IsEqualTo(const v8::Local<v8::Object>& other) const { bool IsEqualTo(const v8::Local<v8::Object>& other) const {
return main_world_wrapper_.Get() == other; return main_world_wrapper_.Get() == other;
} }
...@@ -151,16 +143,14 @@ class PLATFORM_EXPORT ScriptWrappable ...@@ -151,16 +143,14 @@ class PLATFORM_EXPORT ScriptWrappable
ScriptWrappable() = default; ScriptWrappable() = default;
private: private:
// These classes are exceptionally allowed to use MainWorldWrapper().
friend class DOMDataStore;
friend class HeapSnaphotWrapperVisitor;
friend class V8HiddenValue;
friend class V8PrivateProperty;
v8::Local<v8::Object> MainWorldWrapper(v8::Isolate* isolate) const { v8::Local<v8::Object> MainWorldWrapper(v8::Isolate* isolate) const {
return main_world_wrapper_.NewLocal(isolate); return main_world_wrapper_.NewLocal(isolate);
} }
// Clear the main world wrapper if it is set to |handle|.
bool UnsetMainWorldWrapperIfSet(
const v8::TracedReference<v8::Object>& handle);
static_assert( static_assert(
std::is_trivially_destructible< std::is_trivially_destructible<
TraceWrapperV8Reference<v8::Object>>::value, TraceWrapperV8Reference<v8::Object>>::value,
...@@ -168,9 +158,26 @@ class PLATFORM_EXPORT ScriptWrappable ...@@ -168,9 +158,26 @@ class PLATFORM_EXPORT ScriptWrappable
TraceWrapperV8Reference<v8::Object> main_world_wrapper_; TraceWrapperV8Reference<v8::Object> main_world_wrapper_;
// These classes are exceptionally allowed to directly interact with the main
// world wrapper.
friend class DOMDataStore;
friend class DOMWrapperWorld;
friend class HeapSnaphotWrapperVisitor;
friend class V8HiddenValue;
friend class V8PrivateProperty;
DISALLOW_COPY_AND_ASSIGN(ScriptWrappable); DISALLOW_COPY_AND_ASSIGN(ScriptWrappable);
}; };
inline bool ScriptWrappable::UnsetMainWorldWrapperIfSet(
const v8::TracedReference<v8::Object>& handle) {
if (main_world_wrapper_.Get() == handle) {
main_world_wrapper_.Clear();
return true;
}
return false;
}
// Defines |GetWrapperTypeInfo| virtual method which returns the WrapperTypeInfo // Defines |GetWrapperTypeInfo| virtual method which returns the WrapperTypeInfo
// of the instance. Also declares a static member of type WrapperTypeInfo, of // of the instance. Also declares a static member of type WrapperTypeInfo, of
// which the definition is given by the IDL code generator. // which the definition is given by the IDL code generator.
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/platform/heap/unified_heap_controller.h" #include "third_party/blink/renderer/platform/heap/unified_heap_controller.h"
#include "base/macros.h"
#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h" #include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
...@@ -143,9 +145,7 @@ bool UnifiedHeapController::IsTracingDone() { ...@@ -143,9 +145,7 @@ bool UnifiedHeapController::IsTracingDone() {
return is_tracing_done_; return is_tracing_done_;
} }
namespace { bool UnifiedHeapController::IsRootForNonTracingGC(
bool IsRootForNonTracingGCInternal(
const v8::TracedReference<v8::Value>& handle) { const v8::TracedReference<v8::Value>& handle) {
const uint16_t class_id = handle.WrapperClassId(); const uint16_t class_id = handle.WrapperClassId();
// Stand-alone reference or kCustomWrappableId. Keep as root as // Stand-alone reference or kCustomWrappableId. Keep as root as
...@@ -168,8 +168,6 @@ bool IsRootForNonTracingGCInternal( ...@@ -168,8 +168,6 @@ bool IsRootForNonTracingGCInternal(
return false; return false;
} }
} // namespace
void UnifiedHeapController::ResetHandleInNonTracingGC( void UnifiedHeapController::ResetHandleInNonTracingGC(
const v8::TracedReference<v8::Value>& handle) { const v8::TracedReference<v8::Value>& handle) {
const uint16_t class_id = handle.WrapperClassId(); const uint16_t class_id = handle.WrapperClassId();
...@@ -180,12 +178,11 @@ void UnifiedHeapController::ResetHandleInNonTracingGC( ...@@ -180,12 +178,11 @@ void UnifiedHeapController::ResetHandleInNonTracingGC(
return; return;
const v8::TracedReference<v8::Object>& traced = handle.As<v8::Object>(); const v8::TracedReference<v8::Object>& traced = handle.As<v8::Object>();
ToScriptWrappable(traced)->UnsetWrapperIfAny(); bool success = DOMWrapperWorld::UnsetSpecificWrapperIfSet(
} ToScriptWrappable(traced), traced);
// Since V8 found a handle, Blink needs to find it as well when trying to
bool UnifiedHeapController::IsRootForNonTracingGC( // remove it.
const v8::TracedReference<v8::Value>& handle) { CHECK(success);
return IsRootForNonTracingGCInternal(handle);
} }
bool UnifiedHeapController::IsRootForNonTracingGC( bool UnifiedHeapController::IsRootForNonTracingGC(
......
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