summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/bindings
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 16:23:34 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-14 10:37:21 +0000
commit38a9a29f4f9436cace7f0e7abf9c586057df8a4e (patch)
treec4e8c458dc595bc0ddb435708fa2229edfd00bd4 /chromium/third_party/blink/renderer/platform/bindings
parente684a3455bcc29a6e3e66a004e352dea4e1141e7 (diff)
downloadqtwebengine-chromium-38a9a29f4f9436cace7f0e7abf9c586057df8a4e.tar.gz
BASELINE: Update Chromium to 73.0.3683.37
Change-Id: I08c9af2948b645f671e5d933aca1f7a90ea372f2 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/bindings')
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_function_base.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h44
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.cc59
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h41
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h58
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc87
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc104
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc119
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/to_v8.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_binding.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h2
25 files changed, 557 insertions, 201 deletions
diff --git a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc
index 6d2eb3757b3..77350a1f66e 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc
@@ -20,7 +20,7 @@ void ActiveScriptWrappableBase::TraceActiveScriptWrappables(
if (!active_script_wrappables)
return;
- for (auto active_wrappable : *active_script_wrappables) {
+ for (const auto& active_wrappable : *active_script_wrappables) {
if (!active_wrappable->DispatchHasPendingActivity())
continue;
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.cc b/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.cc
index 07c8a4c7e8c..90fb952442e 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.cc
@@ -4,18 +4,30 @@
#include "third_party/blink/renderer/platform/bindings/callback_function_base.h"
+#include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+
namespace blink {
CallbackFunctionBase::CallbackFunctionBase(
v8::Local<v8::Object> callback_function) {
DCHECK(!callback_function.IsEmpty());
- callback_relevant_script_state_ =
- ScriptState::From(callback_function->CreationContext());
- v8::Isolate* isolate = callback_relevant_script_state_->GetIsolate();
-
+ v8::Isolate* isolate = callback_function->GetIsolate();
callback_function_.Set(isolate, callback_function);
+
incumbent_script_state_ = ScriptState::From(isolate->GetIncumbentContext());
+
+ // Set |callback_relevant_script_state_| iff the creation context and the
+ // incumbent context are the same origin-domain. Otherwise, leave it as
+ // nullptr.
+ v8::Local<v8::Context> creation_context =
+ callback_function->CreationContext();
+ if (BindingSecurityForPlatform::ShouldAllowAccessToV8Context(
+ incumbent_script_state_->GetContext(), creation_context,
+ BindingSecurityForPlatform::ErrorReportOption::kDoNotReport)) {
+ callback_relevant_script_state_ = ScriptState::From(creation_context);
+ }
}
void CallbackFunctionBase::Trace(Visitor* visitor) {
@@ -24,9 +36,44 @@ void CallbackFunctionBase::Trace(Visitor* visitor) {
visitor->Trace(incumbent_script_state_);
}
+ScriptState* CallbackFunctionBase::CallbackRelevantScriptStateOrReportError(
+ const char* interface,
+ const char* operation) {
+ if (callback_relevant_script_state_)
+ return callback_relevant_script_state_;
+
+ // Report a SecurityError due to a cross origin callback object.
+ ScriptState::Scope incumbent_scope(incumbent_script_state_);
+ v8::TryCatch try_catch(GetIsolate());
+ try_catch.SetVerbose(true);
+ ExceptionState exception_state(
+ GetIsolate(), ExceptionState::kExecutionContext, interface, operation);
+ exception_state.ThrowSecurityError(
+ "An invocation of the provided callback failed due to cross origin "
+ "access.");
+ return nullptr;
+}
+
+ScriptState* CallbackFunctionBase::CallbackRelevantScriptStateOrThrowException(
+ const char* interface,
+ const char* operation) {
+ if (callback_relevant_script_state_)
+ return callback_relevant_script_state_;
+
+ // Throw a SecurityError due to a cross origin callback object.
+ ScriptState::Scope incumbent_scope(incumbent_script_state_);
+ ExceptionState exception_state(
+ GetIsolate(), ExceptionState::kExecutionContext, interface, operation);
+ exception_state.ThrowSecurityError(
+ "An invocation of the provided callback failed due to cross origin "
+ "access.");
+ return nullptr;
+}
+
V8PersistentCallbackFunctionBase::V8PersistentCallbackFunctionBase(
CallbackFunctionBase* callback_function)
: callback_function_(callback_function) {
+ v8::HandleScope scope(callback_function_->GetIsolate());
v8_function_.Reset(callback_function_->GetIsolate(),
callback_function_->callback_function_.Get());
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h b/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h
index cc38447a2ad..e13ff148990 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h
@@ -36,22 +36,55 @@ class PLATFORM_EXPORT CallbackFunctionBase
}
v8::Isolate* GetIsolate() const {
- return callback_relevant_script_state_->GetIsolate();
+ return incumbent_script_state_->GetIsolate();
}
+ // Returns the ScriptState of the relevant realm of the callback object.
+ //
+ // NOTE: This function must be used only when it's pretty sure that the
+ // callcack object is the same origin-domain. Otherwise,
+ // |CallbackRelevantScriptStateOrReportError| or
+ // |CallbackRelevantScriptStateOrThrowException| must be used instead.
ScriptState* CallbackRelevantScriptState() {
+ DCHECK(callback_relevant_script_state_);
return callback_relevant_script_state_;
}
+ // Returns the ScriptState of the relevant realm of the callback object iff
+ // the callback is the same origin-domain. Otherwise, reports an error and
+ // returns nullptr.
+ ScriptState* CallbackRelevantScriptStateOrReportError(const char* interface,
+ const char* operation);
+
+ // Returns the ScriptState of the relevant realm of the callback object iff
+ // the callback is the same origin-domain. Otherwise, throws an exception and
+ // returns nullptr.
+ ScriptState* CallbackRelevantScriptStateOrThrowException(
+ const char* interface,
+ const char* operation);
+
+ DOMWrapperWorld& GetWorld() const { return incumbent_script_state_->World(); }
+
// Returns true if the ES function has a [[Construct]] internal method.
bool IsConstructor() const { return CallbackFunction()->IsConstructor(); }
+ // Makes the underlying V8 function collectable by V8 Scavenger GC. Do not
+ // use this function unless you really need a hacky performance optimization.
+ // The V8 function is collectable by V8 Full GC whenever this instance is no
+ // longer referenced, so there is no need to call this function unless you
+ // really need V8 *Scavenger* GC to collect the V8 function before V8 Full GC
+ // runs.
+ void DisposeV8FunctionImmediatelyToReduceMemoryFootprint() {
+ callback_function_.Clear();
+ }
+
protected:
explicit CallbackFunctionBase(v8::Local<v8::Object>);
v8::Local<v8::Function> CallbackFunction() const {
return callback_function_.NewLocal(GetIsolate()).As<v8::Function>();
}
+
ScriptState* IncumbentScriptState() { return incumbent_script_state_; }
private:
@@ -59,7 +92,8 @@ class PLATFORM_EXPORT CallbackFunctionBase
// Use v8::Object instead of v8::Function in order to handle
// [TreatNonObjectAsNull].
TraceWrapperV8Reference<v8::Object> callback_function_;
- // The associated Realm of the callback function type value.
+ // The associated Realm of the callback function type value iff it's the same
+ // origin-domain. Otherwise, nullptr.
Member<ScriptState> callback_relevant_script_state_;
// The callback context, i.e. the incumbent Realm when an ECMAScript value is
// converted to an IDL value.
@@ -67,9 +101,6 @@ class PLATFORM_EXPORT CallbackFunctionBase
Member<ScriptState> incumbent_script_state_;
friend class V8PersistentCallbackFunctionBase;
- friend v8::Local<v8::Value> ToV8(CallbackFunctionBase* callback,
- v8::Local<v8::Object> creation_context,
- v8::Isolate*);
};
// V8PersistentCallbackFunctionBase retains the underlying v8::Function of a
@@ -124,7 +155,8 @@ ToV8PersistentCallbackFunction(V8CallbackFunction* callback_function) {
std::is_base_of<CallbackFunctionBase, V8CallbackFunction>::value,
"V8CallbackFunction must be a subclass of CallbackFunctionBase.");
return callback_function
- ? new V8PersistentCallbackFunction<V8CallbackFunction>(
+ ? MakeGarbageCollected<
+ V8PersistentCallbackFunction<V8CallbackFunction>>(
callback_function)
: nullptr;
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.cc b/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.cc
index 6523b794190..f5d336ffc0a 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.cc
@@ -4,25 +4,32 @@
#include "third_party/blink/renderer/platform/bindings/callback_interface_base.h"
+#include "third_party/blink/renderer/platform/bindings/binding_security_for_platform.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+
namespace blink {
CallbackInterfaceBase::CallbackInterfaceBase(
v8::Local<v8::Object> callback_object,
- v8::Local<v8::Context> callback_object_creation_context,
SingleOperationOrNot single_op_or_not) {
DCHECK(!callback_object.IsEmpty());
- DCHECK(!callback_object_creation_context.IsEmpty());
- DCHECK(callback_object->CreationContext() ==
- callback_object_creation_context);
-
- callback_relevant_script_state_ =
- ScriptState::From(callback_object_creation_context);
- v8::Isolate* isolate = callback_relevant_script_state_->GetIsolate();
+ v8::Isolate* isolate = callback_object->GetIsolate();
callback_object_.Set(isolate, callback_object);
+
+ incumbent_script_state_ = ScriptState::From(isolate->GetIncumbentContext());
is_callback_object_callable_ =
(single_op_or_not == kSingleOperation) && callback_object->IsCallable();
- incumbent_script_state_ = ScriptState::From(isolate->GetIncumbentContext());
+
+ // Set |callback_relevant_script_state_| iff the creation context and the
+ // incumbent context are the same origin-domain. Otherwise, leave it as
+ // nullptr.
+ v8::Local<v8::Context> creation_context = callback_object->CreationContext();
+ if (BindingSecurityForPlatform::ShouldAllowAccessToV8Context(
+ incumbent_script_state_->GetContext(), creation_context,
+ BindingSecurityForPlatform::ErrorReportOption::kDoNotReport)) {
+ callback_relevant_script_state_ = ScriptState::From(creation_context);
+ }
}
void CallbackInterfaceBase::Trace(Visitor* visitor) {
@@ -31,6 +38,40 @@ void CallbackInterfaceBase::Trace(Visitor* visitor) {
visitor->Trace(incumbent_script_state_);
}
+ScriptState* CallbackInterfaceBase::CallbackRelevantScriptStateOrReportError(
+ const char* interface,
+ const char* operation) {
+ if (callback_relevant_script_state_)
+ return callback_relevant_script_state_;
+
+ // Report a SecurityError due to a cross origin callback object.
+ ScriptState::Scope incumbent_scope(incumbent_script_state_);
+ v8::TryCatch try_catch(GetIsolate());
+ try_catch.SetVerbose(true);
+ ExceptionState exception_state(
+ GetIsolate(), ExceptionState::kExecutionContext, interface, operation);
+ exception_state.ThrowSecurityError(
+ "An invocation of the provided callback failed due to cross origin "
+ "access.");
+ return nullptr;
+}
+
+ScriptState* CallbackInterfaceBase::CallbackRelevantScriptStateOrThrowException(
+ const char* interface,
+ const char* operation) {
+ if (callback_relevant_script_state_)
+ return callback_relevant_script_state_;
+
+ // Throw a SecurityError due to a cross origin callback object.
+ ScriptState::Scope incumbent_scope(incumbent_script_state_);
+ ExceptionState exception_state(
+ GetIsolate(), ExceptionState::kExecutionContext, interface, operation);
+ exception_state.ThrowSecurityError(
+ "An invocation of the provided callback failed due to cross origin "
+ "access.");
+ return nullptr;
+}
+
V8PersistentCallbackInterfaceBase::V8PersistentCallbackInterfaceBase(
CallbackInterfaceBase* callback_interface)
: callback_interface_(callback_interface) {
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h b/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h
index cdd141a3f2b..902d3badf87 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h
@@ -49,14 +49,34 @@ class PLATFORM_EXPORT CallbackInterfaceBase
return callback_object_.NewLocal(GetIsolate());
}
- v8::Isolate* GetIsolate() {
- return callback_relevant_script_state_->GetIsolate();
- }
-
+ v8::Isolate* GetIsolate() { return incumbent_script_state_->GetIsolate(); }
+
+ // Returns the ScriptState of the relevant realm of the callback object.
+ //
+ // NOTE: This function must be used only when it's pretty sure that the
+ // callcack object is the same origin-domain. Otherwise,
+ // |CallbackRelevantScriptStateOrReportError| or
+ // |CallbackRelevantScriptStateOrThrowException| must be used instead.
ScriptState* CallbackRelevantScriptState() {
+ DCHECK(callback_relevant_script_state_);
return callback_relevant_script_state_;
}
+ // Returns the ScriptState of the relevant realm of the callback object iff
+ // the callback is the same origin-domain. Otherwise, reports an error and
+ // returns nullptr.
+ ScriptState* CallbackRelevantScriptStateOrReportError(const char* interface,
+ const char* operation);
+
+ // Returns the ScriptState of the relevant realm of the callback object iff
+ // the callback is the same origin-domain. Otherwise, throws an exception and
+ // returns nullptr.
+ ScriptState* CallbackRelevantScriptStateOrThrowException(
+ const char* interface,
+ const char* operation);
+
+ DOMWrapperWorld& GetWorld() const { return incumbent_script_state_->World(); }
+
// NodeIteratorBase counts the invocation of those which are callable and
// those which are not.
bool IsCallbackObjectCallableForNodeIteratorBase() const {
@@ -64,13 +84,13 @@ class PLATFORM_EXPORT CallbackInterfaceBase
}
protected:
- CallbackInterfaceBase(v8::Local<v8::Object> callback_object,
- v8::Local<v8::Context> callback_object_creation_context,
- SingleOperationOrNot);
+ explicit CallbackInterfaceBase(v8::Local<v8::Object> callback_object,
+ SingleOperationOrNot);
// Returns true iff the callback interface is a single operation callback
// interface and the callback interface type value is callable.
bool IsCallbackObjectCallable() const { return is_callback_object_callable_; }
+
ScriptState* IncumbentScriptState() { return incumbent_script_state_; }
private:
@@ -87,10 +107,6 @@ class PLATFORM_EXPORT CallbackInterfaceBase
Member<ScriptState> incumbent_script_state_;
friend class V8PersistentCallbackInterfaceBase;
- // ToV8 needs to call |CallbackObject| member function.
- friend v8::Local<v8::Value> ToV8(CallbackInterfaceBase* callback,
- v8::Local<v8::Object> creation_context,
- v8::Isolate*);
};
// V8PersistentCallbackInterfaceBase retains the underlying v8::Object of a
@@ -145,7 +161,8 @@ ToV8PersistentCallbackInterface(V8CallbackInterface* callback_interface) {
std::is_base_of<CallbackInterfaceBase, V8CallbackInterface>::value,
"V8CallbackInterface must be a subclass of CallbackInterfaceBase.");
return callback_interface
- ? new V8PersistentCallbackInterface<V8CallbackInterface>(
+ ? MakeGarbageCollected<
+ V8PersistentCallbackInterface<V8CallbackInterface>>(
callback_interface)
: nullptr;
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.cc b/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.cc
index 2394eec2ba1..ba8e013d0c7 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.cc
@@ -18,8 +18,9 @@ CallbackMethodRetriever::CallbackMethodRetriever(
DCHECK(constructor_->IsConstructor());
}
-void CallbackMethodRetriever::GetPrototypeObject(
+v8::Local<v8::Object> CallbackMethodRetriever::GetPrototypeObject(
ExceptionState& exception_state) {
+ DCHECK(prototype_object_.IsEmpty()) << "Do not call GetPrototypeObject twice";
// https://html.spec.whatwg.org/C/custom-elements.html#element-definition
// step 10.1. Let prototype be Get(constructor, "prototype"). Rethrow any
// exceptions.
@@ -29,15 +30,16 @@ void CallbackMethodRetriever::GetPrototypeObject(
->Get(current_context_, V8AtomicString(isolate_, "prototype"))
.ToLocal(&prototype)) {
exception_state.RethrowV8Exception(try_catch.Exception());
- return;
+ return v8::Local<v8::Object>();
}
// step 10.2. If Type(prototype) is not Object, then throw a TypeError
// exception.
if (!prototype->IsObject()) {
exception_state.ThrowTypeError("constructor prototype is not an object");
- return;
+ return v8::Local<v8::Object>();
}
prototype_object_ = prototype.As<v8::Object>();
+ return prototype_object_;
}
v8::Local<v8::Value> CallbackMethodRetriever::GetFunctionOrUndefined(
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h b/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h
index 1207dbe811b..ee8f10acb2d 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_method_retriever.h
@@ -28,7 +28,7 @@ class PLATFORM_EXPORT CallbackMethodRetriever {
// Get the prototype object from the callback function. Must be invoked prior
// to GetMethod or GetStaticMethod.
- void GetPrototypeObject(ExceptionState&);
+ v8::Local<v8::Object> GetPrototypeObject(ExceptionState&);
// Returns a function extracted from the prototype chain, or undefined.
// Throws if the property is neither of function nor undefined.
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
index 0777e2cf2b6..7b69bb134e8 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
@@ -133,7 +133,6 @@ DOMWrapperWorld::~DOMWrapperWorld() {
}
void DOMWrapperWorld::Dispose() {
- dom_object_holders_.clear();
dom_data_store_.reset();
DCHECK(GetWorldMap().Contains(world_id_));
GetWorldMap().erase(world_id_);
@@ -207,26 +206,6 @@ void DOMWrapperWorld::SetNonMainWorldHumanReadableName(
IsolatedWorldHumanReadableNames().Set(world_id, human_readable_name);
}
-void DOMWrapperWorld::RegisterDOMObjectHolderInternal(
- std::unique_ptr<DOMObjectHolderBase> holder_base) {
- DCHECK(!dom_object_holders_.Contains(holder_base.get()));
- holder_base->SetWorld(this);
- holder_base->SetWeak(&DOMWrapperWorld::WeakCallbackForDOMObjectHolder);
- dom_object_holders_.insert(std::move(holder_base));
-}
-
-void DOMWrapperWorld::UnregisterDOMObjectHolder(
- DOMObjectHolderBase* holder_base) {
- DCHECK(dom_object_holders_.Contains(holder_base));
- dom_object_holders_.erase(holder_base);
-}
-
-void DOMWrapperWorld::WeakCallbackForDOMObjectHolder(
- const v8::WeakCallbackInfo<DOMObjectHolderBase>& data) {
- DOMObjectHolderBase* holder_base = data.GetParameter();
- holder_base->World()->UnregisterDOMObjectHolder(holder_base);
-}
-
// static
int DOMWrapperWorld::GenerateWorldIdForType(WorldType world_type) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<int>, next_world_id, ());
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
index fca64772026..251116e7bc9 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
@@ -45,7 +45,6 @@
namespace blink {
class DOMDataStore;
-class DOMObjectHolderBase;
class ScriptWrappable;
class SecurityOrigin;
@@ -122,8 +121,11 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
// Associates an isolated world (see above for description) with a security
// origin. XMLHttpRequest instances used in that world will be considered
// to come from that origin, not the frame's.
- static void SetIsolatedWorldSecurityOrigin(int world_id,
- scoped_refptr<SecurityOrigin>);
+ // Note: if |security_origin| is null, the security origin stored for the
+ // isolated world is cleared.
+ static void SetIsolatedWorldSecurityOrigin(
+ int world_id,
+ scoped_refptr<SecurityOrigin> security_origin);
SecurityOrigin* IsolatedWorldSecurityOrigin();
static bool HasWrapperInAnyWorldInMainThread(ScriptWrappable*);
@@ -138,58 +140,9 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
int GetWorldId() const { return world_id_; }
DOMDataStore& DomDataStore() const { return *dom_data_store_; }
- template <typename T>
- void RegisterDOMObjectHolder(v8::Isolate* isolate,
- T* object,
- v8::Local<v8::Value> wrapper) {
- RegisterDOMObjectHolderInternal(
- DOMObjectHolder<T>::Create(isolate, object, wrapper));
- }
-
private:
- class DOMObjectHolderBase {
- USING_FAST_MALLOC(DOMObjectHolderBase);
-
- public:
- DOMObjectHolderBase(v8::Isolate* isolate, v8::Local<v8::Value> wrapper)
- : wrapper_(isolate, wrapper), world_(nullptr) {}
- virtual ~DOMObjectHolderBase() = default;
-
- DOMWrapperWorld* World() const { return world_; }
- void SetWorld(DOMWrapperWorld* world) { world_ = world; }
- void SetWeak(v8::WeakCallbackInfo<DOMObjectHolderBase>::Callback callback) {
- wrapper_.SetWeak(this, callback);
- }
-
- private:
- ScopedPersistent<v8::Value> wrapper_;
- DOMWrapperWorld* world_;
- };
-
- template <typename T>
- class DOMObjectHolder : public DOMObjectHolderBase {
- public:
- static std::unique_ptr<DOMObjectHolder<T>>
- Create(v8::Isolate* isolate, T* object, v8::Local<v8::Value> wrapper) {
- return base::WrapUnique(new DOMObjectHolder(isolate, object, wrapper));
- }
-
- private:
- DOMObjectHolder(v8::Isolate* isolate,
- T* object,
- v8::Local<v8::Value> wrapper)
- : DOMObjectHolderBase(isolate, wrapper), object_(object) {}
-
- Persistent<T> object_;
- };
-
DOMWrapperWorld(v8::Isolate*, WorldType, int world_id);
- static void WeakCallbackForDOMObjectHolder(
- const v8::WeakCallbackInfo<DOMObjectHolderBase>&);
- void RegisterDOMObjectHolderInternal(std::unique_ptr<DOMObjectHolderBase>);
- void UnregisterDOMObjectHolder(DOMObjectHolderBase*);
-
static unsigned number_of_non_main_worlds_in_main_thread_;
// Returns an identifier for a given world type. This must not be called for
@@ -224,7 +177,6 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
const WorldType world_type_;
const int world_id_;
std::unique_ptr<DOMDataStore> dom_data_store_;
- HashSet<std::unique_ptr<DOMObjectHolderBase>> dom_object_holders_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
index f2189c0b52c..df13aa4ab0e 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.cc
@@ -15,10 +15,12 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string_manager.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h"
#include "third_party/blink/renderer/platform/scheduler/public/background_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
#include "third_party/blink/renderer/platform/wtf/address_sanitizer.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/zlib/google/compression_utils.h"
@@ -86,6 +88,32 @@ void AsanUnpoisonString(const String& string) {
#endif // defined(ADDRESS_SANITIZER)
}
+// Char buffer allocated using PartitionAlloc, may be nullptr.
+class NullableCharBuffer final {
+ public:
+ explicit NullableCharBuffer(size_t size) {
+ data_ =
+ reinterpret_cast<char*>(WTF::Partitions::BufferPartition()->AllocFlags(
+ base::PartitionAllocReturnNull, size, "NullableCharBuffer"));
+ size_ = size;
+ }
+
+ ~NullableCharBuffer() {
+ if (data_)
+ WTF::Partitions::BufferPartition()->Free(data_);
+ }
+
+ // May return nullptr.
+ char* data() const { return data_; }
+ size_t size() const { return size_; }
+
+ private:
+ char* data_;
+ size_t size_;
+
+ DISALLOW_COPY_AND_ASSIGN(NullableCharBuffer);
+};
+
} // namespace
// Created and destroyed on the same thread, accessed on a background thread as
@@ -185,6 +213,12 @@ void ParkableStringImpl::Unlock() {
#endif // defined(ADDRESS_SANITIZER) && DCHECK_IS_ON()
}
+void ParkableStringImpl::PurgeMemory() {
+ AssertOnValidThread();
+ if (state_ == State::kUnparked)
+ compressed_ = nullptr;
+}
+
const String& ParkableStringImpl::ToString() {
AssertOnValidThread();
MutexLocker locker(mutex_);
@@ -338,22 +372,43 @@ void ParkableStringImpl::CompressInBackground(
#endif // defined(ADDRESS_SANITIZER)
// Compression touches the string.
AsanUnpoisonString(params->string->string_);
+ bool ok;
base::StringPiece data(reinterpret_cast<const char*>(params->data),
params->size);
- std::string compressed_string;
- bool ok = compression::GzipCompress(data, &compressed_string);
-
std::unique_ptr<Vector<uint8_t>> compressed = nullptr;
- if (ok && compressed_string.size() < params->size) {
- compressed = std::make_unique<Vector<uint8_t>>();
- compressed->Append(
- reinterpret_cast<const uint8_t*>(compressed_string.c_str()),
- compressed_string.size());
- }
+
+ {
+ // Temporary vector. As we don't want to waste memory, the temporary buffer
+ // has the same size as the initial data. Compression will fail if this is
+ // not large enough.
+ //
+ // This is not using:
+ // - malloc() or any STL container: this is discouraged in blink, and there
+ // is a suspected memory regression caused by using it (crbug.com/920194).
+ // - WTF::Vector<> as allocation failures result in an OOM crash, whereas
+ // we can fail gracefully. See crbug.com/905777 for an example of OOM
+ // triggered from there.
+ NullableCharBuffer buffer(params->size);
+ ok = buffer.data();
+ size_t compressed_size;
+ if (ok) {
+ ok = compression::GzipCompress(data, buffer.data(), buffer.size(),
+ &compressed_size);
+ }
+
#if defined(ADDRESS_SANITIZER)
- params->string->Unlock();
+ params->string->Unlock();
#endif // defined(ADDRESS_SANITIZER)
+ if (ok) {
+ compressed = std::make_unique<Vector<uint8_t>>();
+ // Not using realloc() as we want the compressed data to be a regular
+ // WTF::Vector.
+ compressed->Append(reinterpret_cast<const uint8_t*>(buffer.data()),
+ compressed_size);
+ }
+ }
+
auto* task_runner = params->callback_task_runner.get();
size_t size = params->size;
PostCrossThreadTask(
@@ -396,6 +451,18 @@ void ParkableString::Unlock() const {
impl_->Unlock();
}
+void ParkableString::OnMemoryDump(WebProcessMemoryDump* pmd,
+ const String& name) const {
+ // Parkable strings are reported by ParkableStringManager.
+ if (!impl_ || may_be_parked())
+ return;
+
+ auto* dump = pmd->CreateMemoryAllocatorDump(name);
+ dump->AddScalar("size", "bytes", CharactersSizeInBytes());
+ pmd->AddSuballocation(dump->Guid(),
+ String(WTF::Partitions::kAllocatedObjectPoolName));
+}
+
bool ParkableString::Is8Bit() const {
return impl_->is_8bit();
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
index d828bcc9c35..30cdf7bd3fb 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string.h
@@ -30,6 +30,7 @@
namespace blink {
+class WebProcessMemoryDump;
struct CompressionTaskParams;
// A parked string is parked by calling |Park()|, and unparked by calling
@@ -60,6 +61,8 @@ class PLATFORM_EXPORT ParkableStringImpl final
void Lock();
void Unlock();
+ void PurgeMemory();
+
// The returned string may be used as a normal one, as long as the
// returned value (or a copy of it) is alive.
const String& ToString();
@@ -153,6 +156,8 @@ class PLATFORM_EXPORT ParkableString final {
// Can be called from any thread.
void Unlock() const;
+ void OnMemoryDump(WebProcessMemoryDump* pmd, const String& name) const;
+
// See the matching String methods.
bool Is8Bit() const;
bool IsNull() const { return !impl_; }
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
index 11b9aa40e8b..b38c876b53c 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.cc
@@ -10,6 +10,8 @@
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/process_memory_dump.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string.h"
#include "third_party/blink/renderer/platform/memory_coordinator.h"
@@ -21,6 +23,8 @@
namespace blink {
+namespace {
+
class OnPurgeMemoryListener : public GarbageCollected<OnPurgeMemoryListener>,
public MemoryCoordinatorClient {
USING_GARBAGE_COLLECTED_MIXIN(OnPurgeMemoryListener);
@@ -28,12 +32,30 @@ class OnPurgeMemoryListener : public GarbageCollected<OnPurgeMemoryListener>,
void OnPurgeMemory() override {
if (!base::FeatureList::IsEnabled(kCompressParkableStringsInBackground))
return;
-
- ParkableStringManager::Instance().ParkAllIfRendererBackgrounded(
- ParkableStringImpl::ParkingMode::kAlways);
+ ParkableStringManager::Instance().PurgeMemory();
}
};
+} // namespace
+
+// static
+ParkableStringManagerDumpProvider*
+ParkableStringManagerDumpProvider::Instance() {
+ static ParkableStringManagerDumpProvider instance;
+ return &instance;
+}
+
+bool ParkableStringManagerDumpProvider::OnMemoryDump(
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ return ParkableStringManager::Instance().OnMemoryDump(pmd);
+}
+
+ParkableStringManagerDumpProvider::~ParkableStringManagerDumpProvider() =
+ default;
+ParkableStringManagerDumpProvider::ParkableStringManagerDumpProvider() =
+ default;
+
ParkableStringManager& ParkableStringManager::Instance() {
DCHECK(IsMainThread());
DEFINE_STATIC_LOCAL(ParkableStringManager, instance, ());
@@ -94,6 +116,43 @@ bool ParkableStringManager::IsRendererBackgrounded() const {
return backgrounded_;
}
+bool ParkableStringManager::OnMemoryDump(
+ base::trace_event::ProcessMemoryDump* pmd) {
+ DCHECK(IsMainThread());
+ base::trace_event::MemoryAllocatorDump* dump =
+ pmd->CreateAllocatorDump("parkable_strings");
+
+ size_t uncompressed_size = 0;
+ size_t compressed_size = 0;
+ size_t metadata_size = 0;
+ size_t overhead_size = 0;
+
+ for (ParkableStringImpl* str : unparked_strings_.Values()) {
+ uncompressed_size += str->CharactersSizeInBytes();
+ metadata_size += sizeof(ParkableStringImpl);
+
+ if (str->has_compressed_data())
+ overhead_size += str->compressed_size();
+ }
+
+ for (ParkableStringImpl* str : parked_strings_) {
+ compressed_size += str->compressed_size();
+ metadata_size += sizeof(ParkableStringImpl);
+ }
+
+ size_t total_size =
+ uncompressed_size + compressed_size + metadata_size + overhead_size;
+ dump->AddScalar("size", "bytes", total_size);
+ dump->AddScalar("uncompressed_size", "bytes", uncompressed_size);
+ dump->AddScalar("compressed_size", "bytes", compressed_size);
+ dump->AddScalar("metadata_size", "bytes", metadata_size);
+ dump->AddScalar("overhead_size", "bytes", overhead_size);
+
+ pmd->AddSuballocation(dump->guid(),
+ WTF::Partitions::kAllocatedObjectPoolName);
+ return true;
+}
+
// static
bool ParkableStringManager::ShouldPark(const StringImpl& string) {
// Don't attempt to park strings smaller than this size.
@@ -151,14 +210,10 @@ void ParkableStringManager::OnUnparked(ParkableStringImpl* was_parked_string,
unparked_strings_.insert(new_unparked_string, was_parked_string);
}
-void ParkableStringManager::ParkAllIfRendererBackgrounded(
- ParkableStringImpl::ParkingMode mode) {
+void ParkableStringManager::ParkAll(ParkableStringImpl::ParkingMode mode) {
DCHECK(IsMainThread());
DCHECK(base::FeatureList::IsEnabled(kCompressParkableStringsInBackground));
- if (!IsRendererBackgrounded())
- return;
-
size_t total_size = 0;
for (ParkableStringImpl* str : parked_strings_)
total_size += str->CharactersSizeInBytes();
@@ -182,8 +237,9 @@ void ParkableStringManager::ParkAllIfRendererBackgrounded(
total_size += str->CharactersSizeInBytes();
}
- // Only collect stats for "full" parking calls.
- if (mode == ParkableStringImpl::ParkingMode::kAlways) {
+ // Only collect stats for "full" parking calls in background.
+ if (mode == ParkableStringImpl::ParkingMode::kAlways &&
+ IsRendererBackgrounded()) {
size_t total_size_kb = total_size / 1000;
UMA_HISTOGRAM_COUNTS_100000("Memory.MovableStringsTotalSizeKb",
total_size_kb);
@@ -191,6 +247,14 @@ void ParkableStringManager::ParkAllIfRendererBackgrounded(
}
}
+void ParkableStringManager::ParkAllIfRendererBackgrounded(
+ ParkableStringImpl::ParkingMode mode) {
+ DCHECK(IsMainThread());
+
+ if (IsRendererBackgrounded())
+ ParkAll(mode);
+}
+
size_t ParkableStringManager::Size() const {
return parked_strings_.size() + unparked_strings_.size();
}
@@ -238,6 +302,23 @@ void ParkableStringManager::DropStringsWithCompressedDataAndRecordStatistics() {
}
}
+void ParkableStringManager::PurgeMemory() {
+ DCHECK(IsMainThread());
+ DCHECK(base::FeatureList::IsEnabled(kCompressParkableStringsInBackground));
+
+ ParkAll(ParkableStringImpl::ParkingMode::kAlways);
+ // Critical memory pressure: drop compressed data for strings that we cannot
+ // park now.
+ //
+ // After |ParkAll()| has been called, parkable strings have either been parked
+ // synchronously (and no longer in |unparked_strings_|), or being parked and
+ // purging is a no-op.
+ if (!IsRendererBackgrounded()) {
+ for (ParkableStringImpl* str : unparked_strings_.Values())
+ str->PurgeMemory();
+ }
+}
+
void ParkableStringManager::ResetForTesting() {
backgrounded_ = false;
waiting_to_record_stats_ = false;
@@ -254,7 +335,8 @@ ParkableStringManager::ParkableStringManager()
parked_strings_() {
// No need to ever unregister, as the only ParkableStringManager instance
// lives forever.
- MemoryCoordinator::Instance().RegisterClient(new OnPurgeMemoryListener());
+ MemoryCoordinator::Instance().RegisterClient(
+ MakeGarbageCollected<OnPurgeMemoryListener>());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
index 262b9ddea2f..54e763184f3 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_manager.h
@@ -8,6 +8,7 @@
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
+#include "base/trace_event/memory_dump_provider.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -23,6 +24,23 @@ class ParkableString;
const base::Feature kCompressParkableStringsInBackground{
"CompressParkableStringsInBackground", base::FEATURE_DISABLED_BY_DEFAULT};
+class PLATFORM_EXPORT ParkableStringManagerDumpProvider
+ : public base::trace_event::MemoryDumpProvider {
+ USING_FAST_MALLOC(ParkableStringManagerDumpProvider);
+
+ public:
+ static ParkableStringManagerDumpProvider* Instance();
+ ~ParkableStringManagerDumpProvider() override;
+
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs&,
+ base::trace_event::ProcessMemoryDump*) override;
+
+ private:
+ ParkableStringManagerDumpProvider();
+
+ DISALLOW_COPY_AND_ASSIGN(ParkableStringManagerDumpProvider);
+};
+
// Manages all the ParkableStrings, and parks eligible strings after the
// renderer has been backgrounded.
// Main Thread only.
@@ -35,9 +53,12 @@ class PLATFORM_EXPORT ParkableStringManager {
void SetRendererBackgrounded(bool backgrounded);
bool IsRendererBackgrounded() const;
+ void PurgeMemory();
// Number of parked and unparked strings. Public for testing.
size_t Size() const;
+ bool OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd);
+
// Whether a string is parkable or not. Can be called from any thread.
static bool ShouldPark(const StringImpl& string);
@@ -48,7 +69,6 @@ class PLATFORM_EXPORT ParkableStringManager {
private:
friend class ParkableString;
friend class ParkableStringImpl;
- friend class OnPurgeMemoryListener;
scoped_refptr<ParkableStringImpl> Add(scoped_refptr<StringImpl>&&);
void Remove(ParkableStringImpl*, StringImpl*);
@@ -56,6 +76,7 @@ class PLATFORM_EXPORT ParkableStringManager {
void OnParked(ParkableStringImpl*, StringImpl*);
void OnUnparked(ParkableStringImpl*, StringImpl*);
+ void ParkAll(ParkableStringImpl::ParkingMode mode);
void ParkAllIfRendererBackgrounded(ParkableStringImpl::ParkingMode mode);
void DropStringsWithCompressedDataAndRecordStatistics();
void ResetForTesting();
diff --git a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
index b186942e1e8..a42626e9944 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
@@ -2,12 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <limits>
+#include <random>
#include <thread>
#include <vector>
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
+#include "base/trace_event/memory_allocator_dump.h"
+#include "base/trace_event/memory_dump_provider.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/renderer/platform/bindings/parkable_string.h"
@@ -25,7 +31,7 @@ constexpr size_t kCompressedSize = 55;
String MakeLargeString() {
std::vector<char> data(kSizeKb * 1000, 'a');
- return String(String(data.data(), data.size()).ReleaseImpl());
+ return String(data.data(), data.size()).ReleaseImpl();
}
} // namespace
@@ -101,6 +107,37 @@ TEST_F(ParkableStringTest, CheckCompressedSize) {
EXPECT_EQ(kCompressedSize, parkable.Impl()->compressed_size());
}
+TEST_F(ParkableStringTest, DontCompressRandomString) {
+ // Make a large random string. Large to make sure it's parkable, and random to
+ // ensure its compressed size is larger than the initial size (at least from
+ // gzip's header). Mersenne-Twister implementation is specified, making the
+ // test deterministic.
+ std::vector<unsigned char> data(kSizeKb * 1000);
+ std::mt19937 engine(42);
+ // uniform_int_distribution<T> is undefined behavior for T = unsigned char.
+ std::uniform_int_distribution<int> dist(
+ 0, std::numeric_limits<unsigned char>::max());
+
+ for (size_t i = 0; i < data.size(); ++i) {
+ data[i] = static_cast<unsigned char>(dist(engine));
+ }
+ ParkableString parkable(String(data.data(), data.size()).ReleaseImpl());
+
+ EXPECT_TRUE(parkable.Impl()->Park(ParkableStringImpl::ParkingMode::kAlways));
+ RunPostedTasks();
+ // Not parked because the temporary buffer wasn't large enough.
+ EXPECT_FALSE(parkable.Impl()->is_parked());
+}
+
+TEST_F(ParkableStringTest, ParkUnparkIdenticalContent) {
+ ParkableString parkable(MakeLargeString().ReleaseImpl());
+ EXPECT_TRUE(parkable.Impl()->Park(ParkableStringImpl::ParkingMode::kAlways));
+ RunPostedTasks();
+ EXPECT_TRUE(parkable.Impl()->is_parked());
+
+ EXPECT_EQ(MakeLargeString(), parkable.ToString());
+}
+
TEST_F(ParkableStringTest, Simple) {
ParkableString parkable_abc(String("abc").ReleaseImpl());
@@ -543,14 +580,14 @@ TEST_F(ParkableStringTest, SynchronousCompression) {
parkable.ToString();
EXPECT_TRUE(parkable.Impl()->has_compressed_data());
// No waiting, synchronous compression.
- manager.ParkAllIfRendererBackgrounded(
- ParkableStringImpl::ParkingMode::kIfCompressedDataExists);
+ manager.ParkAll(ParkableStringImpl::ParkingMode::kIfCompressedDataExists);
EXPECT_TRUE(parkable.Impl()->is_parked());
scoped_task_environment_.FastForwardUntilNoTasksRemain();
}
-TEST_F(ParkableStringTest, OnPurgeMemory) {
+TEST_F(ParkableStringTest, OnPurgeMemoryInBackground) {
ParkableString parkable = CreateAndParkAll();
+ EXPECT_TRUE(ParkableStringManager::Instance().IsRendererBackgrounded());
parkable.ToString();
EXPECT_FALSE(parkable.Impl()->is_parked());
@@ -558,6 +595,80 @@ TEST_F(ParkableStringTest, OnPurgeMemory) {
MemoryCoordinator::Instance().OnPurgeMemory();
EXPECT_TRUE(parkable.Impl()->is_parked());
+
+ parkable.ToString();
+ EXPECT_TRUE(parkable.Impl()->has_compressed_data());
+}
+
+TEST_F(ParkableStringTest, OnPurgeMemoryInForeground) {
+ ParkableString parkable1 = CreateAndParkAll();
+ ParkableString parkable2(MakeLargeString().ReleaseImpl());
+
+ // Park everything.
+ ParkableStringManager::Instance().SetRendererBackgrounded(true);
+ WaitForDelayedParking();
+ EXPECT_TRUE(parkable1.Impl()->is_parked());
+ EXPECT_TRUE(parkable2.Impl()->is_parked());
+
+ ParkableStringManager::Instance().SetRendererBackgrounded(false);
+
+ // Different usage patterns:
+ // 1. Parkable, will be parked synchronouly.
+ // 2. Cannot be parked, compressed representation is purged.
+ parkable1.ToString();
+ String retained = parkable2.ToString();
+ EXPECT_TRUE(parkable2.Impl()->has_compressed_data());
+
+ MemoryCoordinator::Instance().OnPurgeMemory();
+ EXPECT_TRUE(parkable1.Impl()->is_parked()); // Parked synchronously.
+ EXPECT_FALSE(parkable2.Impl()->is_parked());
+ EXPECT_FALSE(parkable2.Impl()->has_compressed_data()); // Purged.
+
+ parkable1.ToString();
+ EXPECT_TRUE(parkable1.Impl()->has_compressed_data());
+}
+
+TEST_F(ParkableStringTest, ReportMemoryDump) {
+ using base::trace_event::MemoryAllocatorDump;
+ using testing::ByRef;
+ using testing::Contains;
+ using testing::Eq;
+
+ auto& manager = ParkableStringManager::Instance();
+ ParkableString parkable1(MakeLargeString().ReleaseImpl());
+ ParkableString parkable2(MakeLargeString().ReleaseImpl());
+ // Not reported in stats below.
+ ParkableString parkable3(String("short string, not parkable").ReleaseImpl());
+
+ manager.SetRendererBackgrounded(true);
+ WaitForDelayedParking();
+ parkable1.ToString();
+
+ base::trace_event::MemoryDumpArgs args = {
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
+ base::trace_event::ProcessMemoryDump pmd(args);
+ manager.OnMemoryDump(&pmd);
+ base::trace_event::MemoryAllocatorDump* dump =
+ pmd.GetAllocatorDump("parkable_strings");
+ ASSERT_NE(nullptr, dump);
+
+ // |parkable1| is unparked.
+ MemoryAllocatorDump::Entry uncompressed("uncompressed_size", "bytes",
+ kSizeKb * 1000);
+ EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(uncompressed))));
+
+ MemoryAllocatorDump::Entry compressed("compressed_size", "bytes",
+ kCompressedSize);
+ EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(compressed))));
+
+ // |parkable1| compressed data is overhead.
+ MemoryAllocatorDump::Entry overhead("overhead_size", "bytes",
+ kCompressedSize);
+ EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(overhead))));
+
+ MemoryAllocatorDump::Entry metadata("metadata_size", "bytes",
+ 2 * sizeof(ParkableStringImpl));
+ EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(metadata))));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h b/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
index 24643901979..749837ee49c 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
@@ -199,7 +199,6 @@ class PLATFORM_EXPORT RuntimeCallStats {
#define BINDINGS_COUNTERS(V) \
V(AssociateObjectWithWrapper) \
V(CreateWrapper) \
- V(GetEventListener) \
V(HasInstance) \
V(ToExecutionContext) \
V(ToV8DOMWindow) \
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h
index 20778d6a0de..8433c4b8c5b 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h
@@ -57,6 +57,9 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
template <typename T>
inline static void WriteBarrier(const T* dst_object);
+ template <typename T>
+ static void WriteBarrier(TraceWrapperMember<T>* array, size_t length);
+
static void WriteBarrier(v8::Isolate*, const WrapperTypeInfo*, void*);
static void WriteBarrier(v8::Isolate*,
@@ -229,6 +232,25 @@ inline void ScriptWrappableMarkingVisitor::WriteBarrier(const T* dst_object) {
TraceDescriptorFor(dst_object));
}
+template <typename T>
+inline void ScriptWrappableMarkingVisitor::WriteBarrier(
+ TraceWrapperMember<T>* array,
+ size_t length) {
+ if (!ThreadState::IsAnyWrapperTracing() || !array)
+ return;
+
+ const ThreadState* thread_state =
+ ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
+ DCHECK(thread_state);
+ // Bail out if tracing is not in progress.
+ if (!thread_state->IsWrapperTracing())
+ return;
+
+ for (size_t i = 0; i < length; ++i) {
+ CurrentVisitor(thread_state->GetIsolate())->Trace(array[i]);
+ }
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_MARKING_VISITOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/to_v8.h b/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
index 75478328831..00370018f60 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
@@ -47,10 +47,11 @@ inline v8::Local<v8::Value> ToV8(CallbackFunctionBase* callback,
v8::Isolate* isolate) {
// |creation_context| is intentionally ignored. Callback functions are not
// wrappers nor clonable. ToV8 on a callback function must be used only when
- // it's the same origin-domain in the same world.
- DCHECK(!callback || (callback->CallbackRelevantScriptState()->GetContext() ==
- creation_context->CreationContext()));
- return callback ? callback->CallbackFunction().As<v8::Value>()
+ // it's in the same world.
+ DCHECK(!callback ||
+ (&callback->GetWorld() ==
+ &ScriptState::From(creation_context->CreationContext())->World()));
+ return callback ? callback->CallbackObject().As<v8::Value>()
: v8::Null(isolate).As<v8::Value>();
}
@@ -59,11 +60,12 @@ inline v8::Local<v8::Value> ToV8(CallbackFunctionBase* callback,
inline v8::Local<v8::Value> ToV8(CallbackInterfaceBase* callback,
v8::Local<v8::Object> creation_context,
v8::Isolate* isolate) {
- // |creation_context| is intentionally ignored. Callback interface objects
- // are not wrappers nor clonable. ToV8 on a callback interface object must
- // be used only when it's the same origin-domain in the same world.
- DCHECK(!callback || (callback->CallbackRelevantScriptState()->GetContext() ==
- creation_context->CreationContext()));
+ // |creation_context| is intentionally ignored. Callback interfaces are not
+ // wrappers nor clonable. ToV8 on a callback interface must be used only when
+ // it's in the same world.
+ DCHECK(!callback ||
+ (&callback->GetWorld() ==
+ &ScriptState::From(creation_context->CreationContext())->World()));
return callback ? callback->CallbackObject().As<v8::Value>()
: v8::Null(isolate).As<v8::Value>();
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h
index d021dcc8977..79304ef441e 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h
@@ -61,30 +61,6 @@ class TraceWrapperMember : public Member<T> {
}
};
-// Swaps two HeapVectors specialized for TraceWrapperMember. The custom swap
-// function is required as TraceWrapperMember potentially requires emitting a
-// write barrier.
-template <typename T>
-void swap(HeapVector<TraceWrapperMember<T>>& a,
- HeapVector<TraceWrapperMember<T>>& b) {
- // HeapVector<Member<T>> and HeapVector<TraceWrapperMember<T>> have the
- // same size and semantics.
- HeapVector<Member<T>>& a_ = reinterpret_cast<HeapVector<Member<T>>&>(a);
- HeapVector<Member<T>>& b_ = reinterpret_cast<HeapVector<Member<T>>&>(b);
- a_.swap(b_);
- if (ThreadState::IsAnyWrapperTracing() &&
- ThreadState::Current()->IsWrapperTracing()) {
- // If incremental marking is enabled we need to emit the write barrier since
- // the swap was performed on HeapVector<Member<T>>.
- for (auto item : a) {
- ScriptWrappableMarkingVisitor::WriteBarrier(item.Get());
- }
- for (auto item : b) {
- ScriptWrappableMarkingVisitor::WriteBarrier(item.Get());
- }
- }
-}
-
// HeapVectorBacking<TraceWrapperMember<T>> need to map to
// HeapVectorBacking<Member<T>> for performing the swap method below.
template <typename T, typename Traits>
diff --git a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
index 21bb8db0d92..41c038346a5 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
@@ -11,8 +11,9 @@
namespace blink {
/**
- * TraceWrapperV8Reference is used to trace from Blink to V8. The reference is
- * (strongly) traced by wrapper tracing.
+ * TraceWrapperV8Reference is used to hold references from Blink to V8 that are
+ * known to both garbage collectors. The reference is a regular traced reference
+ * for wrapper tracing as well as unified heap garbage collections.
*
* TODO(mlippautz): Use a better handle type than v8::Persistent.
*/
@@ -37,16 +38,6 @@ class TraceWrapperV8Reference {
handle_.SetWeak();
}
- template <typename P>
- void Set(v8::Isolate* isolate,
- v8::Local<T> handle,
- P* parameters,
- void (*callback)(const v8::WeakCallbackInfo<P>&),
- v8::WeakCallbackType type = v8::WeakCallbackType::kParameter) {
- InternalSet(isolate, handle);
- handle_.SetWeak(parameters, callback, type);
- }
-
ALWAYS_INLINE v8::Local<T> NewLocal(v8::Isolate* isolate) const {
return v8::Local<T>::New(isolate, handle_);
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h b/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h
index 378f5434309..ba7445d3342 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h
@@ -276,9 +276,9 @@ inline v8::Local<v8::String> V8String(v8::Isolate* isolate,
DCHECK(isolate);
if (!string || string[0] == '\0')
return v8::String::Empty(isolate);
- return v8::String::NewFromOneByte(isolate,
- reinterpret_cast<const uint8_t*>(string),
- v8::NewStringType::kNormal, strlen(string))
+ return v8::String::NewFromOneByte(
+ isolate, reinterpret_cast<const uint8_t*>(string),
+ v8::NewStringType::kNormal, static_cast<int>(strlen(string)))
.ToLocalChecked();
}
@@ -324,7 +324,7 @@ inline v8::Local<v8::String> V8AtomicString(v8::Isolate* isolate,
return v8::String::Empty(isolate);
return v8::String::NewFromOneByte(
isolate, reinterpret_cast<const uint8_t*>(string),
- v8::NewStringType::kInternalized, strlen(string))
+ v8::NewStringType::kInternalized, static_cast<int>(strlen(string)))
.ToLocalChecked();
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h b/chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h
index df0f8eb117c..6ca82aea230 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_global_value_map.h
@@ -111,6 +111,8 @@ class V8GlobalValueMap : public v8::GlobalValueMap<
typedef V8GlobalValueMapTraits<KeyType, ValueType, type> Traits;
explicit V8GlobalValueMap(v8::Isolate* isolate)
: v8::GlobalValueMap<KeyType, ValueType, Traits>(isolate) {}
+ V8GlobalValueMap(v8::Isolate* isolate, const char* label)
+ : v8::GlobalValueMap<KeyType, ValueType, Traits>(isolate, label) {}
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc
index 20c5c4df946..ee25586573c 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc
@@ -45,16 +45,25 @@
namespace blink {
+namespace {
+
+constexpr char kWrapperBoilerplatesLabel[] =
+ "V8PerContextData::wrapper_boilerplates_";
+constexpr char kConstructorMapLabel[] = "V8PerContextData::constructor_map_";
+constexpr char kContextLabel[] = "V8PerContextData::context_";
+
+} // namespace
+
V8PerContextData::V8PerContextData(v8::Local<v8::Context> context)
: isolate_(context->GetIsolate()),
- wrapper_boilerplates_(isolate_),
- constructor_map_(isolate_),
+ wrapper_boilerplates_(isolate_, kWrapperBoilerplatesLabel),
+ constructor_map_(isolate_, kConstructorMapLabel),
context_holder_(std::make_unique<gin::ContextHolder>(isolate_)),
context_(isolate_, context),
activity_logger_(nullptr),
data_map_(MakeGarbageCollected<DataMap>()) {
context_holder_->SetContext(context);
- context_.Get().AnnotateStrongRetainer("blink::V8PerContextData::context_");
+ context_.Get().AnnotateStrongRetainer(kContextLabel);
if (IsMainThread()) {
InstanceCounters::IncrementCounter(
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
index eed599acde1..5766cb414fe 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
@@ -49,6 +49,13 @@
namespace blink {
+namespace {
+
+constexpr char kInterfaceMapLabel[] =
+ "V8PerIsolateData::interface_template_map_for_v8_context_snapshot_";
+
+} // namespace
+
// Wrapper function defined in WebKit.h
v8::Isolate* MainThreadIsolate() {
return V8PerIsolateData::MainThreadIsolate();
@@ -75,7 +82,8 @@ V8PerIsolateData::V8PerIsolateData(
: gin::IsolateHolder::kAllowAtomicsWait,
IsMainThread() ? gin::IsolateHolder::IsolateType::kBlinkMainThread
: gin::IsolateHolder::IsolateType::kBlinkWorkerThread),
- interface_template_map_for_v8_context_snapshot_(GetIsolate()),
+ interface_template_map_for_v8_context_snapshot_(GetIsolate(),
+ kInterfaceMapLabel),
string_cache_(std::make_unique<StringCache>(GetIsolate())),
private_property_(V8PrivateProperty::Create()),
constructor_mode_(ConstructorMode::kCreateNewObject),
@@ -86,8 +94,7 @@ V8PerIsolateData::V8PerIsolateData(
new ScriptWrappableMarkingVisitor(ThreadState::Current())),
unified_heap_controller_(
new UnifiedHeapController(ThreadState::Current())),
- runtime_call_stats_(base::DefaultTickClock::GetInstance()),
- handled_near_v8_heap_limit_(false) {
+ runtime_call_stats_(base::DefaultTickClock::GetInstance()) {
// FIXME: Remove once all v8::Isolate::GetCurrent() calls are gone.
GetIsolate()->Enter();
GetIsolate()->AddBeforeCallEnteredCallback(&BeforeCallEnteredCallback);
@@ -112,8 +119,7 @@ V8PerIsolateData::V8PerIsolateData()
use_counter_disabled_(false),
is_handling_recursion_level_error_(false),
is_reporting_exception_(false),
- runtime_call_stats_(base::DefaultTickClock::GetInstance()),
- handled_near_v8_heap_limit_(false) {
+ runtime_call_stats_(base::DefaultTickClock::GetInstance()) {
CHECK(IsMainThread());
// SnapshotCreator enters the isolate, so we don't call Isolate::Enter() here.
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
index d126266a5c4..6599b4fed71 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
@@ -219,10 +219,6 @@ class PLATFORM_EXPORT V8PerIsolateData {
return unified_heap_controller_.get();
}
- int IsNearV8HeapLimitHandled() { return handled_near_v8_heap_limit_; }
-
- void HandledNearV8HeapLimit() { handled_near_v8_heap_limit_ = true; }
-
private:
V8PerIsolateData(scoped_refptr<base::SingleThreadTaskRunner>,
V8ContextSnapshotMode);
@@ -294,7 +290,6 @@ class PLATFORM_EXPORT V8PerIsolateData {
std::unique_ptr<UnifiedHeapController> unified_heap_controller_;
RuntimeCallStats runtime_call_stats_;
- bool handled_near_v8_heap_limit_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h b/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h
index 6eff732d5b3..8dfd6ec588c 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h
@@ -49,8 +49,6 @@ class ScriptWrappable;
X(SameObject, NotificationVibrate) \
X(SameObject, PerformanceLongTaskTimingAttribution) \
X(SameObject, PushManagerSupportedContentEncodings) \
- X(CustomWrappable, EventHandler) \
- X(CustomWrappable, EventListener) \
SCRIPT_PROMISE_PROPERTIES(X, Promise) \
SCRIPT_PROMISE_PROPERTIES(X, Resolver)