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 {
static void SetNativesDataBlob(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.
*
......
......@@ -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) {
i::FlagList::SetFlagsFromString(str, length);
}
......
......@@ -2156,7 +2156,7 @@ void Factory::SetNumberStringCache(Handle<Object> number,
// cache in the snapshot to keep boot-time memory usage down.
// If we expand the number string cache already while creating
// 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);
isolate()->heap()->set_number_string_cache(*new_cache);
return;
......
......@@ -712,12 +712,8 @@ DEFINE_STRING(testing_serialization_file, "/tmp/serdes",
#endif
// 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,
"Write V8 startup blob file. "
"(mksnapshot only)")
"Write V8 startup blob file. (mksnapshot only)")
// code-stubs-hydrogen.cc
DEFINE_BOOL(profile_hydrogen_code_stub_compilation, false,
......
......@@ -36,15 +36,11 @@ class SnapshotWriter {
startup_blob_file_ = GetFileDescriptorOrDie(startup_blob_file);
}
void WriteSnapshot(const i::SnapshotData& sd,
const i::SnapshotData& csd) const {
i::SnapshotByteSink sink;
sink.PutBlob(sd.RawData(), "startup");
sink.PutBlob(csd.RawData(), "context");
const i::Vector<const i::byte>& blob = sink.data().ToConstVector();
WriteSnapshotFile(blob);
MaybeWriteStartupBlob(blob);
void WriteSnapshot(v8::StartupData blob) const {
i::Vector<const i::byte> blob_vector(
reinterpret_cast<const i::byte*>(blob.data), blob.raw_size);
WriteSnapshotFile(blob_vector);
MaybeWriteStartupBlob(blob_vector);
}
private:
......@@ -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) {
// By default, log code create information in the snapshot.
i::FLAG_log_code = true;
......@@ -135,6 +119,8 @@ int main(int argc, char** argv) {
// at runtime.
i::FLAG_harmony_shipping = false;
i::FLAG_logfile_per_isolate = false;
// Print the usage if an error occurs when parsing the command line
// flags or if the help flag is set.
int result = i::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
......@@ -150,101 +136,15 @@ int main(int argc, char** argv) {
v8::V8::InitializePlatform(platform);
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]);
if (i::FLAG_startup_blob)
writer.SetStartupBlobFile(i::FLAG_startup_blob);
i::SnapshotData sd(snapshot_sink, ser);
i::SnapshotData csd(context_sink, context_ser);
writer.WriteSnapshot(sd, csd);
}
{
SnapshotWriter writer(argv[1]);
if (i::FLAG_startup_blob) writer.SetStartupBlobFile(i::FLAG_startup_blob);
StartupData blob = v8::V8::CreateSnapshotDataBlob();
CHECK(blob.data);
writer.WriteSnapshot(blob);
delete[] blob.data;
}
isolate->Dispose();
V8::Dispose();
V8::ShutdownPlatform();
delete platform;
......
......@@ -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) {
if (!HaveASnapshotToStartFrom()) return false;
base::ElapsedTimer timer;
if (FLAG_profile_deserialization) timer.Start();
SnapshotData snapshot_data(StartupSnapshot());
const v8::StartupData blob = SnapshotBlob();
SnapshotData snapshot_data(ExtractStartupData(&blob));
Deserializer deserializer(&snapshot_data);
bool success = isolate->Init(&deserializer);
if (FLAG_profile_deserialization) {
......@@ -63,7 +39,8 @@ bool Snapshot::Initialize(Isolate* isolate) {
Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
if (!HaveASnapshotToStartFrom()) return Handle<Context>();
SnapshotData snapshot_data(ContextSnapshot());
const v8::StartupData blob = SnapshotBlob();
SnapshotData snapshot_data(ExtractContextData(&blob));
Deserializer deserializer(&snapshot_data);
Object* root;
deserializer.DeserializePartial(isolate, &root);
......@@ -71,4 +48,44 @@ Handle<Context> Snapshot::NewContextFromSnapshot(Isolate* isolate) {
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
......@@ -26,11 +26,10 @@ void SetSnapshotFromFile(StartupData* snapshot_blob) {
DCHECK(snapshot_blob->data);
DCHECK(snapshot_blob->raw_size > 0);
DCHECK(!external_startup_blob.data);
external_startup_blob = *snapshot_blob;
// Validate snapshot blob.
DCHECK(!Snapshot::StartupSnapshot().is_empty());
DCHECK(!Snapshot::ContextSnapshot().is_empty());
DCHECK(!Snapshot::ExtractStartupData(snapshot_blob).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,
}
void SnapshotByteSink::PutBlob(Vector<const byte> blob,
const char* description) {
PutInt(blob.length(), description);
PutRaw(blob.start(), blob.length(), description);
}
bool SnapshotByteSource::AtEOF() {
if (0u + length_ - position_ > 2 * sizeof(uint32_t)) return false;
for (int x = position_; x < length_; x++) {
......
......@@ -91,7 +91,6 @@ class SnapshotByteSink {
void PutInt(uintptr_t integer, 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(); }
const List<byte>& data() const { return data_; }
......
......@@ -10,7 +10,7 @@
namespace v8 {
namespace internal {
class Snapshot {
class Snapshot : public AllStatic {
public:
// Initialize the Isolate from the internal snapshot. Returns false if no
// snapshot could be found.
......@@ -18,12 +18,18 @@ class Snapshot {
// Create a new context using the internal partial snapshot.
static Handle<Context> NewContextFromSnapshot(Isolate* isolate);
static const Vector<const byte> StartupSnapshot();
static const Vector<const byte> ContextSnapshot();
static bool HaveASnapshotToStartFrom();
// To be implemented by the snapshot source.
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:
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