Commit 9a62ac5d authored by Chris Hamilton's avatar Chris Hamilton Committed by Commit Bot

Create V8ContextToken and v8::Context lifecycle tracking.

This adorns ScriptStates with a unique identifier, and adds
lifecycle tracking instrumentation hooks. A further CL will
wire this up in order to implement detached context tracking
as part of the performance.measureMemory API.

BUG=1085129

Change-Id: I4ddb84c547430a28615dea57e7fd346c9e27b1f5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2327851
Commit-Queue: Chris Hamilton <chrisha@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: default avatarWill Harris <wfh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795477}
parent 8cccc82a
...@@ -81,6 +81,9 @@ using ExecutionContextAttributionToken = MultiToken<LocalFrameToken, ...@@ -81,6 +81,9 @@ using ExecutionContextAttributionToken = MultiToken<LocalFrameToken,
// renderer process, and a content::Portal in the browser process. // renderer process, and a content::Portal in the browser process.
using PortalToken = util::TokenType<class PortalTokenTypeMarker>; using PortalToken = util::TokenType<class PortalTokenTypeMarker>;
// Identifies a v8::Context / blink::ScriptState.
using V8ContextToken = util::TokenType<class V8ContextTokenTypeMarker>;
} // namespace blink } // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_H_ #endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_H_
...@@ -116,6 +116,11 @@ struct StructTraits<blink::mojom::PortalTokenDataView, blink::PortalToken> ...@@ -116,6 +116,11 @@ struct StructTraits<blink::mojom::PortalTokenDataView, blink::PortalToken>
: public blink::TokenMojomTraitsHelper<blink::mojom::PortalTokenDataView, : public blink::TokenMojomTraitsHelper<blink::mojom::PortalTokenDataView,
blink::PortalToken> {}; blink::PortalToken> {};
template <>
struct StructTraits<blink::mojom::V8ContextTokenDataView, blink::V8ContextToken>
: public blink::TokenMojomTraitsHelper<blink::mojom::V8ContextTokenDataView,
blink::V8ContextToken> {};
} // namespace mojo } // namespace mojo
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_MOJOM_TRAITS_H_ #endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_MOJOM_TRAITS_H_
...@@ -61,6 +61,10 @@ mojom_component("tokens") { ...@@ -61,6 +61,10 @@ mojom_component("tokens") {
mojom = "blink.mojom.PortalToken" mojom = "blink.mojom.PortalToken"
cpp = "::blink::PortalToken" cpp = "::blink::PortalToken"
}, },
{
mojom = "blink.mojom.V8ContextToken"
cpp = "::blink::V8ContextToken"
},
] ]
traits_headers = traits_headers =
[ "//third_party/blink/public/common/tokens/tokens_mojom_traits.h" ] [ "//third_party/blink/public/common/tokens/tokens_mojom_traits.h" ]
......
...@@ -72,3 +72,7 @@ union ExecutionContextAttributionToken { ...@@ -72,3 +72,7 @@ union ExecutionContextAttributionToken {
struct PortalToken { struct PortalToken {
mojo_base.mojom.UnguessableToken value; mojo_base.mojom.UnguessableToken value;
}; };
struct V8ContextToken {
mojo_base.mojom.UnguessableToken value;
};
...@@ -248,7 +248,9 @@ void LocalWindowProxy::CreateContext() { ...@@ -248,7 +248,9 @@ void LocalWindowProxy::CreateContext() {
DidAttachGlobalObject(); DidAttachGlobalObject();
#endif #endif
script_state_ = MakeGarbageCollected<ScriptState>(context, world_); DCHECK(GetFrame()->DomWindow());
script_state_ = MakeGarbageCollected<ScriptState>(context, world_,
GetFrame()->DomWindow());
DCHECK(lifecycle_ == Lifecycle::kContextIsUninitialized || DCHECK(lifecycle_ == Lifecycle::kContextIsUninitialized ||
lifecycle_ == Lifecycle::kGlobalObjectIsDetached); lifecycle_ == Lifecycle::kGlobalObjectIsDetached);
......
...@@ -132,7 +132,8 @@ class ScriptPromisePropertyTestBase { ...@@ -132,7 +132,8 @@ class ScriptPromisePropertyTestBase {
v8::HandleScope handle_scope(GetIsolate()); v8::HandleScope handle_scope(GetIsolate());
other_script_state_ = MakeGarbageCollected<ScriptState>( other_script_state_ = MakeGarbageCollected<ScriptState>(
v8::Context::New(GetIsolate()), v8::Context::New(GetIsolate()),
DOMWrapperWorld::EnsureIsolatedWorld(GetIsolate(), 1)); DOMWrapperWorld::EnsureIsolatedWorld(GetIsolate(), 1),
/* execution_context = */ nullptr);
} }
virtual ~ScriptPromisePropertyTestBase() { DestroyContext(); } virtual ~ScriptPromisePropertyTestBase() { DestroyContext(); }
......
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h" #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h" #include "third_party/blink/renderer/core/inspector/worker_thread_debugger.h"
#include "third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/shared_worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h" #include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h" #include "third_party/blink/renderer/core/workers/worker_thread.h"
...@@ -187,7 +189,8 @@ void WorkerOrWorkletScriptController::Initialize(const KURL& url_for_debugger) { ...@@ -187,7 +189,8 @@ void WorkerOrWorkletScriptController::Initialize(const KURL& url_for_debugger) {
} }
DCHECK(!context.IsEmpty()); DCHECK(!context.IsEmpty());
script_state_ = MakeGarbageCollected<ScriptState>(context, world_); script_state_ =
MakeGarbageCollected<ScriptState>(context, world_, global_scope_);
ScriptState::Scope scope(script_state_); ScriptState::Scope scope(script_state_);
......
...@@ -7,19 +7,24 @@ ...@@ -7,19 +7,24 @@
#include "third_party/blink/renderer/platform/bindings/v8_binding.h" #include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h" #include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
#include "third_party/blink/renderer/platform/instrumentation/instance_counters.h" #include "third_party/blink/renderer/platform/instrumentation/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h"
namespace blink { namespace blink {
ScriptState::ScriptState(v8::Local<v8::Context> context, ScriptState::ScriptState(v8::Local<v8::Context> context,
scoped_refptr<DOMWrapperWorld> world) scoped_refptr<DOMWrapperWorld> world,
ExecutionContext* execution_context)
: isolate_(context->GetIsolate()), : isolate_(context->GetIsolate()),
context_(isolate_, context), context_(isolate_, context),
world_(std::move(world)), world_(std::move(world)),
per_context_data_(std::make_unique<V8PerContextData>(context)), per_context_data_(std::make_unique<V8PerContextData>(context)),
reference_from_v8_context_(PERSISTENT_FROM_HERE, this) { reference_from_v8_context_(PERSISTENT_FROM_HERE, this),
token_(V8ContextToken::Create()) {
DCHECK(world_); DCHECK(world_);
context_.SetWeak(this, &OnV8ContextCollectedCallback); context_.SetWeak(this, &OnV8ContextCollectedCallback);
context->SetAlignedPointerInEmbedderData(kV8ContextPerContextDataIndex, this); context->SetAlignedPointerInEmbedderData(kV8ContextPerContextDataIndex, this);
RendererResourceCoordinator::Get()->OnScriptStateCreated(this,
execution_context);
} }
ScriptState::~ScriptState() { ScriptState::~ScriptState() {
...@@ -27,6 +32,7 @@ ScriptState::~ScriptState() { ...@@ -27,6 +32,7 @@ ScriptState::~ScriptState() {
DCHECK(context_.IsEmpty()); DCHECK(context_.IsEmpty());
InstanceCounters::DecrementCounter( InstanceCounters::DecrementCounter(
InstanceCounters::kDetachedScriptStateCounter); InstanceCounters::kDetachedScriptStateCounter);
RendererResourceCoordinator::Get()->OnScriptStateDestroyed(this);
} }
void ScriptState::DetachGlobalObject() { void ScriptState::DetachGlobalObject() {
...@@ -38,6 +44,7 @@ void ScriptState::DisposePerContextData() { ...@@ -38,6 +44,7 @@ void ScriptState::DisposePerContextData() {
per_context_data_ = nullptr; per_context_data_ = nullptr;
InstanceCounters::IncrementCounter( InstanceCounters::IncrementCounter(
InstanceCounters::kDetachedScriptStateCounter); InstanceCounters::kDetachedScriptStateCounter);
RendererResourceCoordinator::Get()->OnScriptStateDetached(this);
} }
void ScriptState::DissociateContext() { void ScriptState::DissociateContext() {
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "gin/public/context_holder.h" #include "gin/public/context_holder.h"
#include "gin/public/gin_embedders.h" #include "gin/public/gin_embedders.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h" #include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
#include "third_party/blink/renderer/platform/bindings/v8_cross_origin_callback_info.h" #include "third_party/blink/renderer/platform/bindings/v8_cross_origin_callback_info.h"
#include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/handle.h"
...@@ -20,6 +21,7 @@ ...@@ -20,6 +21,7 @@
namespace blink { namespace blink {
class DOMWrapperWorld; class DOMWrapperWorld;
class ExecutionContext;
class ScriptValue; class ScriptValue;
class V8PerContextData; class V8PerContextData;
...@@ -121,7 +123,11 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> { ...@@ -121,7 +123,11 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
v8::Local<v8::Context> context_; v8::Local<v8::Context> context_;
}; };
ScriptState(v8::Local<v8::Context>, scoped_refptr<DOMWrapperWorld>); // If this ScriptState is associated with an ExecutionContext then it must be
// provided here, otherwise providing nullptr is fine.
ScriptState(v8::Local<v8::Context>,
scoped_refptr<DOMWrapperWorld>,
ExecutionContext* execution_context);
~ScriptState(); ~ScriptState();
void Trace(Visitor*) const {} void Trace(Visitor*) const {}
...@@ -173,6 +179,7 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> { ...@@ -173,6 +179,7 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
v8::Isolate* GetIsolate() const { return isolate_; } v8::Isolate* GetIsolate() const { return isolate_; }
DOMWrapperWorld& World() const { return *world_; } DOMWrapperWorld& World() const { return *world_; }
const V8ContextToken& GetToken() const { return token_; }
// This can return an empty handle if the v8::Context is gone. // This can return an empty handle if the v8::Context is gone.
v8::Local<v8::Context> GetContext() const { v8::Local<v8::Context> GetContext() const {
...@@ -219,6 +226,10 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> { ...@@ -219,6 +226,10 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
// exactly. // exactly.
SelfKeepAlive<ScriptState> reference_from_v8_context_; SelfKeepAlive<ScriptState> reference_from_v8_context_;
// Serves as a unique ID for this context, which can be used to name the
// context in browser/renderer communications.
V8ContextToken token_;
static constexpr int kV8ContextPerContextDataIndex = static constexpr int kV8ContextPerContextDataIndex =
static_cast<int>(gin::kPerContextDataStartIndex) + static_cast<int>(gin::kPerContextDataStartIndex) +
static_cast<int>(gin::kEmbedderBlink); static_cast<int>(gin::kEmbedderBlink);
......
...@@ -289,8 +289,10 @@ v8::Local<v8::Context> V8PerIsolateData::EnsureScriptRegexpContext() { ...@@ -289,8 +289,10 @@ v8::Local<v8::Context> V8PerIsolateData::EnsureScriptRegexpContext() {
LEAK_SANITIZER_DISABLED_SCOPE; LEAK_SANITIZER_DISABLED_SCOPE;
v8::Local<v8::Context> context(v8::Context::New(GetIsolate())); v8::Local<v8::Context> context(v8::Context::New(GetIsolate()));
script_regexp_script_state_ = MakeGarbageCollected<ScriptState>( script_regexp_script_state_ = MakeGarbageCollected<ScriptState>(
context, DOMWrapperWorld::Create(GetIsolate(), context,
DOMWrapperWorld::WorldType::kRegExp)); DOMWrapperWorld::Create(GetIsolate(),
DOMWrapperWorld::WorldType::kRegExp),
/* execution_context = */ nullptr);
} }
return script_regexp_script_state_->GetContext(); return script_regexp_script_state_->GetContext();
} }
......
...@@ -64,4 +64,20 @@ void RendererResourceCoordinator::SetMainThreadTaskLoadIsLow( ...@@ -64,4 +64,20 @@ void RendererResourceCoordinator::SetMainThreadTaskLoadIsLow(
service_->SetMainThreadTaskLoadIsLow(main_thread_task_load_is_low); service_->SetMainThreadTaskLoadIsLow(main_thread_task_load_is_low);
} }
void RendererResourceCoordinator::OnScriptStateCreated(
ScriptState* script_state,
ExecutionContext* execution_context) {
// TODO(chrisha): Extract tokens and forward this to the browser!
}
void RendererResourceCoordinator::OnScriptStateDetached(
ScriptState* script_state) {
// TODO(chrisha): Extract tokens and forward this to the browser!
}
void RendererResourceCoordinator::OnScriptStateDestroyed(
ScriptState* script_state) {
// TODO(chrisha): Extract tokens and forward this to the browser!
}
} // namespace blink } // namespace blink
...@@ -13,6 +13,9 @@ ...@@ -13,6 +13,9 @@
namespace blink { namespace blink {
class ExecutionContext;
class ScriptState;
class PLATFORM_EXPORT RendererResourceCoordinator { class PLATFORM_EXPORT RendererResourceCoordinator {
USING_FAST_MALLOC(RendererResourceCoordinator); USING_FAST_MALLOC(RendererResourceCoordinator);
...@@ -29,6 +32,22 @@ class PLATFORM_EXPORT RendererResourceCoordinator { ...@@ -29,6 +32,22 @@ class PLATFORM_EXPORT RendererResourceCoordinator {
void SetMainThreadTaskLoadIsLow(bool); void SetMainThreadTaskLoadIsLow(bool);
// Used for tracking content javascript contexts (frames, workers, worklets,
// etc). These functions are thread-safe.
// Called when a |script_state| is created. Note that |execution_context| may
// be nullptr if the |script_state| is not associated with an
// |execution_context|.
void OnScriptStateCreated(ScriptState* script_state,
ExecutionContext* execution_context);
// Called when the |script_state| has been detached from the v8::Context
// (and ExecutionContext, if applicable) it was associated with at creation.
// At this point the associated v8::Context is considered "detached" until it
// is garbage collected.
void OnScriptStateDetached(ScriptState* script_state);
// Called when the |script_state| itself is garbage collected.
void OnScriptStateDestroyed(ScriptState* script_state);
protected: protected:
RendererResourceCoordinator(); RendererResourceCoordinator();
......
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