From b62f094884b95cf7b45484a27a9721a8477efc91 Mon Sep 17 00:00:00 2001 From: yangguo Date: Wed, 14 Jan 2015 03:06:38 -0800 Subject: [PATCH] Store embed-script flag as metadata into snapshot blob. R=vogelheim@chromium.org Review URL: https://codereview.chromium.org/848023002 Cr-Commit-Position: refs/heads/master@{#26049} --- src/api.cc | 5 ++++- src/bootstrapper.cc | 5 +++++ src/heap/spaces.cc | 3 +++ src/snapshot-common.cc | 43 +++++++++++++++++++++++++++++++++++-------- src/snapshot-external.cc | 4 +--- src/snapshot.h | 34 ++++++++++++++++++++++++++++++++-- 6 files changed, 80 insertions(+), 14 deletions(-) diff --git a/src/api.cc b/src/api.cc index 1903e47..03d79a5 100644 --- a/src/api.cc +++ b/src/api.cc @@ -229,11 +229,13 @@ StartupData V8::CreateSnapshotDataBlob(char* custom_source) { Isolate::Scope isolate_scope(isolate); i::Isolate* internal_isolate = reinterpret_cast(isolate); Persistent context; + i::Snapshot::Metadata metadata; { HandleScope handle_scope(isolate); Handle new_context = Context::New(isolate); context.Reset(isolate, new_context); if (custom_source != NULL) { + metadata.set_embeds_script(true); Context::Scope context_scope(new_context); if (!RunExtraCode(isolate, custom_source)) context.Reset(); } @@ -264,7 +266,8 @@ StartupData V8::CreateSnapshotDataBlob(char* custom_source) { i::SnapshotData sd(snapshot_sink, ser); i::SnapshotData csd(context_sink, context_ser); - result = i::Snapshot::CreateSnapshotBlob(sd.RawData(), csd.RawData()); + result = i::Snapshot::CreateSnapshotBlob(sd.RawData(), csd.RawData(), + metadata); } } isolate->Dispose(); diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index 308f754..0ece57c 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -2578,6 +2578,11 @@ bool Genesis::ConfigureApiObject(Handle object, void Genesis::TransferNamedProperties(Handle from, Handle to) { + // If JSObject::AddProperty asserts due to already existing property, + // it is likely due to both global objects sharing property name(s). + // Merging those two global objects is impossible. + // The global template must not create properties that already exist + // in the snapshotted global object. if (from->HasFastProperties()) { Handle descs = Handle(from->map()->instance_descriptors()); diff --git a/src/heap/spaces.cc b/src/heap/spaces.cc index 3802e47..1a2ff27 100644 --- a/src/heap/spaces.cc +++ b/src/heap/spaces.cc @@ -10,6 +10,7 @@ #include "src/heap/mark-compact.h" #include "src/macro-assembler.h" #include "src/msan.h" +#include "src/snapshot.h" namespace v8 { namespace internal { @@ -1044,6 +1045,8 @@ bool PagedSpace::Expand() { intptr_t PagedSpace::SizeOfFirstPage() { + // If the snapshot contains a custom script, all size guarantees are off. + if (Snapshot::EmbedsScript()) return AreaSize(); // If using an ool constant pool then transfer the constant pool allowance // from the code space to the old pointer space. static const int constant_pool_delta = FLAG_enable_ool_constant_pool ? 48 : 0; diff --git a/src/snapshot-common.cc b/src/snapshot-common.cc index 09cf722..c2ce60d 100644 --- a/src/snapshot-common.cc +++ b/src/snapshot-common.cc @@ -19,6 +19,21 @@ bool Snapshot::HaveASnapshotToStartFrom() { } +#ifdef DEBUG +bool Snapshot::SnapshotIsValid(v8::StartupData* snapshot_blob) { + return !Snapshot::ExtractStartupData(snapshot_blob).is_empty() && + !Snapshot::ExtractContextData(snapshot_blob).is_empty(); +} +#endif // DEBUG + + +bool Snapshot::EmbedsScript() { + if (!HaveASnapshotToStartFrom()) return false; + const v8::StartupData blob = SnapshotBlob(); + return ExtractMetadata(&blob).embeds_script(); +} + + bool Snapshot::Initialize(Isolate* isolate) { if (!HaveASnapshotToStartFrom()) return false; base::ElapsedTimer timer; @@ -54,6 +69,9 @@ MaybeHandle Snapshot::NewContextFromSnapshot( Handle result; if (!maybe_context.ToHandle(&result)) return MaybeHandle(); CHECK(result->IsContext()); + // If the snapshot does not contain a custom script, we need to update + // the global object for exactly one context. + CHECK(EmbedsScript() || (*outdated_contexts_out)->length() == 1); if (FLAG_profile_deserialization) { double ms = timer.Elapsed().InMillisecondsF(); int bytes = context_data.length(); @@ -65,28 +83,37 @@ MaybeHandle Snapshot::NewContextFromSnapshot( v8::StartupData Snapshot::CreateSnapshotBlob( const Vector startup_data, - const Vector context_data) { + const Vector context_data, Snapshot::Metadata metadata) { int startup_length = startup_data.length(); int context_length = context_data.length(); - int context_offset = kIntSize + startup_length; + int context_offset = ContextOffset(startup_length); + int length = context_offset + context_length; char* data = new char[length]; - memcpy(data, &startup_length, kIntSize); - memcpy(data + kIntSize, startup_data.begin(), startup_length); + memcpy(data + kMetadataOffset, &metadata.RawValue(), kInt32Size); + memcpy(data + kStartupLengthOffset, &startup_length, kInt32Size); + memcpy(data + kStartupDataOffset, startup_data.begin(), startup_length); memcpy(data + context_offset, context_data.begin(), context_length); v8::StartupData result = {data, length}; return result; } +Snapshot::Metadata Snapshot::ExtractMetadata(const v8::StartupData* data) { + uint32_t raw; + memcpy(&raw, data->data + kMetadataOffset, kInt32Size); + return Metadata(raw); +} + + Vector Snapshot::ExtractStartupData(const v8::StartupData* data) { DCHECK_LT(kIntSize, data->raw_size); int startup_length; - memcpy(&startup_length, data->data, kIntSize); + memcpy(&startup_length, data->data + kStartupLengthOffset, kInt32Size); DCHECK_LT(startup_length, data->raw_size); const byte* startup_data = - reinterpret_cast(data->data + kIntSize); + reinterpret_cast(data->data + kStartupDataOffset); return Vector(startup_data, startup_length); } @@ -94,8 +121,8 @@ Vector Snapshot::ExtractStartupData(const v8::StartupData* data) { Vector Snapshot::ExtractContextData(const v8::StartupData* data) { DCHECK_LT(kIntSize, data->raw_size); int startup_length; - memcpy(&startup_length, data->data, kIntSize); - int context_offset = kIntSize + startup_length; + memcpy(&startup_length, data->data + kStartupLengthOffset, kIntSize); + int context_offset = ContextOffset(startup_length); const byte* context_data = reinterpret_cast(data->data + context_offset); DCHECK_LT(context_offset, data->raw_size); diff --git a/src/snapshot-external.cc b/src/snapshot-external.cc index 2fda571..f26a5a1 100644 --- a/src/snapshot-external.cc +++ b/src/snapshot-external.cc @@ -26,9 +26,7 @@ void SetSnapshotFromFile(StartupData* snapshot_blob) { DCHECK(snapshot_blob->data); DCHECK(snapshot_blob->raw_size > 0); DCHECK(!external_startup_blob.data); - // Validate snapshot blob. - DCHECK(!Snapshot::ExtractStartupData(snapshot_blob).is_empty()); - DCHECK(!Snapshot::ExtractContextData(snapshot_blob).is_empty()); + DCHECK(Snapshot::SnapshotIsValid(snapshot_blob)); external_startup_blob = *snapshot_blob; } diff --git a/src/snapshot.h b/src/snapshot.h index 04c7ba6..62e0b9b 100644 --- a/src/snapshot.h +++ b/src/snapshot.h @@ -12,6 +12,21 @@ namespace internal { class Snapshot : public AllStatic { public: + class Metadata { + public: + explicit Metadata(uint32_t data = 0) : data_(data) {} + bool embeds_script() { return EmbedsScriptBits::decode(data_); } + void set_embeds_script(bool v) { + data_ = EmbedsScriptBits::update(data_, v); + } + + uint32_t& RawValue() { return data_; } + + private: + class EmbedsScriptBits : public BitField {}; + uint32_t data_; + }; + // Initialize the Isolate from the internal snapshot. Returns false if no // snapshot could be found. static bool Initialize(Isolate* isolate); @@ -21,17 +36,32 @@ class Snapshot : public AllStatic { static bool HaveASnapshotToStartFrom(); + static bool EmbedsScript(); + // To be implemented by the snapshot source. static const v8::StartupData SnapshotBlob(); static v8::StartupData CreateSnapshotBlob( const Vector startup_data, - const Vector context_data); + const Vector context_data, Metadata metadata); + +#ifdef DEBUG + static bool SnapshotIsValid(v8::StartupData* snapshot_blob); +#endif // DEBUG + private: static Vector ExtractStartupData(const v8::StartupData* data); static Vector ExtractContextData(const v8::StartupData* data); + static Metadata ExtractMetadata(const v8::StartupData* data); + + static const int kMetadataOffset = 0; + static const int kStartupLengthOffset = kMetadataOffset + kInt32Size; + static const int kStartupDataOffset = kStartupLengthOffset + kInt32Size; + + static int ContextOffset(int startup_length) { + return kStartupDataOffset + startup_length; + } - private: DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot); }; -- 2.7.4