[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}
This commit is contained in:
yangguo 2016-06-20 22:08:38 -07:00 committed by Commit bot
parent 6773ee2508
commit c5ae5bb16b
7 changed files with 111 additions and 5 deletions

View File

@ -4487,6 +4487,9 @@ class V8_EXPORT FunctionTemplate : public Template {
Local<Value> data = Local<Value>(),
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,
* the callback cannot be null.
@ -4662,6 +4665,9 @@ class V8_EXPORT ObjectTemplate : public Template {
Local<FunctionTemplate> constructor = Local<FunctionTemplate>());
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.*/
V8_DEPRECATE_SOON("Use maybe version", Local<Object> NewInstance());
V8_WARN_UNUSED_RESULT MaybeLocal<Object> NewInstance(Local<Context> context);
@ -6810,6 +6816,12 @@ class SnapshotCreator {
*/
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.
* This must not be called from within a handle scope.

View File

@ -386,7 +386,10 @@ bool RunExtraCode(Isolate* isolate, Local<Context> context,
struct SnapshotCreatorData {
explicit SnapshotCreatorData(Isolate* isolate)
: isolate_(isolate), contexts_(isolate), created_(false) {}
: isolate_(isolate),
contexts_(isolate),
templates_(isolate),
created_(false) {}
static SnapshotCreatorData* cast(void* data) {
return reinterpret_cast<SnapshotCreatorData*>(data);
@ -395,6 +398,7 @@ struct SnapshotCreatorData {
ArrayBufferAllocator allocator_;
Isolate* isolate_;
PersistentValueVector<Context> contexts_;
PersistentValueVector<Template> templates_;
bool created_;
};
@ -442,12 +446,35 @@ size_t SnapshotCreator::AddContext(Local<Context> context) {
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(
SnapshotCreator::FunctionCodeHandling function_code_handling) {
SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_);
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
// context even after we have disposed of the context.
isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
@ -1173,6 +1200,20 @@ Local<FunctionTemplate> FunctionTemplate::New(Isolate* isolate,
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(
Isolate* isolate, FunctionCallback callback,
@ -1384,6 +1425,21 @@ Local<ObjectTemplate> ObjectTemplate::New(
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
// constructor is available we create one.
static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(

View File

@ -732,6 +732,11 @@ int Heap::GetNextTemplateSerialNumber() {
return next_serial_number;
}
void Heap::SetSerializedTemplates(FixedArray* templates) {
DCHECK_EQ(empty_fixed_array(), serialized_templates());
set_serialized_templates(templates);
}
AlwaysAllocateScope::AlwaysAllocateScope(Isolate* isolate)
: heap_(isolate->heap()) {
heap_->always_allocate_scope_count_.Increment(1);

View File

@ -2897,6 +2897,8 @@ void Heap::CreateInitialObjects() {
handle(Smi::FromInt(Isolate::kArrayProtectorValid), isolate()));
set_species_protector(*species_cell);
set_serialized_templates(empty_fixed_array());
set_weak_stack_trace_list(Smi::FromInt(0));
set_noscript_shared_function_infos(Smi::FromInt(0));
@ -2934,6 +2936,7 @@ bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
case kRetainedMapsRootIndex:
case kNoScriptSharedFunctionInfosRootIndex:
case kWeakStackTraceListRootIndex:
case kSerializedTemplatesRootIndex:
// Smi values
#define SMI_ENTRY(type, name, Name) case k##Name##RootIndex:
SMI_ROOT_LIST(SMI_ENTRY)

View File

@ -197,7 +197,8 @@ using v8::MemoryPressureLevel;
V(Map, bytecode_array_map, BytecodeArrayMap) \
V(WeakCell, empty_weak_cell, EmptyWeakCell) \
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.
#define SMI_ROOT_LIST(V) \
@ -807,6 +808,8 @@ class Heap {
inline void SetInterpreterEntryReturnPCOffset(int pc_offset);
inline int GetNextTemplateSerialNumber();
inline void SetSerializedTemplates(FixedArray* templates);
// For post mortem debugging.
void RememberUnmappedPage(Address page, bool compacted);

View File

@ -74,6 +74,8 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
// All the internalized strings that the partial snapshot needs should be
// either in the root table or in the partial snapshot cache.
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;

View File

@ -2031,7 +2031,7 @@ TEST(SnapshotCreatorExternalReferences) {
delete[] blob.data;
}
TEST(SnapshotCreatorGlobalTemplate) {
TEST(SnapshotCreatorTemplates) {
DisableTurbofan();
v8::StartupData blob;
{
@ -2042,13 +2042,16 @@ TEST(SnapshotCreatorGlobalTemplate) {
v8::ExtensionConfiguration* no_extension = nullptr;
v8::Local<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(isolate);
global_template->Set(
v8_str("f"), v8::FunctionTemplate::New(isolate, SerializedCallback));
v8::Local<v8::FunctionTemplate> callback =
v8::FunctionTemplate::New(isolate, SerializedCallback);
global_template->Set(v8_str("f"), callback);
v8::Local<v8::Context> context =
v8::Context::New(isolate, no_extension, global_template);
v8::Context::Scope context_scope(context);
ExpectInt32("f()", 42);
CHECK_EQ(0, creator.AddContext(context));
CHECK_EQ(0, creator.AddTemplate(callback));
CHECK_EQ(1, creator.AddTemplate(global_template));
}
blob =
creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
@ -2073,6 +2076,28 @@ TEST(SnapshotCreatorGlobalTemplate) {
v8::Context::New(isolate, no_extension, no_template, no_object, 0);
v8::Context::Scope context_scope(context);
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");
}
{