Chromium Code Reviews| Index: third_party/WebKit/Source/bindings/core/v8/V8SnapshotCreator.cpp |
| diff --git a/third_party/WebKit/Source/bindings/core/v8/V8SnapshotCreator.cpp b/third_party/WebKit/Source/bindings/core/v8/V8SnapshotCreator.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3f1b7845170361b09ece6ff7972048cf7c38bf6a |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/bindings/core/v8/V8SnapshotCreator.cpp |
| @@ -0,0 +1,232 @@ |
| +#include "bindings/core/v8/V8SnapshotCreator.h" |
|
Yuki
2017/05/12 15:20:10
Copyright?
peria
2017/05/30 08:25:42
Done.
|
| + |
| +#include <cstring> |
| + |
| +#include "bindings/core/v8/GeneratedCodeHelper.h" |
| +#include "bindings/core/v8/V8Document.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.h> |
|
Yuki
2017/05/12 15:20:10
s|<v8.h>|"v8/include/v8.h"|
peria
2017/05/30 08:25:42
Done.
|
| + |
| +namespace blink { |
| + |
| +namespace { |
| + |
| +bool g_taking_snapshot = false; |
|
Yuki
2017/05/15 09:37:29
Put a comment when this is true and what is guaran
peria
2017/05/30 08:25:42
Done.
|
| + |
| +// NOTE(peria): This method is almost a copy of |
| +// V8PerContext::CreateWrapperFromCacheSlowCase(). |
| +v8::Local<v8::Function> ConstructPlainType(v8::Isolate* isolate, |
|
Yuki
2017/05/15 09:37:29
Let's merge this code into V8PerContextData::Const
peria
2017/05/30 08:25:42
Acknowledged.
|
| + 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)) |
| + 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)); |
| + 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; |
| +} |
| + |
| +// NOTE(peria): This method is almost a copy of |
| +// V8PerContext::CreateWrapperFromCacheSlowCase(). |
| +v8::Local<v8::Object> CreatePlainWrapper(v8::Isolate* isolate, |
|
Yuki
2017/05/15 09:37:29
Ditto.
peria
2017/05/30 08:25:42
Acknowledged.
|
| + 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)); |
| + v8::Local<v8::Object> wrapper = instance_template->Clone(); |
| + wrapper->SetAlignedPointerInInternalField(kV8DOMWrapperTypeIndex, |
| + const_cast<WrapperTypeInfo*>(type)); |
| + return wrapper; |
| +} |
| + |
| +} // namespace |
| + |
| +void V8SnapshotCreator::TakeSnapshot(v8::SnapshotCreator* creator, |
| + int world_id) { |
| + DCHECK(g_taking_snapshot); |
| + v8::Isolate* isolate = creator->GetIsolate(); |
| + CHECK_EQ(isolate, v8::Isolate::GetCurrent()); |
| + |
| + RefPtr<DOMWrapperWorld> world_ptr; |
| + if (world_id == 0) { |
| + world_ptr = &DOMWrapperWorld::MainWorld(); |
| + } else { |
| + world_ptr = DOMWrapperWorld::EnsureIsolatedWorld(isolate, world_id); |
| + } |
| + const DOMWrapperWorld& world = *world_ptr; |
| + |
| + // Function templates |
| + v8::HandleScope handleScope(isolate); |
| + v8::Local<v8::FunctionTemplate> event_target_function_template = |
|
Yuki
2017/05/15 09:37:29
nit: We could have an array of WrapperTypeInfo or
peria
2017/05/30 08:25:42
Done.
|
| + V8EventTarget::domTemplate(isolate, world); |
| + CHECK(!event_target_function_template.IsEmpty()); |
| + |
| + v8::Local<v8::FunctionTemplate> window_function_template = |
| + V8Window::domTemplate(isolate, world); |
| + CHECK(!window_function_template.IsEmpty()); |
| + |
| + v8::Local<v8::FunctionTemplate> node_function_template = |
| + V8Node::domTemplate(isolate, world); |
| + CHECK(!node_function_template.IsEmpty()); |
| + |
| + v8::Local<v8::FunctionTemplate> document_function_template = |
| + V8Document::domTemplate(isolate, world); |
| + CHECK(!document_function_template.IsEmpty()); |
| + |
| + v8::Local<v8::FunctionTemplate> html_document_function_template = |
| + V8HTMLDocument::domTemplate(isolate, world); |
| + CHECK(!html_document_function_template.IsEmpty()); |
| + |
| + v8::Local<v8::ObjectTemplate> window_template = |
| + window_function_template->InstanceTemplate(); |
| + CHECK(!window_template.IsEmpty()); |
| + |
| + v8::Local<v8::Context> context; |
| + v8::Local<v8::Object> wrapper; |
| + { |
| + V8PerIsolateData::UseCounterDisabledScope use_counter_disabled( |
| + V8PerIsolateData::From(isolate)); |
| + context = v8::Context::New(isolate, nullptr, window_template); |
| + } |
| + CHECK(!context.IsEmpty()); |
| + |
| + if (world.IsMainWorld()) { |
| + context->Enter(); |
| + v8::Context::Scope scope(context); |
| + wrapper = CreatePlainWrapper(isolate, world, context, |
| + &V8HTMLDocument::wrapperTypeInfo); |
| + CHECK(!wrapper.IsEmpty()); |
| + int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex}; |
| + void* values[] = {nullptr, const_cast<WrapperTypeInfo*>( |
| + &V8HTMLDocument::wrapperTypeInfo)}; |
| + wrapper->SetAlignedPointerInInternalFields(WTF_ARRAY_LENGTH(indices), |
| + indices, values); |
| + |
| + V8PrivateProperty::Symbol symbol = |
| + V8PrivateProperty::GetWindowDocumentCachedAccessor(isolate); |
| + CHECK(V8CallBoolean( |
| + context->Global()->SetPrivate(context, symbol.GetPrivate(), wrapper))); |
| + context->Exit(); |
| + } |
| + |
| + creator->AddTemplate(event_target_function_template); |
| + creator->AddTemplate(window_function_template); |
| + creator->AddTemplate(node_function_template); |
| + creator->AddTemplate(document_function_template); |
| + creator->AddTemplate(html_document_function_template); |
| + creator->AddContext(context, Serialize); |
| + |
| + V8PerIsolateData::From(isolate)->ClearAll(); |
| + isolate->RemoveMessageListeners(V8Initializer::MessageHandlerInMainThread); |
|
Yuki
2017/05/15 09:37:29
Please comment why we need to remove message liste
peria
2017/05/30 08:25:42
Done.
|
| +} |
| + |
| +v8::StartupData V8SnapshotCreator::SetUpSnapshotCreator( |
| + v8::SnapshotCreator* creator) { |
| + v8::Isolate* isolate = creator->GetIsolate(); |
| + CHECK_EQ(isolate, v8::Isolate::GetCurrent()); |
| + |
| + // Disable all runtime enabled featuers |
| + RuntimeEnabledFeatures::setStableFeaturesEnabled(false); |
| + RuntimeEnabledFeatures::setExperimentalFeaturesEnabled(false); |
| + RuntimeEnabledFeatures::setTestFeaturesEnabled(false); |
|
Yuki
2017/05/15 09:37:29
Is there any good way to confirm that we've not ye
Yuki
2017/05/15 09:37:29
nit: We might want to define RuntimeEnabledFeature
peria
2017/05/30 08:25:42
Acknowledged.
peria
2017/06/20 10:20:13
Acknowledged.
|
| + |
| + { |
| + v8::HandleScope handleScope(isolate); |
| + creator->SetDefaultContext(v8::Context::New(isolate)); |
| + |
| + TakeSnapshot(creator, 0); // main world |
| + TakeSnapshot(creator, 1); // non main world |
|
Yuki
2017/05/15 09:37:29
I'm not happy with use of the magic numbers. Shal
peria
2017/05/30 08:25:42
Done.
|
| + } |
| + |
| + return creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); |
| +} |
| + |
| +v8::SnapshotCreator* V8SnapshotCreator::GetSnapshotCreator() { |
| + DCHECK(g_taking_snapshot); |
|
Yuki
2017/05/15 09:37:29
Add a DCHECK to confirm that it's the main thread.
peria
2017/05/30 08:25:42
Acknowledged.
|
| + return V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate()) |
| + ->GetSnapshotCreator(); |
| +} |
| + |
| +bool V8SnapshotCreator::TakingSnapshot() { |
| + return g_taking_snapshot; |
|
Yuki
2017/05/15 09:37:29
Add a DCHECK to confirm that it's the main thread.
peria
2017/05/30 08:25:42
Acknowledged.
|
| +} |
| + |
| +void V8SnapshotCreator::SetTakingSnapshot(bool value) { |
| + g_taking_snapshot = value; |
| +} |
| + |
| +v8::StartupData V8SnapshotCreator::Serialize(v8::Local<v8::Object> holder, |
|
Yuki
2017/05/15 09:37:29
s/Serialize/Serialize(An)InternalField/
Let's make
peria
2017/05/30 08:25:42
Done.
|
| + int index, |
| + void* /*data*/) { |
| + FieldType field_type = kNone; |
| + const WrapperTypeInfo* wrapper_type = ToWrapperTypeInfo(holder); |
| + if (blink::V8HTMLDocument::wrapperTypeInfo.Equals(wrapper_type)) { |
| + if (kV8DOMWrapperObjectIndex == index) { |
| + field_type = kHTMLDocumentObject; |
| + } else if (kV8DOMWrapperTypeIndex == index) { |
| + field_type = kHTMLDocumentType; |
| + } |
| + } else if (blink::V8Document::wrapperTypeInfo.Equals(wrapper_type) && |
| + kV8DOMWrapperTypeIndex == index) { |
| + field_type = kDocumentType; |
| + } else if (blink::V8Node::wrapperTypeInfo.Equals(wrapper_type) && |
| + kV8DOMWrapperTypeIndex == index) { |
| + field_type = kNodeType; |
| + } |
| + |
| + // To confirm covering all patterns to be serialized. |
| + CHECK_NE(field_type, kNone); |
| + |
| + int size = sizeof(FieldType); |
| + char* data = new char[size]; |
| + std::memcpy(data, &field_type, size); |
| + |
| + return {data, size}; |
| +} |
| + |
| +} // namespace blink |