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

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

Issue 2989793003: Revert of [Bindings] Create and use V8 context snapshots (Closed)
Patch Set: Created 3 years, 5 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/V8ContextSnapshot.cpp
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.cpp b/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.cpp
deleted file mode 100644
index f6ffec94779bcaad9c4134d692c49856d0b56d9a..0000000000000000000000000000000000000000
--- a/third_party/WebKit/Source/bindings/core/v8/V8ContextSnapshot.cpp
+++ /dev/null
@@ -1,501 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "bindings/core/v8/V8ContextSnapshot.h"
-
-#include <array>
-#include <cstring>
-
-#include "bindings/core/v8/GeneratedCodeHelper.h"
-#include "bindings/core/v8/V8Document.h"
-#include "bindings/core/v8/V8EventTarget.h"
-#include "bindings/core/v8/V8HTMLDocument.h"
-#include "bindings/core/v8/V8Initializer.h"
-#include "bindings/core/v8/V8Node.h"
-#include "bindings/core/v8/V8Window.h"
-#include "platform/bindings/DOMWrapperWorld.h"
-#include "platform/bindings/V8ObjectConstructor.h"
-#include "platform/bindings/V8PerIsolateData.h"
-#include "platform/bindings/V8PrivateProperty.h"
-#include "platform/instrumentation/tracing/TraceEvent.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-namespace {
-
-intptr_t* g_v8_context_snapshot_reference_table = nullptr;
-
-// TODO(peria): This method is almost a copy of
-// V8PerContext::ConstructorForTypeSlowCase(), so merge with it.
-v8::Local<v8::Function> ConstructPlainType(v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Context> context,
- const WrapperTypeInfo* type) {
- v8::Context::Scope scope(context);
- // We shouldn't reach this point for the types that are implemented in v8 such
- // as typed arrays and hence don't have domTemplateFunction.
- DCHECK(type->dom_template_function);
- v8::Local<v8::FunctionTemplate> interface_template =
- type->domTemplate(isolate, world);
- // Getting the function might fail if we're running out of stack or memory.
- v8::Local<v8::Function> interface_object =
- interface_template->GetFunction(context).ToLocalChecked();
-
- if (type->parent_class) {
- v8::Local<v8::Object> prototype_template =
- ConstructPlainType(isolate, world, context, type->parent_class);
- CHECK(interface_object->SetPrototype(context, prototype_template)
- .ToChecked());
- }
-
- v8::Local<v8::Value> prototype_value =
- interface_object->Get(context, V8AtomicString(isolate, "prototype"))
- .ToLocalChecked();
- CHECK(prototype_value->IsObject());
- v8::Local<v8::Object> prototype_object = prototype_value.As<v8::Object>();
- if (prototype_object->InternalFieldCount() ==
- kV8PrototypeInternalFieldcount &&
- type->wrapper_type_prototype ==
- WrapperTypeInfo::kWrapperTypeObjectPrototype) {
- prototype_object->SetAlignedPointerInInternalField(
- kV8PrototypeTypeIndex, const_cast<WrapperTypeInfo*>(type));
- }
- type->PreparePrototypeAndInterfaceObject(
- context, world, prototype_object, interface_object, interface_template);
-
- return interface_object;
-}
-
-// TODO(peria): This method is almost a copy of
-// V8PerContext::CreateWrapperFromCacheSlowCase(), so merge with it.
-v8::Local<v8::Object> CreatePlainWrapper(v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::Local<v8::Context> context,
- const WrapperTypeInfo* type) {
- CHECK(V8HTMLDocument::wrapperTypeInfo.Equals(type));
-
- v8::Context::Scope scope(context);
- v8::Local<v8::Function> interface_object =
- ConstructPlainType(isolate, world, context, type);
- CHECK(!interface_object.IsEmpty());
- v8::Local<v8::Object> instance_template =
- V8ObjectConstructor::NewInstance(isolate, interface_object)
- .ToLocalChecked();
- v8::Local<v8::Object> wrapper = instance_template->Clone();
- wrapper->SetAlignedPointerInInternalField(kV8DOMWrapperTypeIndex,
- const_cast<WrapperTypeInfo*>(type));
- return wrapper;
-}
-
-int GetSnapshotIndexForWorld(const DOMWrapperWorld& world) {
- return world.IsMainWorld() ? 0 : 1;
-}
-
-// Interface templates of those classes are stored in a snapshot without any
-// runtime enabled features, so we have to install runtime enabled features on
-// them after instantiation.
-struct SnapshotInterface {
- const WrapperTypeInfo* wrapper_type_info;
- InstallRuntimeEnabledFeaturesOnTemplateFunction install_function;
-};
-SnapshotInterface g_snapshot_interfaces[] = {
- {&V8Window::wrapperTypeInfo,
- V8Window::InstallRuntimeEnabledFeaturesOnTemplate},
- {&V8HTMLDocument::wrapperTypeInfo,
- V8HTMLDocument::InstallRuntimeEnabledFeaturesOnTemplate},
- {&V8EventTarget::wrapperTypeInfo,
- V8EventTarget::InstallRuntimeEnabledFeaturesOnTemplate},
- {&V8Node::wrapperTypeInfo, V8Node::InstallRuntimeEnabledFeaturesOnTemplate},
- {&V8Document::wrapperTypeInfo,
- V8Document::InstallRuntimeEnabledFeaturesOnTemplate},
-};
-constexpr size_t kSnapshotInterfaceSize =
- WTF_ARRAY_LENGTH(g_snapshot_interfaces);
-
-enum class InternalFieldType : uint8_t {
- kNone,
- kNodeType,
- kDocumentType,
- kHTMLDocumentType,
- kHTMLDocumentObject,
-};
-
-const WrapperTypeInfo* FieldTypeToWrapperTypeInfo(InternalFieldType type) {
- switch (type) {
- case InternalFieldType::kNone:
- NOTREACHED();
- break;
- case InternalFieldType::kNodeType:
- return &V8Node::wrapperTypeInfo;
- case InternalFieldType::kDocumentType:
- return &V8Document::wrapperTypeInfo;
- case InternalFieldType::kHTMLDocumentType:
- return &V8HTMLDocument::wrapperTypeInfo;
- case InternalFieldType::kHTMLDocumentObject:
- return &V8HTMLDocument::wrapperTypeInfo;
- }
- NOTREACHED();
- return nullptr;
-}
-
-struct DataForDeserializer {
- STACK_ALLOCATED();
- Member<Document> document;
-};
-
-int CountExternalReferenceEntries() {
- if (!g_v8_context_snapshot_reference_table)
- return 0;
-
- int count = 0;
- for (intptr_t* p = g_v8_context_snapshot_reference_table; *p; ++p)
- ++count;
- return count;
-}
-
-} // namespace
-
-v8::Local<v8::Context> V8ContextSnapshot::CreateContextFromSnapshot(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- v8::ExtensionConfiguration* extension_configuration,
- v8::Local<v8::Object> global_proxy,
- Document* document) {
- if (!CanCreateContextFromSnapshot(isolate, world, document)) {
- return v8::Local<v8::Context>();
- }
-
- const int index = GetSnapshotIndexForWorld(world);
- DataForDeserializer data{document};
- v8::DeserializeInternalFieldsCallback callback =
- v8::DeserializeInternalFieldsCallback(&DeserializeInternalField, &data);
- v8::Local<v8::Context> context =
- v8::Context::FromSnapshot(isolate, index, callback,
- extension_configuration, global_proxy)
- .ToLocalChecked();
- VLOG(1) << "A context is created from snapshot for "
- << (world.IsMainWorld() ? "" : "non-") << "main world";
-
- return context;
-}
-
-void V8ContextSnapshot::InstallRuntimeEnabledFeatures(
- v8::Local<v8::Context> context,
- Document* document) {
- ScriptState* script_state = ScriptState::From(context);
- v8::Isolate* isolate = script_state->GetIsolate();
- const DOMWrapperWorld& world = script_state->World();
- if (!CanCreateContextFromSnapshot(isolate, world, document)) {
- return;
- }
-
- TRACE_EVENT1("v8", "V8ContextSnapshot::InstallRuntimeEnabled", "IsMainFrame",
- world.IsMainWorld());
-
- v8::Local<v8::String> prototype_str = V8AtomicString(isolate, "prototype");
- V8PerContextData* data = script_state->PerContextData();
-
- v8::Local<v8::Object> global_proxy = context->Global();
- {
- v8::Local<v8::Object> window_wrapper =
- global_proxy->GetPrototype().As<v8::Object>();
- const WrapperTypeInfo* type = &V8Window::wrapperTypeInfo;
- v8::Local<v8::Function> interface = data->ConstructorForType(type);
- v8::Local<v8::Object> prototype = interface->Get(context, prototype_str)
- .ToLocalChecked()
- .As<v8::Object>();
- V8Window::install_runtime_enabled_features_function_(
- isolate, world, window_wrapper, prototype, interface);
- }
- {
- const WrapperTypeInfo* type = &V8EventTarget::wrapperTypeInfo;
- v8::Local<v8::Function> interface = data->ConstructorForType(type);
- v8::Local<v8::Object> prototype = interface->Get(context, prototype_str)
- .ToLocalChecked()
- .As<v8::Object>();
- V8EventTarget::InstallRuntimeEnabledFeatures(
- isolate, world, v8::Local<v8::Object>(), prototype, interface);
- }
-
- if (!world.IsMainWorld()) {
- return;
- }
-
- // The below code handles window.document on the main world.
- {
- CHECK(document);
- DCHECK(document->IsHTMLDocument());
- CHECK(document->ContainsWrapper());
- v8::Local<v8::Object> document_wrapper =
- ToV8(document, global_proxy, isolate).As<v8::Object>();
- const WrapperTypeInfo* type = &V8HTMLDocument::wrapperTypeInfo;
- v8::Local<v8::Function> interface = data->ConstructorForType(type);
- v8::Local<v8::Object> prototype = interface->Get(context, prototype_str)
- .ToLocalChecked()
- .As<v8::Object>();
- V8HTMLDocument::InstallRuntimeEnabledFeatures(
- isolate, world, document_wrapper, prototype, interface);
- }
- {
- const WrapperTypeInfo* type = &V8Document::wrapperTypeInfo;
- v8::Local<v8::Function> interface = data->ConstructorForType(type);
- v8::Local<v8::Object> prototype = interface->Get(context, prototype_str)
- .ToLocalChecked()
- .As<v8::Object>();
- V8Document::InstallRuntimeEnabledFeatures(
- isolate, world, v8::Local<v8::Object>(), prototype, interface);
- }
- {
- const WrapperTypeInfo* type = &V8Node::wrapperTypeInfo;
- v8::Local<v8::Function> interface = data->ConstructorForType(type);
- v8::Local<v8::Object> prototype = interface->Get(context, prototype_str)
- .ToLocalChecked()
- .As<v8::Object>();
- V8Node::InstallRuntimeEnabledFeatures(
- isolate, world, v8::Local<v8::Object>(), prototype, interface);
- }
-}
-
-void V8ContextSnapshot::EnsureInterfaceTemplates(v8::Isolate* isolate) {
- if (V8PerIsolateData::From(isolate)->GetV8ContextSnapshotMode() !=
- V8PerIsolateData::V8ContextSnapshotMode::kUseSnapshot) {
- return;
- }
-
- v8::HandleScope handle_scope(isolate);
- SnapshotInterface& snapshot_window = g_snapshot_interfaces[0];
- DCHECK(V8Window::wrapperTypeInfo.Equals(snapshot_window.wrapper_type_info));
- // Update the install function for V8Window to work for partial interfaces.
- snapshot_window.install_function =
- V8Window::install_runtime_enabled_features_on_template_function_;
-
- EnsureInterfaceTemplatesForWorld(isolate, DOMWrapperWorld::MainWorld());
- // Any world types other than |kMain| are acceptable for this.
- RefPtr<DOMWrapperWorld> isolated_world = DOMWrapperWorld::Create(
- isolate, DOMWrapperWorld::WorldType::kForV8ContextSnapshotNonMain);
- EnsureInterfaceTemplatesForWorld(isolate, *isolated_world);
-}
-
-void V8ContextSnapshot::SetReferenceTable(intptr_t* table) {
- DCHECK(!g_v8_context_snapshot_reference_table);
- g_v8_context_snapshot_reference_table = table;
-}
-
-intptr_t* V8ContextSnapshot::GetReferenceTable() {
- return g_v8_context_snapshot_reference_table;
-}
-
-v8::StartupData V8ContextSnapshot::TakeSnapshot() {
- DCHECK_EQ(V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate())
- ->GetV8ContextSnapshotMode(),
- V8PerIsolateData::V8ContextSnapshotMode::kTakeSnapshot);
-
- v8::SnapshotCreator* creator =
- V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate())
- ->GetSnapshotCreator();
- v8::Isolate* isolate = creator->GetIsolate();
- CHECK_EQ(isolate, v8::Isolate::GetCurrent());
-
- VLOG(1) << "External reference table has " << CountExternalReferenceEntries()
- << " entries.";
-
- // Disable all runtime enabled features
- RuntimeEnabledFeatures::SetStableFeaturesEnabled(false);
- RuntimeEnabledFeatures::SetExperimentalFeaturesEnabled(false);
- RuntimeEnabledFeatures::SetTestFeaturesEnabled(false);
-
- {
- v8::HandleScope handleScope(isolate);
- creator->SetDefaultContext(v8::Context::New(isolate));
-
- TakeSnapshotForWorld(creator, DOMWrapperWorld::MainWorld());
- // For non main worlds, we can use any type to create a context.
- TakeSnapshotForWorld(
- creator,
- *DOMWrapperWorld::Create(
- isolate, DOMWrapperWorld::WorldType::kForV8ContextSnapshotNonMain));
- }
-
- isolate->RemoveMessageListeners(V8Initializer::MessageHandlerInMainThread);
-
- return creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
-}
-
-v8::StartupData V8ContextSnapshot::SerializeInternalField(
- v8::Local<v8::Object> object,
- int index,
- void*) {
- InternalFieldType field_type = InternalFieldType::kNone;
- const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(object);
- if (kV8DOMWrapperObjectIndex == index) {
- if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) {
- field_type = InternalFieldType::kHTMLDocumentObject;
- }
- DCHECK_LE(kV8DefaultWrapperInternalFieldCount,
- object->InternalFieldCount());
- } else if (kV8DOMWrapperTypeIndex == index) {
- if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) {
- field_type = InternalFieldType::kHTMLDocumentType;
- } else if (blink::V8Document::wrapperTypeInfo.Equals(wrapper_type)) {
- field_type = InternalFieldType::kDocumentType;
- } else if (blink::V8Node::wrapperTypeInfo.Equals(wrapper_type)) {
- field_type = InternalFieldType::kNodeType;
- }
- DCHECK_LE(kV8PrototypeInternalFieldcount, object->InternalFieldCount());
- }
- CHECK_NE(field_type, InternalFieldType::kNone);
-
- int size = sizeof(InternalFieldType);
- // Allocated memory on |data| will be released in
- // v8::i::PartialSerializer::SerializeEmbedderFields().
- char* data = new char[size];
- std::memcpy(data, &field_type, size);
-
- return {data, size};
-}
-
-void V8ContextSnapshot::DeserializeInternalField(v8::Local<v8::Object> object,
- int index,
- v8::StartupData payload,
- void* ptr) {
- // DeserializeInternalField() expects to be called in the main world
- // with |document| being HTMLDocument.
- CHECK_EQ(payload.raw_size, static_cast<int>(sizeof(InternalFieldType)));
- InternalFieldType type =
- *reinterpret_cast<const InternalFieldType*>(payload.data);
-
- const WrapperTypeInfo* wrapper_type_info = FieldTypeToWrapperTypeInfo(type);
- switch (type) {
- case InternalFieldType::kNodeType:
- case InternalFieldType::kDocumentType:
- case InternalFieldType::kHTMLDocumentType: {
- CHECK_EQ(index, kV8DOMWrapperTypeIndex);
- object->SetAlignedPointerInInternalField(
- index, const_cast<WrapperTypeInfo*>(wrapper_type_info));
- return;
- }
- case InternalFieldType::kHTMLDocumentObject: {
- // The below code handles window.document on the main world.
- CHECK_EQ(index, kV8DOMWrapperObjectIndex);
- v8::Isolate* isolate = v8::Isolate::GetCurrent();
- DataForDeserializer* data = static_cast<DataForDeserializer*>(ptr);
- ScriptWrappable* document = data->document;
- DCHECK(document);
-
- // Make reference from wrapper to document
- object->SetAlignedPointerInInternalField(index, document);
- // Make reference from document to wrapper
- CHECK(document->SetWrapper(isolate, wrapper_type_info, object));
- WrapperTypeInfo::WrapperCreated();
- return;
- }
- case InternalFieldType::kNone:
- NOTREACHED();
- return;
- }
-
- NOTREACHED();
-}
-
-bool V8ContextSnapshot::CanCreateContextFromSnapshot(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world,
- Document* document) {
- DCHECK(document);
- if (V8PerIsolateData::From(isolate)->GetV8ContextSnapshotMode() !=
- V8PerIsolateData::V8ContextSnapshotMode::kUseSnapshot) {
- return false;
- }
-
- // When creating a context for the main world from snapshot, we also need a
- // HTMLDocument instance. If typeof window.document is not HTMLDocument, e.g.
- // SVGDocument or XMLDocument, we can't create contexts from the snapshot.
- return !world.IsMainWorld() || document->IsHTMLDocument();
-}
-
-void V8ContextSnapshot::EnsureInterfaceTemplatesForWorld(
- v8::Isolate* isolate,
- const DOMWrapperWorld& world) {
- V8PerIsolateData* data = V8PerIsolateData::From(isolate);
-
- // A snapshot has some interface templates in it. The first
- // |kSnapshotInterfaceSize| templates are for the main world, and the
- // remaining templates are for isolated worlds.
- const int index_offset = world.IsMainWorld() ? 0 : kSnapshotInterfaceSize;
-
- for (size_t i = 0; i < kSnapshotInterfaceSize; ++i) {
- auto& snapshot_interface = g_snapshot_interfaces[i];
- const WrapperTypeInfo* wrapper_type_info =
- snapshot_interface.wrapper_type_info;
- v8::Local<v8::FunctionTemplate> interface_template =
- v8::FunctionTemplate::FromSnapshot(isolate, index_offset + i)
- .ToLocalChecked();
- snapshot_interface.install_function(isolate, world, interface_template);
- CHECK(!interface_template.IsEmpty());
- data->SetInterfaceTemplate(world, wrapper_type_info, interface_template);
- }
-}
-
-void V8ContextSnapshot::TakeSnapshotForWorld(v8::SnapshotCreator* creator,
- const DOMWrapperWorld& world) {
- v8::Isolate* isolate = creator->GetIsolate();
- CHECK_EQ(isolate, v8::Isolate::GetCurrent());
-
- // Function templates
- v8::HandleScope handleScope(isolate);
- std::array<v8::Local<v8::FunctionTemplate>, kSnapshotInterfaceSize>
- interface_templates;
- v8::Local<v8::FunctionTemplate> window_template;
- for (size_t i = 0; i < kSnapshotInterfaceSize; ++i) {
- const WrapperTypeInfo* wrapper_type_info =
- g_snapshot_interfaces[i].wrapper_type_info;
- v8::Local<v8::FunctionTemplate> interface_template =
- wrapper_type_info->domTemplate(isolate, world);
- CHECK(!interface_template.IsEmpty());
- interface_templates[i] = interface_template;
- if (V8Window::wrapperTypeInfo.Equals(wrapper_type_info)) {
- window_template = interface_template;
- }
- }
- CHECK(!window_template.IsEmpty());
-
- v8::Local<v8::ObjectTemplate> window_instance_template =
- window_template->InstanceTemplate();
- CHECK(!window_instance_template.IsEmpty());
-
- v8::Local<v8::Context> context;
- {
- V8PerIsolateData::UseCounterDisabledScope use_counter_disabled(
- V8PerIsolateData::From(isolate));
- context = v8::Context::New(isolate, nullptr, window_instance_template);
- }
- CHECK(!context.IsEmpty());
-
- // For the main world context, we need to prepare a HTMLDocument wrapper and
- // set it to window.documnt.
- if (world.IsMainWorld()) {
- v8::Context::Scope scope(context);
- v8::Local<v8::Object> document_wrapper = CreatePlainWrapper(
- isolate, world, context, &V8HTMLDocument::wrapperTypeInfo);
- int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex};
- void* values[] = {nullptr, const_cast<WrapperTypeInfo*>(
- &V8HTMLDocument::wrapperTypeInfo)};
- document_wrapper->SetAlignedPointerInInternalFields(
- WTF_ARRAY_LENGTH(indices), indices, values);
-
- // Set the cached accessor for window.document.
- CHECK(V8PrivateProperty::GetWindowDocumentCachedAccessor(isolate).Set(
- context->Global(), document_wrapper));
- }
-
- for (auto& interface_template : interface_templates) {
- creator->AddTemplate(interface_template);
- }
- creator->AddContext(context, SerializeInternalField);
-
- V8PerIsolateData::From(isolate)->ClearPersistentsForV8ContextSnapshot();
-}
-
-} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698