| 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..8f74186d124f2a90002709d141699a1c52845fb9 | 
| --- /dev/null | 
| +++ b/third_party/WebKit/Source/bindings/core/v8/V8SnapshotCreator.cpp | 
| @@ -0,0 +1,232 @@ | 
| +#include "bindings/core/v8/V8SnapshotCreator.h" | 
| + | 
| +#include <cstring> | 
| + | 
| +#include "bindings/core/v8/DOMWrapperWorld.h" | 
| +#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/V8ObjectConstructor.h" | 
| +#include "bindings/core/v8/V8PerIsolateData.h" | 
| +#include "bindings/core/v8/V8PrivateProperty.h" | 
| +#include "bindings/core/v8/V8Window.h" | 
| + | 
| +#include <v8.h> | 
| + | 
| +namespace blink { | 
| + | 
| +namespace { | 
| + | 
| +bool g_taking_snapshot = false; | 
| + | 
| +// NOTE(peria): This method is almost a copy of | 
| +// V8PerContext::CreateWrapperFromCacheSlowCase(). | 
| +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)) | 
| +    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, | 
| +                                         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 = | 
| +      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); | 
| +} | 
| + | 
| +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); | 
| + | 
| +  { | 
| +    v8::HandleScope handleScope(isolate); | 
| +    creator->SetDefaultContext(v8::Context::New(isolate)); | 
| + | 
| +    TakeSnapshot(creator, 0);  // main world | 
| +    TakeSnapshot(creator, 1);  // non main world | 
| +  } | 
| + | 
| +  return creator->CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); | 
| +} | 
| + | 
| +v8::SnapshotCreator* V8SnapshotCreator::GetSnapshotCreator() { | 
| +  DCHECK(g_taking_snapshot); | 
| +  return V8PerIsolateData::From(V8PerIsolateData::MainThreadIsolate()) | 
| +      ->GetSnapshotCreator(); | 
| +} | 
| + | 
| +bool V8SnapshotCreator::TakingSnapshot() { | 
| +  return g_taking_snapshot; | 
| +} | 
| + | 
| +void V8SnapshotCreator::SetTakingSnapshot(bool value) { | 
| +  g_taking_snapshot = value; | 
| +} | 
| + | 
| +v8::StartupData V8SnapshotCreator::Serialize(v8::Local<v8::Object> holder, | 
| +                                             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 | 
|  |