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

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

Issue 2841443005: [Bindings] Create and use V8 context snapshots (Closed)
Patch Set: Work for yuki's comments Created 3 years, 6 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/V8SnapshotUtil.cpp
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8SnapshotUtil.cpp b/third_party/WebKit/Source/bindings/core/v8/V8SnapshotUtil.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7be4228905ef5083414b17cf15c3aa2a499f0de9
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/V8SnapshotUtil.cpp
@@ -0,0 +1,498 @@
+// 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/V8SnapshotUtil.h"
+
+#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 "v8/include/v8.h"
+
+namespace blink {
+
+namespace {
+
+intptr_t* g_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;
+ if (!interface_template->GetFunction(context).ToLocal(&interface_object))
Yuki 2017/06/23 15:20:45 s/ToLocal/ToLocalChecked/
peria 2017/06/27 09:52:37 Done.
+ return v8::Local<v8::Function>();
+
+ 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;
+ CHECK(interface_object->Get(context, V8AtomicString(isolate, "prototype"))
+ .ToLocal(&prototype_value));
Yuki 2017/06/23 15:20:44 s/CHECK(...ToLocal(...))/ToLocalChecked()/
peria 2017/06/27 09:52:37 Done.
+ 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;
+ CHECK(V8ObjectConstructor::NewInstance(isolate, interface_object)
+ .ToLocal(&instance_template));
Yuki 2017/06/23 15:20:44 s/CHECK(...ToLocal(...))/ToLocalChecked()/
peria 2017/06/27 09:52:37 Done.
+ v8::Local<v8::Object> wrapper = instance_template->Clone();
+ wrapper->SetAlignedPointerInInternalField(kV8DOMWrapperTypeIndex,
+ const_cast<WrapperTypeInfo*>(type));
+ return wrapper;
+}
+
+constexpr int kWorldIdForNonMainWorld =
+ DOMWrapperWorld::WorldId::kIsolatedWorldIdLimit - 1;
+
+int GetSnapshotIndexForWorld(const DOMWrapperWorld& world) {
+ return world.IsMainWorld() ? 0 : 1;
+}
+
+constexpr const WrapperTypeInfo* kSnapshotWrapperTypes[] = {
+ &V8Window::wrapperTypeInfo, &V8HTMLDocument::wrapperTypeInfo,
+ &V8EventTarget::wrapperTypeInfo, &V8Node::wrapperTypeInfo,
+ &V8Document::wrapperTypeInfo,
+};
+
+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_snapshot_reference_table)
+ return 0;
+
+ int count = 0;
+ for (intptr_t* p = g_snapshot_reference_table; *p; ++p)
+ ++count;
+ return count;
+}
+
+} // namespace
+
+v8::StartupData V8SnapshotUtil::TakeSnapshot() {
+ DCHECK_EQ(V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate())
+ ->GetV8ContextMode(),
+ V8PerIsolateData::V8ContextMode::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 featuers
+ 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::EnsureIsolatedWorld(
+ isolate, kWorldIdForNonMainWorld));
+ }
+
+ // Snapshot is taken on the main thread, but it can be used on other threads.
+ // So we remove a message handler for the main thread.
+ isolate->RemoveMessageListeners(V8Initializer::MessageHandlerInMainThread);
+
+ return creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
+}
+
+void V8SnapshotUtil::TakeSnapshotForWorld(v8::SnapshotCreator* creator,
Yuki 2017/06/23 15:20:45 Be consistent with the declaration order in the he
peria 2017/06/27 09:52:37 Done.
+ const DOMWrapperWorld& world) {
+ v8::Isolate* isolate = creator->GetIsolate();
+ CHECK_EQ(isolate, v8::Isolate::GetCurrent());
+
+ // Function templates
+ v8::HandleScope handleScope(isolate);
+ Vector<v8::Local<v8::FunctionTemplate>> interface_templates;
Yuki 2017/06/23 15:20:45 It's not allowed to put v8::Local on heap. Vector
peria 2017/06/27 09:52:37 Done.
+ for (const WrapperTypeInfo* wrapper_type_info : kSnapshotWrapperTypes) {
+ v8::Local<v8::FunctionTemplate> interface_template =
+ wrapper_type_info->domTemplate(isolate, world);
+ CHECK(!interface_template.IsEmpty());
+ interface_templates.push_back(interface_template);
+ }
+
+ // TODO(peria): Confirm interface_tempaltes[0] is a template of V8Window.
+ v8::Local<v8::ObjectTemplate> window_template =
+ interface_templates[0]->InstanceTemplate();
+ CHECK(!window_template.IsEmpty());
+
+ v8::Local<v8::Context> context;
+ {
+ V8PerIsolateData::UseCounterDisabledScope use_counter_disabled(
+ V8PerIsolateData::From(isolate));
+ context = v8::Context::New(isolate, nullptr, window_template);
+ }
+ CHECK(!context.IsEmpty());
+
+ 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);
+
+ // Update the cached accessor for window.document.
+ CHECK(V8PrivateProperty::GetWindowDocumentCachedAccessor(isolate).Set(
Yuki 2017/06/23 15:20:44 Probably, this should be gone. You're now setting
peria 2017/06/27 09:52:37 Hmm. This code is required here to keep the HTMLDo
+ context->Global(), document_wrapper));
+ }
+
+ for (auto& interface_template : interface_templates) {
+ creator->AddTemplate(interface_template);
+ }
+ creator->AddContext(context, SerializeInternalField);
+
+ V8PerIsolateData::From(isolate)->ClearPersistentsForV8Snapshot();
+}
+
+void V8SnapshotUtil::EnsureInterfaceTemplates(v8::Isolate* isolate) {
+ if (V8PerIsolateData::From(isolate)->GetV8ContextMode() !=
+ V8PerIsolateData::V8ContextMode::kUseSnapshot) {
+ return;
+ }
+
+ EnsureInterfaceTemplatesForWorld(isolate, DOMWrapperWorld::MainWorld());
+ EnsureInterfaceTemplatesForWorld(
+ isolate,
+ *DOMWrapperWorld::EnsureIsolatedWorld(isolate, kWorldIdForNonMainWorld));
+}
+
+void V8SnapshotUtil::EnsureInterfaceTemplatesForWorld(
+ v8::Isolate* isolate,
+ const DOMWrapperWorld& world) {
+ V8PerIsolateData* data = V8PerIsolateData::From(isolate);
+ for (const WrapperTypeInfo* wrapper_type_info : kSnapshotWrapperTypes) {
+ v8::Local<v8::FunctionTemplate> interface =
+ InterfaceTemplateFromSnapshot(isolate, world, wrapper_type_info);
+ CHECK(!interface.IsEmpty());
+ data->SetInterfaceTemplate(world, wrapper_type_info, interface);
+ }
+}
+
+v8::Local<v8::FunctionTemplate> V8SnapshotUtil::InterfaceTemplateFromSnapshot(
Yuki 2017/06/23 15:20:44 InterfaceTemplateFromSnapshot is only used in Ensu
peria 2017/06/27 09:52:37 Done.
+ v8::Isolate* isolate,
+ const DOMWrapperWorld& world,
+ const WrapperTypeInfo* wrapper_type_info) {
+ const int index_offset =
+ world.IsMainWorld() ? 0 : WTF_ARRAY_LENGTH(kSnapshotWrapperTypes);
+
+ if (V8Window::wrapperTypeInfo.Equals(wrapper_type_info)) {
+ v8::Local<v8::FunctionTemplate> interface_template =
+ v8::FunctionTemplate::FromSnapshot(isolate, index_offset + 0)
+ .ToLocalChecked();
+ V8Window::installV8WindowRuntimeEnabledOnTemplateFunction(
Yuki 2017/06/23 15:20:44 s/installV8Window.../InstallV8Window.../ Does thi
peria 2017/06/27 09:52:37 For V8Window, we call it via static function point
+ isolate, world, interface_template);
+ return interface_template;
+ }
+ if (V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type_info)) {
+ v8::Local<v8::FunctionTemplate> interface_template =
+ v8::FunctionTemplate::FromSnapshot(isolate, index_offset + 1)
+ .ToLocalChecked();
+ V8HTMLDocument::InstallRuntimeEnabledFeaturesOnTemplate(isolate, world,
+ interface_template);
+ return interface_template;
+ }
+ if (V8EventTarget::wrapperTypeInfo.Equals(wrapper_type_info)) {
+ v8::Local<v8::FunctionTemplate> interface_template =
+ v8::FunctionTemplate::FromSnapshot(isolate, index_offset + 2)
+ .ToLocalChecked();
+ V8EventTarget::InstallRuntimeEnabledFeaturesOnTemplate(isolate, world,
+ interface_template);
+ return interface_template;
+ }
+ if (V8Node::wrapperTypeInfo.Equals(wrapper_type_info)) {
+ v8::Local<v8::FunctionTemplate> interface_template =
+ v8::FunctionTemplate::FromSnapshot(isolate, index_offset + 3)
+ .ToLocalChecked();
+ V8Node::InstallRuntimeEnabledFeaturesOnTemplate(isolate, world,
+ interface_template);
+ return interface_template;
+ }
+ if (V8Document::wrapperTypeInfo.Equals(wrapper_type_info)) {
+ v8::Local<v8::FunctionTemplate> interface_template =
+ v8::FunctionTemplate::FromSnapshot(isolate, index_offset + 4)
+ .ToLocalChecked();
+ V8Document::InstallRuntimeEnabledFeaturesOnTemplate(isolate, world,
+ interface_template);
+ return interface_template;
+ }
+
+ NOTREACHED();
+ return v8::Local<v8::FunctionTemplate>();
+}
+
+v8::StartupData V8SnapshotUtil::SerializeInternalField(
+ v8::Local<v8::Object> holder,
+ int index,
+ void*) {
+ InternalFieldType field_type = InternalFieldType::kNone;
+ const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(holder);
+ if (kV8DOMWrapperObjectIndex == index) {
+ if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) {
+ field_type = InternalFieldType::kHTMLDocumentObject;
+ }
+ } 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;
+ }
+ }
+ CHECK_NE(field_type, InternalFieldType::kNone);
+
+ int size = sizeof(InternalFieldType);
+ char* data = new char[size];
+ std::memcpy(data, &field_type, size);
+
+ return {data, size};
+}
+
+void V8SnapshotUtil::DeserializeInternalField(v8::Local<v8::Object> holder,
Yuki 2017/06/23 15:20:44 s/holder/object/ This is not relevant to a holder
peria 2017/06/27 09:52:37 Done.
+ 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);
+ holder->SetAlignedPointerInInternalField(
+ index, const_cast<WrapperTypeInfo*>(wrapper_type_info));
+ return;
+ }
+ case InternalFieldType::kHTMLDocumentObject: {
+ 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
+ holder->SetAlignedPointerInInternalField(index, document);
+ // Make reference from document to wrapper
+ CHECK(document->SetWrapper(isolate, wrapper_type_info, holder));
+ WrapperTypeInfo::WrapperCreated();
+ return;
+ }
+ case InternalFieldType::kNone:
+ NOTREACHED();
+ return;
+ }
+
+ NOTREACHED();
+}
+
+v8::Local<v8::Context> V8SnapshotUtil::CreateContext(
+ v8::Isolate* isolate,
+ const DOMWrapperWorld& world,
+ v8::ExtensionConfiguration* extension_configuration,
+ v8::Local<v8::Object> global_proxy,
+ Document* document) {
+ if (V8PerIsolateData::From(isolate)->GetV8ContextMode() !=
+ V8PerIsolateData::V8ContextMode::kUseSnapshot) {
+ return v8::Local<v8::Context>();
+ }
+ // For main world frames, we don't support the case that |document| is not
+ // an instance of HTMLDocument, e.g. XMLDocument.
+ if (world.IsMainWorld() && !(document && document->IsHTMLDocument())) {
+ 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();
+ CHECK(!context.IsEmpty());
+ DVLOG(1) << "A context is created from snapshot";
+
+ return context;
+}
+
+void V8SnapshotUtil::SetupContext(v8::Local<v8::Context> context,
+ Document* document) {
+ ScriptState* script_state = ScriptState::From(context);
+ v8::Isolate* isolate = script_state->GetIsolate();
+ if (V8PerIsolateData::From(isolate)->GetV8ContextMode() !=
+ V8PerIsolateData::V8ContextMode::kUseSnapshot) {
+ return;
+ }
+
+ v8::Local<v8::String> prototype_str = V8AtomicString(isolate, "prototype");
+ DOMWrapperWorld& world = script_state->World();
+ 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 = &V8EventTarget::wrapperTypeInfo;
+ v8::Local<v8::Function> constructor = data->ConstructorForType(type);
Yuki 2017/06/23 15:20:44 nit: s/constructor/interface/ We're not intereste
peria 2017/06/27 09:52:37 Done.
+ v8::Local<v8::Object> prototype = constructor->Get(context, prototype_str)
+ .ToLocalChecked()
+ .As<v8::Object>();
+ V8EventTarget::InstallRuntimeEnabledFeatures(isolate, world, window_wrapper,
+ prototype, constructor);
+ }
+ {
+ const WrapperTypeInfo* type = &V8Window::wrapperTypeInfo;
+ v8::Local<v8::Function> constructor = data->ConstructorForType(type);
+ v8::Local<v8::Object> prototype = constructor->Get(context, prototype_str)
+ .ToLocalChecked()
+ .As<v8::Object>();
+ V8Window::installV8WindowRuntimeEnabledFunction(
+ isolate, world, window_wrapper, prototype, constructor);
+ }
+
+ // In case we create a context for the main world from snapshot, we also have
+ // to work for HTMLDocument wrapper and its prototype chain.
+ if (world.IsMainWorld() && document && document->IsHTMLDocument()) {
Yuki 2017/06/23 15:20:44 This condition must appear at the very beginning o
peria 2017/06/27 09:52:37 Done.
+ CHECK(document->ContainsWrapper());
+ v8::Local<v8::Object> document_wrapper =
+ document->MainWorldWrapper(isolate);
+
+ {
+ // Prototype object and interface object of EventTarget were set up with
+ // Window wrapper.
+ V8EventTarget::InstallRuntimeEnabledFeatures(
+ isolate, world, document_wrapper, v8::Local<v8::Object>(),
+ v8::Local<v8::Function>());
+ }
+ {
+ const WrapperTypeInfo* type = &V8Node::wrapperTypeInfo;
+ v8::Local<v8::Function> constructor = data->ConstructorForType(type);
+ v8::Local<v8::Object> prototype = constructor->Get(context, prototype_str)
+ .ToLocalChecked()
+ .As<v8::Object>();
+ V8Node::InstallRuntimeEnabledFeatures(isolate, world, document_wrapper,
+ prototype, constructor);
+ }
+ {
+ const WrapperTypeInfo* type = &V8Document::wrapperTypeInfo;
+ v8::Local<v8::Function> constructor = data->ConstructorForType(type);
+ v8::Local<v8::Object> prototype = constructor->Get(context, prototype_str)
+ .ToLocalChecked()
+ .As<v8::Object>();
+ V8Document::InstallRuntimeEnabledFeatures(
+ isolate, world, document_wrapper, prototype, constructor);
+ }
+ {
+ const WrapperTypeInfo* type = &V8HTMLDocument::wrapperTypeInfo;
+ v8::Local<v8::Function> constructor = data->ConstructorForType(type);
+ v8::Local<v8::Object> prototype = constructor->Get(context, prototype_str)
+ .ToLocalChecked()
+ .As<v8::Object>();
+ V8HTMLDocument::InstallRuntimeEnabledFeatures(
+ isolate, world, document_wrapper, prototype, constructor);
+ }
+ }
+}
+
+void V8SnapshotUtil::SetReferenceTable(intptr_t* table) {
+ DCHECK(!g_snapshot_reference_table);
+ g_snapshot_reference_table = table;
+}
+
+intptr_t* V8SnapshotUtil::GetReferenceTable() {
+ DCHECK(g_snapshot_reference_table);
+ return g_snapshot_reference_table;
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698