Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Unified Diff: third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp

Issue 2841443005: [Bindings] Create and use V8 context snapshots (Closed)
Patch Set: Fix some behaviors Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
diff --git a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
index 930b5bb4ce53414aa4ff352e293632965471173e..c423f15d5d01da2c969a75754baa4f5fbb86cb3e 100644
--- a/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/LocalWindowProxy.cpp
@@ -39,6 +39,7 @@
#include "bindings/core/v8/V8HTMLDocument.h"
#include "bindings/core/v8/V8Initializer.h"
#include "bindings/core/v8/V8PagePopupControllerBinding.h"
+#include "bindings/core/v8/V8SnapshotCreator.h"
#include "bindings/core/v8/V8Window.h"
#include "core/dom/Modulator.h"
#include "core/frame/LocalFrame.h"
@@ -157,26 +158,110 @@ void LocalWindowProxy::Initialize() {
SetSecurityToken(origin);
}
- MainThreadDebugger::Instance()->ContextCreated(script_state_.Get(),
- GetFrame(), origin);
- GetFrame()->Loader().Client()->DidCreateScriptContext(context,
- world_->GetWorldId());
- // If conditional features for window have been queued before the V8 context
- // was ready, then inject them into the context now
- if (world_->IsMainWorld()) {
- InstallConditionalFeaturesOnWindow(script_state_.Get());
+ {
+ TRACE_EVENT1("v8", "notification", "isMainWindow",
Yuki 2017/05/10 08:58:42 nit: I'm not clear about what "main window" is. W
peria 2017/06/01 08:33:31 Done.
+ GetFrame()->IsMainFrame());
+ MainThreadDebugger::Instance()->ContextCreated(script_state_.Get(),
+ GetFrame(), origin);
+ GetFrame()->Loader().Client()->DidCreateScriptContext(context,
+ world_->GetWorldId());
+ // If conditional features for window have been queued before the V8 context
+ // was ready, then inject them into the context now
+ if (world_->IsMainWorld()) {
+ InstallConditionalFeaturesOnWindow(script_state_.Get());
+ GetFrame()->Loader().DispatchDidClearWindowObjectInMainWorld();
+ }
}
+}
- if (world_->IsMainWorld())
- GetFrame()->Loader().DispatchDidClearWindowObjectInMainWorld();
+namespace {
+
+struct DataForDeserializer {
Yuki 2017/05/10 08:58:43 You don't want to expose this kind of hack outside
peria 2017/05/30 08:25:41 Done.
+ STACK_ALLOCATED();
+ Member<Document> document;
+};
+
+const WrapperTypeInfo* FieldTypeToWrapperTypeInfo(
Yuki 2017/05/10 08:58:43 V8SnapshotCreater should be responsible about the
peria 2017/05/30 08:25:41 Done.
+ V8SnapshotCreator::FieldType type) {
+ switch (type) {
+ case V8SnapshotCreator::kNodeType:
+ return &V8Node::wrapperTypeInfo;
+ case V8SnapshotCreator::kDocumentType:
+ return &V8Document::wrapperTypeInfo;
+ case V8SnapshotCreator::kHTMLDocumentType:
+ return &V8HTMLDocument::wrapperTypeInfo;
+ case V8SnapshotCreator::kHTMLDocumentObject:
+ return &V8HTMLDocument::wrapperTypeInfo;
+ case V8SnapshotCreator::kNone:
+ NOTREACHED();
+ break;
+ }
+ NOTREACHED();
+ return nullptr;
}
+void deserialize(v8::Local<v8::Object> wrapper,
+ int index,
+ v8::StartupData payload,
+ void* ptr) {
+ CHECK_EQ(payload.raw_size,
+ static_cast<int>(sizeof(V8SnapshotCreator::FieldType)));
+ V8SnapshotCreator::FieldType type =
+ *reinterpret_cast<const V8SnapshotCreator::FieldType*>(payload.data);
+
+ const WrapperTypeInfo* wrapper_type_info = FieldTypeToWrapperTypeInfo(type);
+ switch (type) {
+ case V8SnapshotCreator::kNodeType:
Yuki 2017/05/10 08:58:42 nit: Probably it's cleaner to use bit flags here.
peria 2017/05/30 08:25:41 Acknowledged.
+ case V8SnapshotCreator::kDocumentType:
+ case V8SnapshotCreator::kHTMLDocumentType: {
+ CHECK_EQ(index, kV8DOMWrapperTypeIndex);
+ wrapper->SetAlignedPointerInInternalField(
+ index, const_cast<WrapperTypeInfo*>(wrapper_type_info));
Yuki 2017/05/10 08:58:43 I'm not confident, but we wouldn't need to set an
peria 2017/05/30 08:25:41 Acknowledged.
+ wrapper_type_info->WrapperCreated();
Yuki 2017/05/10 08:58:43 IIUC, interface objects are not considered as "wra
peria 2017/05/30 08:25:41 Done.
+ break;
+ }
+ case V8SnapshotCreator::kHTMLDocumentObject: {
+ CHECK_EQ(index, kV8DOMWrapperObjectIndex);
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ DataForDeserializer* data = static_cast<DataForDeserializer*>(ptr);
+ ScriptWrappable* document = data->document;
+
+ // Make reference from wrapper to document
+ wrapper->SetAlignedPointerInInternalField(index, document);
+ // Make reference from document to wrapper
+ CHECK(document->SetWrapper(isolate, wrapper_type_info, wrapper));
Yuki 2017/05/10 08:58:42 I think that you should use document->AssociateWit
peria 2017/05/30 08:25:41 This routine is run during creating v8::Context, s
+ break;
+ }
+ case V8SnapshotCreator::kNone:
+ NOTREACHED();
+ break;
+ }
+}
+
+} // namespace
+
void LocalWindowProxy::CreateContext() {
- // Create a new v8::Context with the window object as the global object
- // (aka the inner global). Reuse the outer global proxy if it already exists.
- v8::Local<v8::ObjectTemplate> global_template =
- V8Window::domTemplate(GetIsolate(), *world_)->InstanceTemplate();
- CHECK(!global_template.IsEmpty());
+ TRACE_EVENT1("v8", "LocalWindowProxy::CreateContext", "isMainWindow",
+ GetFrame()->IsMainFrame());
+
+ if (V8PerIsolateData::From(GetIsolate())->UseSnapshot()) {
Yuki 2017/05/10 08:58:43 This kind of code should live hidden in V8Snapshot
peria 2017/05/30 08:25:41 Done. This part should be run once per context. I
+ // To store function templates into V8PerIsolateData.
+ v8::Local<v8::FunctionTemplate> eventTargetFunctionTemplate =
+ V8EventTarget::domTemplate(GetIsolate(), World());
+ CHECK(!eventTargetFunctionTemplate.IsEmpty());
+ v8::Local<v8::FunctionTemplate> windowFunctionTemplate =
+ V8Window::domTemplate(GetIsolate(), World());
+ CHECK(!windowFunctionTemplate.IsEmpty());
+ v8::Local<v8::FunctionTemplate> nodeFunctionTemplate =
+ V8Node::domTemplate(GetIsolate(), World());
+ CHECK(!nodeFunctionTemplate.IsEmpty());
+ v8::Local<v8::FunctionTemplate> documentFunctionTemplate =
+ V8Document::domTemplate(GetIsolate(), World());
+ CHECK(!documentFunctionTemplate.IsEmpty());
+ v8::Local<v8::FunctionTemplate> htmlDocumentFunctionTemplate =
+ V8HTMLDocument::domTemplate(GetIsolate(), World());
+ CHECK(!htmlDocumentFunctionTemplate.IsEmpty());
+ }
Vector<const char*> extension_names;
// Dynamically tell v8 about our extensions now.
@@ -191,11 +276,33 @@ void LocalWindowProxy::CreateContext() {
v8::Local<v8::Context> context;
{
+ V8PerIsolateData* per_isolate_data = V8PerIsolateData::From(GetIsolate());
V8PerIsolateData::UseCounterDisabledScope use_counter_disabled(
V8PerIsolateData::From(GetIsolate()));
- context =
- v8::Context::New(GetIsolate(), &extension_configuration,
- global_template, global_proxy_.NewLocal(GetIsolate()));
+ TRACE_EVENT1("v8", "contextCreation", "isMainWindow",
+ GetFrame()->IsMainFrame());
+
+ v8::Local<v8::Object> global_proxy = global_proxy_.NewLocal(GetIsolate());
+ Document* document = GetFrame()->GetDocument();
+
+ if (per_isolate_data->UseSnapshot() &&
+ (!World().IsMainWorld() || (document && document->IsHTMLDocument()))) {
Yuki 2017/05/10 08:58:42 I don't understand these conditions. I thought th
peria 2017/05/30 08:25:41 First of all, we need at least two types of contex
+ const int index = World().IsMainWorld() ? 0 : 1;
Yuki 2017/05/10 08:58:43 Where these magic numbers 0 and 1 come from? You
peria 2017/05/30 08:25:41 Done.
+ DataForDeserializer data{document};
+ CHECK(v8::Context::FromSnapshot(
+ GetIsolate(), index,
+ v8::DeserializeInternalFieldsCallback(&deserialize, &data),
+ &extension_configuration, global_proxy)
+ .ToLocal(&context));
+ }
+
+ if (context.IsEmpty()) {
Yuki 2017/05/10 08:58:43 Should this simply be } else { ? It seems that
peria 2017/05/30 08:25:41 Done.
+ v8::Local<v8::ObjectTemplate> global_template =
+ V8Window::domTemplate(GetIsolate(), *world_)->InstanceTemplate();
+ CHECK(!global_template.IsEmpty());
+ context = v8::Context::New(GetIsolate(), &extension_configuration,
+ global_template, global_proxy);
+ }
}
CHECK(!context.IsEmpty());
@@ -212,6 +319,9 @@ void LocalWindowProxy::CreateContext() {
}
void LocalWindowProxy::SetupWindowPrototypeChain() {
+ TRACE_EVENT1("v8", "LocalWindowProxy::setupWindowPrototypeChain",
Yuki 2017/05/10 08:58:43 nit: s/setup/Setup/
peria 2017/05/30 08:25:41 Done.
+ "isMainWindow", GetFrame()->IsMainFrame());
+
// Associate the window wrapper object and its prototype chain with the
// corresponding native DOMWindow object.
DOMWindow* window = GetFrame()->DomWindow();
@@ -248,6 +358,14 @@ void LocalWindowProxy::SetupWindowPrototypeChain() {
V8DOMWrapper::SetNativeInfo(GetIsolate(), window_properties,
wrapper_type_info, window);
+ if (V8PerIsolateData::From(GetIsolate())->UseSnapshot()) {
+ v8::Local<v8::Function> window_interface =
+ V8Window::domTemplate(GetIsolate(), World())->GetFunction();
+ V8Window::installV8WindowRuntimeEnabledFunction(
+ GetIsolate(), World(), window_wrapper, window_prototype,
+ window_interface);
+ }
+
// TODO(keishi): Remove installPagePopupController and implement
// PagePopupController in another way.
V8PagePopupControllerBinding::InstallPagePopupController(context,
@@ -256,12 +374,29 @@ void LocalWindowProxy::SetupWindowPrototypeChain() {
void LocalWindowProxy::UpdateDocumentProperty() {
DCHECK(world_->IsMainWorld());
+ TRACE_EVENT1("v8", "LocalWindowProxy::updateDocumentProperty", "isMainWindow",
Yuki 2017/05/10 08:58:43 nit: s/update/Update/
peria 2017/05/30 08:25:41 Done.
+ GetFrame()->IsMainFrame());
ScriptState::Scope scope(script_state_.Get());
v8::Local<v8::Context> context = script_state_->GetContext();
v8::Local<v8::Value> document_wrapper =
ToV8(GetFrame()->GetDocument(), context->Global(), GetIsolate());
DCHECK(document_wrapper->IsObject());
+
+ if (V8PerIsolateData::From(GetIsolate())->UseSnapshot()) {
+ v8::Local<v8::Object> wrapper = document_wrapper.As<v8::Object>();
Yuki 2017/05/10 08:58:42 s/wrapper/htmldocument_wrapper/ and make it clear
peria 2017/05/30 08:25:41 Done.
+ v8::Local<v8::Object> document_prototype = wrapper->GetPrototype()
+ .As<v8::Object>()
+ ->GetPrototype()
+ .As<v8::Object>();
+ V8Document::installRuntimeEnabledFeatures(GetIsolate(), World(), wrapper,
Yuki 2017/05/10 08:58:43 Although it's noop, we do have {V8HTMLDocument,V8N
peria 2017/05/30 08:25:41 Done.
+ document_prototype,
+ v8::Local<v8::Function>());
+ V8Document::preparePrototypeAndInterfaceObject(
+ context, World(), document_prototype, v8::Local<v8::Function>(),
+ v8::Local<v8::FunctionTemplate>());
+ }
+
// Update the cached accessor for window.document.
CHECK(V8PrivateProperty::GetWindowDocumentCachedAccessor(GetIsolate())
.Set(context->Global(), document_wrapper));
@@ -305,8 +440,8 @@ void LocalWindowProxy::SetSecurityToken(SecurityOrigin* origin) {
String frame_security_token = frame_security_origin->ToString();
// We need to check the return value of domainWasSetInDOM() on the
// frame's SecurityOrigin because, if that's the case, only
- // SecurityOrigin::m_domain would have been modified.
- // m_domain is not used by SecurityOrigin::toString(), so we would end
+ // SecurityOrigin::domain_ would have been modified.
+ // domain_ is not used by SecurityOrigin::toString(), so we would end
// up generating the same token that was already set.
if (frame_security_origin->DomainWasSetInDOM() ||
frame_security_token.IsEmpty() || frame_security_token == "null") {

Powered by Google App Engine
This is Rietveld 408576698