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

Extract non-IO part of mksnapshot into an API method.

R=vogelheim@chromium.org

Review URL: https://codereview.chromium.org/789213002

Cr-Commit-Position: refs/heads/master@{#25747}
parent 30f2578c
...@@ -5360,6 +5360,13 @@ class V8_EXPORT V8 { ...@@ -5360,6 +5360,13 @@ class V8_EXPORT V8 {
static void SetNativesDataBlob(StartupData* startup_blob); static void SetNativesDataBlob(StartupData* startup_blob);
static void SetSnapshotDataBlob(StartupData* startup_blob); static void SetSnapshotDataBlob(StartupData* startup_blob);
/**
* Create a new isolate and context for the purpose of capturing a snapshot
* Returns { NULL, 0 } on failure.
* The caller owns the data array in the return value.
*/
static StartupData CreateSnapshotDataBlob();
/** /**
* Adds a message listener. * Adds a message listener.
* *
......
...@@ -206,6 +206,53 @@ void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) { ...@@ -206,6 +206,53 @@ void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
} }
StartupData V8::CreateSnapshotDataBlob() {
Isolate::CreateParams params;
params.enable_serializer = true;
Isolate* isolate = v8::Isolate::New(params);
StartupData result = {NULL, 0};
{
Isolate::Scope isolate_scope(isolate);
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
Persistent<Context> context;
{
HandleScope handle_scope(isolate);
context.Reset(isolate, Context::New(isolate));
}
if (!context.IsEmpty()) {
// Make sure all builtin scripts are cached.
{
HandleScope scope(isolate);
for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
internal_isolate->bootstrapper()->NativesSourceLookup(i);
}
}
// 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.
internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
i::Object* raw_context = *v8::Utils::OpenPersistent(context);
context.Reset();
i::SnapshotByteSink snapshot_sink;
i::StartupSerializer ser(internal_isolate, &snapshot_sink);
ser.SerializeStrongReferences();
i::SnapshotByteSink context_sink;
i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
context_ser.Serialize(&raw_context);
ser.SerializeWeakReferences();
i::SnapshotData sd(snapshot_sink, ser);
i::SnapshotData csd(context_sink, context_ser);
result = i::Snapshot::CreateSnapshotBlob(sd.RawData(), csd.RawData());
}
}
isolate->Dispose();
return result;
}
void V8::SetFlagsFromString(const char* str, int length) { void V8::SetFlagsFromString(const char* str, int length) {
i::FlagList::SetFlagsFromString(str, length); i::FlagList::SetFlagsFromString(str, length);
} }
......
...@@ -2156,7 +2156,7 @@ void Factory::SetNumberStringCache(Handle<Object> number, ...@@ -2156,7 +2156,7 @@ void Factory::SetNumberStringCache(Handle<Object> number,
// cache in the snapshot to keep boot-time memory usage down. // cache in the snapshot to keep boot-time memory usage down.
// If we expand the number string cache already while creating // If we expand the number string cache already while creating
// the snapshot then that didn't work out. // the snapshot then that didn't work out.
DCHECK(!isolate()->serializer_enabled() || FLAG_extra_code != NULL); DCHECK(!isolate()->serializer_enabled());
Handle<FixedArray> new_cache = NewFixedArray(full_size, TENURED); Handle<FixedArray> new_cache = NewFixedArray(full_size, TENURED);
isolate()->heap()->set_number_string_cache(*new_cache); isolate()->heap()->set_number_string_cache(*new_cache);
return; return;
......
...@@ -712,12 +712,8 @@ DEFINE_STRING(testing_serialization_file, "/tmp/serdes", ...@@ -712,12 +712,8 @@ DEFINE_STRING(testing_serialization_file, "/tmp/serdes",
#endif #endif
// mksnapshot.cc // mksnapshot.cc
DEFINE_STRING(extra_code, NULL,
"A filename with extra code to be included in"
" the snapshot (mksnapshot only)")
DEFINE_STRING(startup_blob, NULL, DEFINE_STRING(startup_blob, NULL,
"Write V8 startup blob file. " "Write V8 startup blob file. (mksnapshot only)")
"(mksnapshot only)")
// code-stubs-hydrogen.cc // code-stubs-hydrogen.cc
DEFINE_BOOL(profile_hydrogen_code_stub_compilation, false, DEFINE_BOOL(profile_hydrogen_code_stub_compilation, false,
......
...@@ -36,15 +36,11 @@ class SnapshotWriter { ...@@ -36,15 +36,11 @@ class SnapshotWriter {
startup_blob_file_ = GetFileDescriptorOrDie(startup_blob_file); startup_blob_file_ = GetFileDescriptorOrDie(startup_blob_file);
} }
void WriteSnapshot(const i::SnapshotData& sd, void WriteSnapshot(v8::StartupData blob) const {
const i::SnapshotData& csd) const { i::Vector<const i::byte> blob_vector(
i::SnapshotByteSink sink; reinterpret_cast<const i::byte*>(blob.data), blob.raw_size);
sink.PutBlob(sd.RawData(), "startup"); WriteSnapshotFile(blob_vector);
sink.PutBlob(csd.RawData(), "context"); MaybeWriteStartupBlob(blob_vector);
const i::Vector<const i::byte>& blob = sink.data().ToConstVector();
WriteSnapshotFile(blob);
MaybeWriteStartupBlob(blob);
} }
private: private:
...@@ -115,18 +111,6 @@ class SnapshotWriter { ...@@ -115,18 +111,6 @@ class SnapshotWriter {
}; };
void DumpException(Handle<Message> message) {
String::Utf8Value message_string(message->Get());
String::Utf8Value message_line(message->GetSourceLine());
fprintf(stderr, "%s at line %d\n", *message_string, message->GetLineNumber());
fprintf(stderr, "%s\n", *message_line);
for (int i = 0; i <= message->GetEndColumn(); ++i) {
fprintf(stderr, "%c", i < message->GetStartColumn() ? ' ' : '^');
}
fprintf(stderr, "\n");
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
// By default, log code create information in the snapshot. // By default, log code create information in the snapshot.
i::FLAG_log_code = true; i::FLAG_log_code = true;
...@@ -135,6 +119,8 @@ int main(int argc, char** argv) { ...@@ -135,6 +119,8 @@ int main(int argc, char** argv) {
// at runtime. // at runtime.
i::FLAG_harmony_shipping = false; i::FLAG_harmony_shipping = false;
i::FLAG_logfile_per_isolate = false;
// Print the usage if an error occurs when parsing the command line // Print the usage if an error occurs when parsing the command line
// flags or if the help flag is set. // flags or if the help flag is set.
int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true); int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
...@@ -150,101 +136,15 @@ int main(int argc, char** argv) { ...@@ -150,101 +136,15 @@ int main(int argc, char** argv) {
v8::V8::InitializePlatform(platform); v8::V8::InitializePlatform(platform);
v8::V8::Initialize(); v8::V8::Initialize();
i::FLAG_logfile_per_isolate = false;
Isolate::CreateParams params;
params.enable_serializer = true;
Isolate* isolate = v8::Isolate::New(params);
{ Isolate::Scope isolate_scope(isolate);
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
Persistent<Context> context;
{
HandleScope handle_scope(isolate);
context.Reset(isolate, Context::New(isolate));
}
if (context.IsEmpty()) {
fprintf(stderr,
"\nException thrown while compiling natives - see above.\n\n");
exit(1);
}
if (i::FLAG_extra_code != NULL) {
// Capture 100 frames if anything happens.
V8::SetCaptureStackTraceForUncaughtExceptions(true, 100);
HandleScope scope(isolate);
v8::Context::Scope cscope(v8::Local<v8::Context>::New(isolate, context));
const char* name = i::FLAG_extra_code;
FILE* file = base::OS::FOpen(name, "rb");
if (file == NULL) {
fprintf(stderr, "Failed to open '%s': errno %d\n", name, errno);
exit(1);
}
fseek(file, 0, SEEK_END);
int size = ftell(file);
rewind(file);
char* chars = new char[size + 1];
chars[size] = '\0';
for (int i = 0; i < size;) {
int read = static_cast<int>(fread(&chars[i], 1, size - i, file));
if (read < 0) {
fprintf(stderr, "Failed to read '%s': errno %d\n", name, errno);
exit(1);
}
i += read;
}
fclose(file);
Local<String> source = String::NewFromUtf8(isolate, chars);
TryCatch try_catch;
Local<Script> script = Script::Compile(source);
if (try_catch.HasCaught()) {
fprintf(stderr, "Failure compiling '%s'\n", name);
DumpException(try_catch.Message());
exit(1);
}
script->Run();
if (try_catch.HasCaught()) {
fprintf(stderr, "Failure running '%s'\n", name);
DumpException(try_catch.Message());
exit(1);
}
}
// Make sure all builtin scripts are cached.
{ HandleScope scope(isolate);
for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
internal_isolate->bootstrapper()->NativesSourceLookup(i);
}
}
// 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.
internal_isolate->heap()->CollectAllAvailableGarbage("mksnapshot");
i::Object* raw_context = *v8::Utils::OpenPersistent(context);
context.Reset();
// This results in a somewhat smaller snapshot, probably because it gets
// rid of some things that are cached between garbage collections.
i::SnapshotByteSink snapshot_sink;
i::StartupSerializer ser(internal_isolate, &snapshot_sink);
ser.SerializeStrongReferences();
i::SnapshotByteSink context_sink;
i::PartialSerializer context_ser(internal_isolate, &ser, &context_sink);
context_ser.Serialize(&raw_context);
ser.SerializeWeakReferences();
{ {
SnapshotWriter writer(argv[1]); SnapshotWriter writer(argv[1]);
if (i::FLAG_startup_blob) if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob);
writer.SetStartupBlobFile(i::FLAG_startup_blob); StartupData blob = v8::V8::CreateSnapshotDataBlob();
i::SnapshotData sd(snapshot_sink, ser); CHECK(blob.data);
i::SnapshotData csd(context_sink, context_ser); writer.WriteSnapshot(blob);
writer.WriteSnapshot(sd, csd); delete[] blob.data;
}
} }
isolate->Dispose();
V8::Dispose(); V8::Dispose();
V8::ShutdownPlatform(); V8::ShutdownPlatform();
delete platform; delete platform;
......
...@@ -19,37 +19,13 @@ bool Snapshot::HaveASnapshotToStartFrom() { ...@@ -19,37 +19,13 @@ bool Snapshot::HaveASnapshotToStartFrom() {
} }
const Vector<const byte> Snapshot::StartupSnapshot() {
DCHECK(HaveASnapshotToStartFrom());
const v8::StartupData blob = SnapshotBlob();
SnapshotByteSource source(blob.data, blob.raw_size);
const byte* data;
int length;
bool success = source.GetBlob(&data, &length);
CHECK(success);
return Vector<const byte>(data, length);
}
const Vector<const byte> Snapshot::ContextSnapshot() {
DCHECK(HaveASnapshotToStartFrom());
const v8::StartupData blob = SnapshotBlob();
SnapshotByteSource source(blob.data, blob.raw_size);
const byte* data;
int length;
bool success = source.GetBlob(&data, &length);
success &= source.GetBlob(&data, &length);
CHECK(success);
return Vector<const byte>(data, length);
}
bool Snapshot::Initialize(Isolate* isolate) { bool Snapshot::Initialize(Isolate* isolate) {
if (!HaveASnapshotToStartFrom()) return false; if (!HaveASnapshotToStartFrom()) return false;
base::ElapsedTimer timer; base::ElapsedTimer timer;
if (FLAG_profile_deserialization) timer.Start(); if (FLAG_profile_deserialization) timer.Start();
SnapshotData snapshot_data(StartupSnapshot()); const v8::StartupData blob = SnapshotBlob();
SnapshotData snapshot_data(ExtractStartupData(&blob));
Deserializer deserializer(&snapshot_data); Deserializer deserializer(&snapshot_data);
bool success = isolate->Init(&deserializer); bool success = isolate->Init(&deserializer);
if (FLAG_profile_deserialization) { if (FLAG_profile_deserialization) {
...@@ -63,7 +39,8 @@ bool Snapshot::Initialize(Isolate* isolate) { ...@@ -63,7 +39,8 @@ bool Snapshot::Initialize(Isolate* isolate) {
Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) { Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
if (!HaveASnapshotToStartFrom()) return Handle<Context>(); if (!HaveASnapshotToStartFrom()) return Handle<Context>();
SnapshotData snapshot_data(ContextSnapshot()); const v8::StartupData blob = SnapshotBlob();
SnapshotData snapshot_data(ExtractContextData(&blob));
Deserializer deserializer(&snapshot_data); Deserializer deserializer(&snapshot_data);
Object* root; Object* root;
deserializer.DeserializePartial(isolate, &root); deserializer.DeserializePartial(isolate, &root);
...@@ -71,4 +48,44 @@ Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) { ...@@ -71,4 +48,44 @@ Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
return Handle<Context>(Context::cast(root)); return Handle<Context>(Context::cast(root));
} }
v8::StartupData Snapshot::CreateSnapshotBlob(
const Vector<const byte> startup_data,
const Vector<const byte> context_data) {
int startup_length = startup_data.length();
int context_length = context_data.length();
int context_offset = kIntSize + 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 + context_offset, context_data.begin(), context_length);
v8::StartupData result = {data, length};
return result;
}
Vector<const byte> Snapshot::ExtractStartupData(const v8::StartupData* data) {
DCHECK_LT(kIntSize, data->raw_size);
int startup_length;
memcpy(&startup_length, data->data, kIntSize);
DCHECK_LT(startup_length, data->raw_size);
const byte* startup_data =
reinterpret_cast<const byte*>(data->data + kIntSize);
return Vector<const byte>(startup_data, startup_length);
}
Vector<const byte> 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;
const byte* context_data =
reinterpret_cast<const byte*>(data->data + context_offset);
DCHECK_LT(context_offset, data->raw_size);
int context_length = data->raw_size - context_offset;
return Vector<const byte>(context_data, context_length);
}
} } // namespace v8::internal } } // namespace v8::internal
...@@ -26,11 +26,10 @@ void SetSnapshotFromFile(StartupData* snapshot_blob) { ...@@ -26,11 +26,10 @@ void SetSnapshotFromFile(StartupData* snapshot_blob) {
DCHECK(snapshot_blob->data); DCHECK(snapshot_blob->data);
DCHECK(snapshot_blob->raw_size > 0); DCHECK(snapshot_blob->raw_size > 0);
DCHECK(!external_startup_blob.data); DCHECK(!external_startup_blob.data);
external_startup_blob = *snapshot_blob;
// Validate snapshot blob. // Validate snapshot blob.
DCHECK(!Snapshot::StartupSnapshot().is_empty()); DCHECK(!Snapshot::ExtractStartupData(snapshot_blob).is_empty());
DCHECK(!Snapshot::ContextSnapshot().is_empty()); DCHECK(!Snapshot::ExtractContextData(snapshot_blob).is_empty());
external_startup_blob = *snapshot_blob;
} }
......
...@@ -50,13 +50,6 @@ void SnapshotByteSink::PutRaw(const byte* data, int number_of_bytes, ...@@ -50,13 +50,6 @@ void SnapshotByteSink::PutRaw(const byte* data, int number_of_bytes,
} }
void SnapshotByteSink::PutBlob(Vector<const byte> blob,
const char* description) {
PutInt(blob.length(), description);
PutRaw(blob.start(), blob.length(), description);
}
bool SnapshotByteSource::AtEOF() { bool SnapshotByteSource::AtEOF() {
if (0u + length_ - position_ > 2 * sizeof(uint32_t)) return false; if (0u + length_ - position_ > 2 * sizeof(uint32_t)) return false;
for (int x = position_; x < length_; x++) { for (int x = position_; x < length_; x++) {
......
...@@ -91,7 +91,6 @@ class SnapshotByteSink { ...@@ -91,7 +91,6 @@ class SnapshotByteSink {
void PutInt(uintptr_t integer, const char* description); void PutInt(uintptr_t integer, const char* description);
void PutRaw(const byte* data, int number_of_bytes, const char* description); void PutRaw(const byte* data, int number_of_bytes, const char* description);
void PutBlob(Vector<const byte> blob, const char* description);
int Position() { return data_.length(); } int Position() { return data_.length(); }
const List<byte>& data() const { return data_; } const List<byte>& data() const { return data_; }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class Snapshot { class Snapshot : public AllStatic {
public: public:
// Initialize the Isolate from the internal snapshot. Returns false if no // Initialize the Isolate from the internal snapshot. Returns false if no
// snapshot could be found. // snapshot could be found.
...@@ -18,12 +18,18 @@ class Snapshot { ...@@ -18,12 +18,18 @@ class Snapshot {
// Create a new context using the internal partial snapshot. // Create a new context using the internal partial snapshot.
static Handle<Context> NewContextFromSnapshot(Isolate* isolate); static Handle<Context> NewContextFromSnapshot(Isolate* isolate);
static const Vector<const byte> StartupSnapshot();
static const Vector<const byte> ContextSnapshot();
static bool HaveASnapshotToStartFrom(); static bool HaveASnapshotToStartFrom();
// To be implemented by the snapshot source.
static const v8::StartupData SnapshotBlob(); static const v8::StartupData SnapshotBlob();
static v8::StartupData CreateSnapshotBlob(
const Vector<const byte> startup_data,
const Vector<const byte> context_data);
static Vector<const byte> ExtractStartupData(const v8::StartupData* data);
static Vector<const byte> ExtractContextData(const v8::StartupData* data);
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot); DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot);
}; };
......
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