Commit c5ae5bb1 authored by yangguo's avatar yangguo Committed by Commit bot

[snapshot] support including templates in the snapshot.

R=jochen@chromium.org, verwaest@chromium.org
BUG=chromium:617892

Review-Url: https://codereview.chromium.org/2076083002
Cr-Commit-Position: refs/heads/master@{#37122}
parent 6773ee25
...@@ -4487,6 +4487,9 @@ class V8_EXPORT FunctionTemplate : public Template { ...@@ -4487,6 +4487,9 @@ class V8_EXPORT FunctionTemplate : public Template {
Local<Value> data = Local<Value>(), Local<Value> data = Local<Value>(),
Local<Signature> signature = Local<Signature>(), int length = 0); Local<Signature> signature = Local<Signature>(), int length = 0);
/** Get a template included in the snapshot by index. */
static Local<FunctionTemplate> FromSnapshot(Isolate* isolate, size_t index);
/** /**
* Creates a function template with a fast handler. If a fast handler is set, * Creates a function template with a fast handler. If a fast handler is set,
* the callback cannot be null. * the callback cannot be null.
...@@ -4662,6 +4665,9 @@ class V8_EXPORT ObjectTemplate : public Template { ...@@ -4662,6 +4665,9 @@ class V8_EXPORT ObjectTemplate : public Template {
Local<FunctionTemplate> constructor = Local<FunctionTemplate>()); Local<FunctionTemplate> constructor = Local<FunctionTemplate>());
static V8_DEPRECATED("Use isolate version", Local<ObjectTemplate> New()); static V8_DEPRECATED("Use isolate version", Local<ObjectTemplate> New());
/** Get a template included in the snapshot by index. */
static Local<ObjectTemplate> FromSnapshot(Isolate* isolate, size_t index);
/** Creates a new instance of this template.*/ /** Creates a new instance of this template.*/
V8_DEPRECATE_SOON("Use maybe version", Local<Object> NewInstance()); V8_DEPRECATE_SOON("Use maybe version", Local<Object> NewInstance());
V8_WARN_UNUSED_RESULT MaybeLocal<Object> NewInstance(Local<Context> context); V8_WARN_UNUSED_RESULT MaybeLocal<Object> NewInstance(Local<Context> context);
...@@ -6810,6 +6816,12 @@ class SnapshotCreator { ...@@ -6810,6 +6816,12 @@ class SnapshotCreator {
*/ */
size_t AddContext(Local<Context> context); size_t AddContext(Local<Context> context);
/**
* Add a template to be included in the snapshot blob.
* \returns the index of the template in the snapshot blob.
*/
size_t AddTemplate(Local<Template> template_obj);
/** /**
* Created a snapshot data blob. * Created a snapshot data blob.
* This must not be called from within a handle scope. * This must not be called from within a handle scope.
......
...@@ -386,7 +386,10 @@ bool RunExtraCode(Isolate* isolate, Local<Context> context, ...@@ -386,7 +386,10 @@ bool RunExtraCode(Isolate* isolate, Local<Context> context,
struct SnapshotCreatorData { struct SnapshotCreatorData {
explicit SnapshotCreatorData(Isolate* isolate) explicit SnapshotCreatorData(Isolate* isolate)
: isolate_(isolate), contexts_(isolate), created_(false) {} : isolate_(isolate),
contexts_(isolate),
templates_(isolate),
created_(false) {}
static SnapshotCreatorData* cast(void* data) { static SnapshotCreatorData* cast(void* data) {
return reinterpret_cast<SnapshotCreatorData*>(data); return reinterpret_cast<SnapshotCreatorData*>(data);
...@@ -395,6 +398,7 @@ struct SnapshotCreatorData { ...@@ -395,6 +398,7 @@ struct SnapshotCreatorData {
ArrayBufferAllocator allocator_; ArrayBufferAllocator allocator_;
Isolate* isolate_; Isolate* isolate_;
PersistentValueVector<Context> contexts_; PersistentValueVector<Context> contexts_;
PersistentValueVector<Template> templates_;
bool created_; bool created_;
}; };
...@@ -442,12 +446,35 @@ size_t SnapshotCreator::AddContext(Local<Context> context) { ...@@ -442,12 +446,35 @@ size_t SnapshotCreator::AddContext(Local<Context> context) {
return index; return index;
} }
size_t SnapshotCreator::AddTemplate(Local<Template> template_obj) {
DCHECK(!template_obj.IsEmpty());
SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
DCHECK(!data->created_);
DCHECK_EQ(reinterpret_cast<i::Isolate*>(data->isolate_),
Utils::OpenHandle(*template_obj)->GetIsolate());
size_t index = static_cast<int>(data->templates_.Size());
data->templates_.Append(template_obj);
return index;
}
StartupData SnapshotCreator::CreateBlob( StartupData SnapshotCreator::CreateBlob(
SnapshotCreator::FunctionCodeHandling function_code_handling) { SnapshotCreator::FunctionCodeHandling function_code_handling) {
SnapshotCreatorData* data = SnapshotCreatorData::cast(data_); SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_);
DCHECK(!data->created_); DCHECK(!data->created_);
{
int num_templates = static_cast<int>(data->templates_.Size());
i::HandleScope scope(isolate);
i::Handle<i::FixedArray> templates =
isolate->factory()->NewFixedArray(num_templates, i::TENURED);
for (int i = 0; i < num_templates; i++) {
templates->set(i, *v8::Utils::OpenHandle(*data->templates_.Get(i)));
}
isolate->heap()->SetSerializedTemplates(*templates);
data->templates_.Clear();
}
// If we don't do this then we end up with a stray root pointing at the // If we don't do this then we end up with a stray root pointing at the
// context even after we have disposed of the context. // context even after we have disposed of the context.
isolate->heap()->CollectAllAvailableGarbage("mksnapshot"); isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
...@@ -1173,6 +1200,20 @@ Local<FunctionTemplate> FunctionTemplate::New(Isolate* isolate, ...@@ -1173,6 +1200,20 @@ Local<FunctionTemplate> FunctionTemplate::New(Isolate* isolate,
length, false); length, false);
} }
Local<FunctionTemplate> FunctionTemplate::FromSnapshot(Isolate* isolate,
size_t index) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::FixedArray* templates = i_isolate->heap()->serialized_templates();
int int_index = static_cast<int>(index);
if (int_index < templates->length()) {
i::Object* info = i_isolate->heap()->serialized_templates()->get(int_index);
if (info->IsFunctionTemplateInfo()) {
return Utils::ToLocal(i::Handle<i::FunctionTemplateInfo>(
i::FunctionTemplateInfo::cast(info)));
}
}
return Local<FunctionTemplate>();
}
Local<FunctionTemplate> FunctionTemplate::NewWithFastHandler( Local<FunctionTemplate> FunctionTemplate::NewWithFastHandler(
Isolate* isolate, FunctionCallback callback, Isolate* isolate, FunctionCallback callback,
...@@ -1384,6 +1425,21 @@ Local<ObjectTemplate> ObjectTemplate::New( ...@@ -1384,6 +1425,21 @@ Local<ObjectTemplate> ObjectTemplate::New(
return ObjectTemplateNew(isolate, constructor, false); return ObjectTemplateNew(isolate, constructor, false);
} }
Local<ObjectTemplate> ObjectTemplate::FromSnapshot(Isolate* isolate,
size_t index) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::FixedArray* templates = i_isolate->heap()->serialized_templates();
int int_index = static_cast<int>(index);
if (int_index < templates->length()) {
i::Object* info = i_isolate->heap()->serialized_templates()->get(int_index);
if (info->IsObjectTemplateInfo()) {
return Utils::ToLocal(
i::Handle<i::ObjectTemplateInfo>(i::ObjectTemplateInfo::cast(info)));
}
}
return Local<ObjectTemplate>();
}
// Ensure that the object template has a constructor. If no // Ensure that the object template has a constructor. If no
// constructor is available we create one. // constructor is available we create one.
static i::Handle<i::FunctionTemplateInfo> EnsureConstructor( static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
......
...@@ -732,6 +732,11 @@ int Heap::GetNextTemplateSerialNumber() { ...@@ -732,6 +732,11 @@ int Heap::GetNextTemplateSerialNumber() {
return next_serial_number; return next_serial_number;
} }
void Heap::SetSerializedTemplates(FixedArray* templates) {
DCHECK_EQ(empty_fixed_array(), serialized_templates());
set_serialized_templates(templates);
}
AlwaysAllocateScope::AlwaysAllocateScope(Isolate* isolate) AlwaysAllocateScope::AlwaysAllocateScope(Isolate* isolate)
: heap_(isolate->heap()) { : heap_(isolate->heap()) {
heap_->always_allocate_scope_count_.Increment(1); heap_->always_allocate_scope_count_.Increment(1);
......
...@@ -2897,6 +2897,8 @@ void Heap::CreateInitialObjects() { ...@@ -2897,6 +2897,8 @@ void Heap::CreateInitialObjects() {
handle(Smi::FromInt(Isolate::kArrayProtectorValid), isolate())); handle(Smi::FromInt(Isolate::kArrayProtectorValid), isolate()));
set_species_protector(*species_cell); set_species_protector(*species_cell);
set_serialized_templates(empty_fixed_array());
set_weak_stack_trace_list(Smi::FromInt(0)); set_weak_stack_trace_list(Smi::FromInt(0));
set_noscript_shared_function_infos(Smi::FromInt(0)); set_noscript_shared_function_infos(Smi::FromInt(0));
...@@ -2934,6 +2936,7 @@ bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) { ...@@ -2934,6 +2936,7 @@ bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
case kRetainedMapsRootIndex: case kRetainedMapsRootIndex:
case kNoScriptSharedFunctionInfosRootIndex: case kNoScriptSharedFunctionInfosRootIndex:
case kWeakStackTraceListRootIndex: case kWeakStackTraceListRootIndex:
case kSerializedTemplatesRootIndex:
// Smi values // Smi values
#define SMI_ENTRY(type, name, Name) case k##Name##RootIndex: #define SMI_ENTRY(type, name, Name) case k##Name##RootIndex:
SMI_ROOT_LIST(SMI_ENTRY) SMI_ROOT_LIST(SMI_ENTRY)
......
...@@ -197,7 +197,8 @@ using v8::MemoryPressureLevel; ...@@ -197,7 +197,8 @@ using v8::MemoryPressureLevel;
V(Map, bytecode_array_map, BytecodeArrayMap) \ V(Map, bytecode_array_map, BytecodeArrayMap) \
V(WeakCell, empty_weak_cell, EmptyWeakCell) \ V(WeakCell, empty_weak_cell, EmptyWeakCell) \
V(PropertyCell, has_instance_protector, HasInstanceProtector) \ V(PropertyCell, has_instance_protector, HasInstanceProtector) \
V(Cell, species_protector, SpeciesProtector) V(Cell, species_protector, SpeciesProtector) \
V(FixedArray, serialized_templates, SerializedTemplates)
// Entries in this list are limited to Smis and are not visited during GC. // Entries in this list are limited to Smis and are not visited during GC.
#define SMI_ROOT_LIST(V) \ #define SMI_ROOT_LIST(V) \
...@@ -807,6 +808,8 @@ class Heap { ...@@ -807,6 +808,8 @@ class Heap {
inline void SetInterpreterEntryReturnPCOffset(int pc_offset); inline void SetInterpreterEntryReturnPCOffset(int pc_offset);
inline int GetNextTemplateSerialNumber(); inline int GetNextTemplateSerialNumber();
inline void SetSerializedTemplates(FixedArray* templates);
// For post mortem debugging. // For post mortem debugging.
void RememberUnmappedPage(Address page, bool compacted); void RememberUnmappedPage(Address page, bool compacted);
......
...@@ -74,6 +74,8 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, ...@@ -74,6 +74,8 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
// All the internalized strings that the partial snapshot needs should be // All the internalized strings that the partial snapshot needs should be
// either in the root table or in the partial snapshot cache. // either in the root table or in the partial snapshot cache.
DCHECK(!obj->IsInternalizedString()); DCHECK(!obj->IsInternalizedString());
// Function and object templates are not context specific.
DCHECK(!obj->IsTemplateInfo());
if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return; if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return;
......
...@@ -2031,7 +2031,7 @@ TEST(SnapshotCreatorExternalReferences) { ...@@ -2031,7 +2031,7 @@ TEST(SnapshotCreatorExternalReferences) {
delete[] blob.data; delete[] blob.data;
} }
TEST(SnapshotCreatorGlobalTemplate) { TEST(SnapshotCreatorTemplates) {
DisableTurbofan(); DisableTurbofan();
v8::StartupData blob; v8::StartupData blob;
{ {
...@@ -2042,13 +2042,16 @@ TEST(SnapshotCreatorGlobalTemplate) { ...@@ -2042,13 +2042,16 @@ TEST(SnapshotCreatorGlobalTemplate) {
v8::ExtensionConfiguration* no_extension = nullptr; v8::ExtensionConfiguration* no_extension = nullptr;
v8::Local<v8::ObjectTemplate> global_template = v8::Local<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate); v8::ObjectTemplate::New(isolate);
global_template->Set( v8::Local<v8::FunctionTemplate> callback =
v8_str("f"), v8::FunctionTemplate::New(isolate, SerializedCallback)); v8::FunctionTemplate::New(isolate, SerializedCallback);
global_template->Set(v8_str("f"), callback);
v8::Local<v8::Context> context = v8::Local<v8::Context> context =
v8::Context::New(isolate, no_extension, global_template); v8::Context::New(isolate, no_extension, global_template);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
ExpectInt32("f()", 42); ExpectInt32("f()", 42);
CHECK_EQ(0, creator.AddContext(context)); CHECK_EQ(0, creator.AddContext(context));
CHECK_EQ(0, creator.AddTemplate(callback));
CHECK_EQ(1, creator.AddTemplate(global_template));
} }
blob = blob =
creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
...@@ -2073,6 +2076,28 @@ TEST(SnapshotCreatorGlobalTemplate) { ...@@ -2073,6 +2076,28 @@ TEST(SnapshotCreatorGlobalTemplate) {
v8::Context::New(isolate, no_extension, no_template, no_object, 0); v8::Context::New(isolate, no_extension, no_template, no_object, 0);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
ExpectInt32("f()", 42); ExpectInt32("f()", 42);
// Retrieve the snapshotted object template.
v8::Local<v8::ObjectTemplate> obj_template =
v8::ObjectTemplate::FromSnapshot(isolate, 1);
CHECK(!obj_template.IsEmpty());
v8::Local<v8::Object> object =
obj_template->NewInstance(context).ToLocalChecked();
CHECK(context->Global()->Set(context, v8_str("o"), object).FromJust());
ExpectInt32("o.f()", 42);
// Check that it instantiates to the same prototype.
ExpectTrue("o.f.prototype === f.prototype");
// Retrieve the snapshotted function template.
v8::Local<v8::FunctionTemplate> fun_template =
v8::FunctionTemplate::FromSnapshot(isolate, 0);
CHECK(!fun_template.IsEmpty());
v8::Local<v8::Function> fun =
fun_template->GetFunction(context).ToLocalChecked();
CHECK(context->Global()->Set(context, v8_str("g"), fun).FromJust());
ExpectInt32("g()", 42);
// Check that it instantiates to the same prototype.
ExpectTrue("g.prototype === f.prototype");
} }
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment