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,
// renderer process, and a content::Portal in the browser process.
using PortalToken = util::TokenType<class PortalTokenTypeMarker>;
// Identifies a v8::Context / blink::ScriptState.
using V8ContextToken = util::TokenType<class V8ContextTokenTypeMarker>;
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_H_
......@@ -116,6 +116,11 @@ struct StructTraits<blink::mojom::PortalTokenDataView, blink::PortalToken>
: public blink::TokenMojomTraitsHelper<blink::mojom::PortalTokenDataView,
blink::PortalToken> {};
template <>
struct StructTraits<blink::mojom::V8ContextTokenDataView, blink::V8ContextToken>
: public blink::TokenMojomTraitsHelper<blink::mojom::V8ContextTokenDataView,
blink::V8ContextToken> {};
} // namespace mojo
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_TOKENS_TOKENS_MOJOM_TRAITS_H_
......@@ -61,6 +61,10 @@ mojom_component("tokens") {
mojom = "blink.mojom.PortalToken"
cpp = "::blink::PortalToken"
},
{
mojom = "blink.mojom.V8ContextToken"
cpp = "::blink::V8ContextToken"
},
]
traits_headers =
[ "//third_party/blink/public/common/tokens/tokens_mojom_traits.h" ]
......
......@@ -72,3 +72,7 @@ union ExecutionContextAttributionToken {
struct PortalToken {
mojo_base.mojom.UnguessableToken value;
};
struct V8ContextToken {
mojo_base.mojom.UnguessableToken value;
};
......@@ -248,7 +248,9 @@ void LocalWindowProxy::CreateContext() {
DidAttachGlobalObject();
#endif
script_state_ = MakeGarbageCollected<ScriptState>(context, world_);
DCHECK(GetFrame()->DomWindow());
script_state_ = MakeGarbageCollected<ScriptState>(context, world_,
GetFrame()->DomWindow());
DCHECK(lifecycle_ == Lifecycle::kContextIsUninitialized ||
lifecycle_ == Lifecycle::kGlobalObjectIsDetached);
......
......@@ -132,7 +132,8 @@ class ScriptPromisePropertyTestBase {
v8::HandleScope handle_scope(GetIsolate());
other_script_state_ = MakeGarbageCollected<ScriptState>(
v8::Context::New(GetIsolate()),
DOMWrapperWorld::EnsureIsolatedWorld(GetIsolate(), 1));
DOMWrapperWorld::EnsureIsolatedWorld(GetIsolate(), 1),
/* execution_context = */ nullptr);
}
virtual ~ScriptPromisePropertyTestBase() { DestroyContext(); }
......
......@@ -46,6 +46,8 @@
#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/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_or_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
......@@ -187,7 +189,8 @@ void WorkerOrWorkletScriptController::Initialize(const KURL& url_for_debugger) {
}
DCHECK(!context.IsEmpty());
script_state_ = MakeGarbageCollected<ScriptState>(context, world_);
script_state_ =
MakeGarbageCollected<ScriptState>(context, world_, global_scope_);
ScriptState::Scope scope(script_state_);
......
......@@ -7,19 +7,24 @@
#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/instrumentation/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h"
namespace blink {
ScriptState::ScriptState(v8::Local<v8::Context> context,
scoped_refptr<DOMWrapperWorld> world)
scoped_refptr<DOMWrapperWorld> world,
ExecutionContext* execution_context)
: isolate_(context->GetIsolate()),
context_(isolate_, context),
world_(std::move(world)),
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_);
context_.SetWeak(this, &OnV8ContextCollectedCallback);
context->SetAlignedPointerInEmbedderData(kV8ContextPerContextDataIndex, this);
RendererResourceCoordinator::Get()->OnScriptStateCreated(this,
execution_context);
}
ScriptState::~ScriptState() {
......@@ -27,6 +32,7 @@ ScriptState::~ScriptState() {
DCHECK(context_.IsEmpty());
InstanceCounters::DecrementCounter(
InstanceCounters::kDetachedScriptStateCounter);
RendererResourceCoordinator::Get()->OnScriptStateDestroyed(this);
}
void ScriptState::DetachGlobalObject() {
......@@ -38,6 +44,7 @@ void ScriptState::DisposePerContextData() {
per_context_data_ = nullptr;
InstanceCounters::IncrementCounter(
InstanceCounters::kDetachedScriptStateCounter);
RendererResourceCoordinator::Get()->OnScriptStateDetached(this);
}
void ScriptState::DissociateContext() {
......
......@@ -9,6 +9,7 @@
#include "gin/public/context_holder.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/v8_cross_origin_callback_info.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
......@@ -20,6 +21,7 @@
namespace blink {
class DOMWrapperWorld;
class ExecutionContext;
class ScriptValue;
class V8PerContextData;
......@@ -121,7 +123,11 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
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();
void Trace(Visitor*) const {}
......@@ -173,6 +179,7 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
v8::Isolate* GetIsolate() const { return isolate_; }
DOMWrapperWorld& World() const { return *world_; }
const V8ContextToken& GetToken() const { return token_; }
// This can return an empty handle if the v8::Context is gone.
v8::Local<v8::Context> GetContext() const {
......@@ -219,6 +226,10 @@ class PLATFORM_EXPORT ScriptState final : public GarbageCollected<ScriptState> {
// exactly.
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_cast<int>(gin::kPerContextDataStartIndex) +
static_cast<int>(gin::kEmbedderBlink);
......
......@@ -289,8 +289,10 @@ v8::Local<v8::Context> V8PerIsolateData::EnsureScriptRegexpContext() {
LEAK_SANITIZER_DISABLED_SCOPE;
v8::Local<v8::Context> context(v8::Context::New(GetIsolate()));
script_regexp_script_state_ = MakeGarbageCollected<ScriptState>(
context, DOMWrapperWorld::Create(GetIsolate(),
DOMWrapperWorld::WorldType::kRegExp));
context,
DOMWrapperWorld::Create(GetIsolate(),
DOMWrapperWorld::WorldType::kRegExp),
/* execution_context = */ nullptr);
}
return script_regexp_script_state_->GetContext();
}
......
......@@ -64,4 +64,20 @@ void RendererResourceCoordinator::SetMainThreadTaskLoadIsLow(
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
......@@ -13,6 +13,9 @@
namespace blink {
class ExecutionContext;
class ScriptState;
class PLATFORM_EXPORT RendererResourceCoordinator {
USING_FAST_MALLOC(RendererResourceCoordinator);
......@@ -29,6 +32,22 @@ class PLATFORM_EXPORT RendererResourceCoordinator {
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:
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