* Remove old snapshot implementation
Review URL: http://codereview.chromium.org/394007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3307 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
5f3bdbe5a6
commit
64941f1cf9
@ -2636,11 +2636,7 @@ bool v8::V8::Initialize() {
|
||||
if (i::V8::IsRunning()) return true;
|
||||
ENTER_V8;
|
||||
HandleScope scope;
|
||||
if (i::FLAG_new_snapshot) {
|
||||
if (i::Snapshot::Initialize2()) return true;
|
||||
} else {
|
||||
if (i::Snapshot::Initialize()) return true;
|
||||
}
|
||||
if (i::Snapshot::Initialize()) return true;
|
||||
return i::V8::Initialize(NULL);
|
||||
}
|
||||
|
||||
|
@ -471,12 +471,16 @@ class ExternalReference BASE_EMBEDDED {
|
||||
|
||||
static void* Redirect(void* address, bool fp_return = false) {
|
||||
if (redirector_ == NULL) return address;
|
||||
return (*redirector_)(address, fp_return);
|
||||
void* answer = (*redirector_)(address, fp_return);
|
||||
return answer;
|
||||
}
|
||||
|
||||
static void* Redirect(Address address_arg, bool fp_return = false) {
|
||||
void* address = reinterpret_cast<void*>(address_arg);
|
||||
return redirector_ == NULL ? address : (*redirector_)(address, fp_return);
|
||||
void* answer = (redirector_ == NULL) ?
|
||||
address :
|
||||
(*redirector_)(address, fp_return);
|
||||
return answer;
|
||||
}
|
||||
|
||||
void* address_;
|
||||
|
@ -36,6 +36,8 @@ static int fatal_error_handler_nesting_depth = 0;
|
||||
|
||||
// Contains protection against recursive calls (faults while handling faults).
|
||||
extern "C" void V8_Fatal(const char* file, int line, const char* format, ...) {
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
fatal_error_handler_nesting_depth++;
|
||||
// First time we try to print an error message
|
||||
if (fatal_error_handler_nesting_depth < 2) {
|
||||
|
@ -252,7 +252,6 @@ class Variable;
|
||||
class VariableProxy;
|
||||
class RelocInfo;
|
||||
class Deserializer;
|
||||
class GenericDeserializer; // TODO(erikcorry): Get rid of this.
|
||||
class MessageLocation;
|
||||
class ObjectGroup;
|
||||
class TickSample;
|
||||
|
@ -87,27 +87,12 @@ class CounterCollection {
|
||||
// We statically allocate a set of local counters to be used if we
|
||||
// don't want to store the stats in a memory-mapped file
|
||||
static CounterCollection local_counters;
|
||||
static CounterCollection* counters = &local_counters;
|
||||
|
||||
|
||||
typedef std::map<std::string, int*> CounterMap;
|
||||
typedef std::map<std::string, int*>::iterator CounterMapIterator;
|
||||
static CounterMap counter_table_;
|
||||
|
||||
// Callback receiver when v8 has a counter to track.
|
||||
static int* counter_callback(const char* name) {
|
||||
std::string counter = name;
|
||||
// See if this counter name is already known.
|
||||
if (counter_table_.find(counter) != counter_table_.end())
|
||||
return counter_table_[counter];
|
||||
|
||||
Counter* ctr = counters->GetNextCounter();
|
||||
if (ctr == NULL) return NULL;
|
||||
int* ptr = ctr->Bind(name);
|
||||
counter_table_[counter] = ptr;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
class CppByteSink : public i::SnapshotByteSink {
|
||||
public:
|
||||
@ -151,57 +136,6 @@ class CppByteSink : public i::SnapshotByteSink {
|
||||
};
|
||||
|
||||
|
||||
// Write C++ code that defines Snapshot::snapshot_ to contain the snapshot
|
||||
// to the file given by filename. Only the first size chars are written.
|
||||
static int WriteInternalSnapshotToFile(const char* filename,
|
||||
const v8::internal::byte* bytes,
|
||||
int size) {
|
||||
FILE* f = i::OS::FOpen(filename, "wb");
|
||||
if (f == NULL) {
|
||||
i::OS::PrintError("Cannot open file %s for writing.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
fprintf(f, "// Autogenerated snapshot file. Do not edit.\n\n");
|
||||
fprintf(f, "#include \"v8.h\"\n");
|
||||
fprintf(f, "#include \"platform.h\"\n\n");
|
||||
fprintf(f, "#include \"snapshot.h\"\n\n");
|
||||
fprintf(f, "namespace v8 {\nnamespace internal {\n\n");
|
||||
fprintf(f, "const byte Snapshot::data_[] = {");
|
||||
int written = 0;
|
||||
written += fprintf(f, "0x%x", bytes[0]);
|
||||
for (int i = 1; i < size; ++i) {
|
||||
written += fprintf(f, ",0x%x", bytes[i]);
|
||||
// The following is needed to keep the line length low on Visual C++:
|
||||
if (i % 512 == 0) fprintf(f, "\n");
|
||||
}
|
||||
fprintf(f, "};\n\n");
|
||||
fprintf(f, "int Snapshot::size_ = %d;\n\n", size);
|
||||
fprintf(f, "} } // namespace v8::internal\n");
|
||||
fclose(f);
|
||||
return written;
|
||||
}
|
||||
|
||||
|
||||
int main2(int argc, char** argv) {
|
||||
i::Serializer::Enable();
|
||||
Persistent<Context> context = v8::Context::New();
|
||||
// Make sure all builtin scripts are cached.
|
||||
{ HandleScope scope;
|
||||
for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
|
||||
i::Bootstrapper::NativesSourceLookup(i);
|
||||
}
|
||||
}
|
||||
context.Dispose();
|
||||
CppByteSink sink(argv[1]);
|
||||
i::Serializer2 ser(&sink);
|
||||
// This results in a somewhat smaller snapshot, probably because it gets rid
|
||||
// of some things that are cached between garbage collections.
|
||||
i::Heap::CollectAllGarbage(true);
|
||||
ser.Serialize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||
// By default, log code create information in the snapshot.
|
||||
@ -215,38 +149,20 @@ int main(int argc, char** argv) {
|
||||
i::FlagList::PrintHelp();
|
||||
return !i::FLAG_help;
|
||||
}
|
||||
|
||||
if (i::FLAG_new_snapshot) {
|
||||
return main2(argc, argv);
|
||||
}
|
||||
|
||||
v8::V8::SetCounterFunction(counter_callback);
|
||||
v8::HandleScope scope;
|
||||
|
||||
const int kExtensionCount = 1;
|
||||
const char* extension_list[kExtensionCount] = { "v8/gc" };
|
||||
v8::ExtensionConfiguration extensions(kExtensionCount, extension_list);
|
||||
|
||||
i::Serializer::Enable();
|
||||
v8::Context::New(&extensions);
|
||||
|
||||
Persistent<Context> context = v8::Context::New();
|
||||
// Make sure all builtin scripts are cached.
|
||||
{ HandleScope scope;
|
||||
for (int i = 0; i < i::Natives::GetBuiltinsCount(); i++) {
|
||||
i::Bootstrapper::NativesSourceLookup(i);
|
||||
}
|
||||
}
|
||||
// Get rid of unreferenced scripts with a global GC.
|
||||
i::Heap::CollectAllGarbage(false);
|
||||
i::Serializer ser;
|
||||
context.Dispose();
|
||||
CppByteSink sink(argv[1]);
|
||||
i::Serializer ser(&sink);
|
||||
// This results in a somewhat smaller snapshot, probably because it gets rid
|
||||
// of some things that are cached between garbage collections.
|
||||
i::Heap::CollectAllGarbage(true);
|
||||
ser.Serialize();
|
||||
v8::internal::byte* bytes;
|
||||
int len;
|
||||
ser.Finalize(&bytes, &len);
|
||||
|
||||
WriteInternalSnapshotToFile(argv[1], bytes, len);
|
||||
|
||||
i::DeleteArray(bytes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1386
src/serialize.cc
1386
src/serialize.cc
File diff suppressed because it is too large
Load Diff
301
src/serialize.h
301
src/serialize.h
@ -1,4 +1,4 @@
|
||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 2006-2009 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -108,260 +108,6 @@ class ExternalReferenceDecoder {
|
||||
};
|
||||
|
||||
|
||||
// A Serializer recursively visits objects to construct a serialized
|
||||
// representation of the Heap stored in a string. Serialization is
|
||||
// destructive. We use a similar mechanism to the GC to ensure that
|
||||
// each object is visited once, namely, we modify the map pointer of
|
||||
// each visited object to contain the relative address in the
|
||||
// appropriate space where that object will be allocated when the heap
|
||||
// is deserialized.
|
||||
|
||||
|
||||
// Helper classes defined in serialize.cc.
|
||||
class RelativeAddress;
|
||||
class SimulatedHeapSpace;
|
||||
class SnapshotWriter;
|
||||
class ReferenceUpdater;
|
||||
|
||||
|
||||
class Serializer: public ObjectVisitor {
|
||||
public:
|
||||
Serializer();
|
||||
|
||||
virtual ~Serializer();
|
||||
|
||||
// Serialize the current state of the heap. This operation destroys the
|
||||
// heap contents and the contents of the roots into the heap.
|
||||
void Serialize();
|
||||
|
||||
// Returns the serialized buffer. Ownership is transferred to the
|
||||
// caller. Only the destructor and getters may be called after this call.
|
||||
void Finalize(byte** str, int* len);
|
||||
|
||||
int roots() { return roots_; }
|
||||
int objects() { return objects_; }
|
||||
|
||||
#ifdef DEBUG
|
||||
// insert "tag" into the serialized stream
|
||||
virtual void Synchronize(const char* tag);
|
||||
#endif
|
||||
|
||||
static bool enabled() { return serialization_enabled_; }
|
||||
|
||||
static void Enable() {
|
||||
if (!serialization_enabled_) {
|
||||
ASSERT(!too_late_to_enable_now_);
|
||||
}
|
||||
serialization_enabled_ = true;
|
||||
}
|
||||
|
||||
static void Disable() { serialization_enabled_ = false; }
|
||||
// Call this when you have made use of the fact that there is no serialization
|
||||
// going on.
|
||||
static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
|
||||
|
||||
private:
|
||||
friend class ReferenceUpdater;
|
||||
|
||||
virtual void VisitPointers(Object** start, Object** end);
|
||||
virtual void VisitCodeTarget(RelocInfo* rinfo);
|
||||
bool IsVisited(HeapObject* obj);
|
||||
|
||||
Address GetSavedAddress(HeapObject* obj);
|
||||
|
||||
void SaveAddress(HeapObject* obj, Address addr);
|
||||
|
||||
void PutEncodedAddress(Address addr);
|
||||
// Write the global flags into the file.
|
||||
void PutFlags();
|
||||
// Write global information into the header of the file.
|
||||
void PutHeader();
|
||||
// Write the contents of the log into the file.
|
||||
void PutLog();
|
||||
// Serialize 'obj', and return its encoded RelativeAddress.
|
||||
Address PutObject(HeapObject* obj);
|
||||
// Write a stack of handles to the file bottom first.
|
||||
void PutGlobalHandleStack(const List<Handle<Object> >& stack);
|
||||
// Write the context stack into the file.
|
||||
void PutContextStack();
|
||||
|
||||
// Return the encoded RelativeAddress where this object will be
|
||||
// allocated on deserialization. On the first visit of 'o',
|
||||
// serialize its contents. On return, *serialized will be true iff
|
||||
// 'o' has just been serialized.
|
||||
Address Encode(Object* o, bool* serialized);
|
||||
|
||||
// Simulate the allocation of 'obj', returning the address where it will
|
||||
// be allocated on deserialization
|
||||
RelativeAddress Allocate(HeapObject* obj);
|
||||
|
||||
void InitializeAllocators();
|
||||
|
||||
SnapshotWriter* writer_;
|
||||
bool root_; // serializing a root?
|
||||
int roots_; // number of roots visited
|
||||
int objects_; // number of objects serialized
|
||||
|
||||
static bool serialization_enabled_;
|
||||
// Did we already make use of the fact that serialization was not enabled?
|
||||
static bool too_late_to_enable_now_;
|
||||
|
||||
int flags_end_; // The position right after the flags.
|
||||
|
||||
// An array of per-space SimulatedHeapSpaces used as memory allocators.
|
||||
SimulatedHeapSpace* allocator_[LAST_SPACE+1];
|
||||
// A list of global handles at serialization time.
|
||||
List<Object**> global_handles_;
|
||||
|
||||
ExternalReferenceEncoder* reference_encoder_;
|
||||
|
||||
HashMap saved_addresses_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Serializer);
|
||||
};
|
||||
|
||||
// Helper class to read the bytes of the serialized heap.
|
||||
|
||||
class SnapshotReader {
|
||||
public:
|
||||
SnapshotReader(const byte* str, int len): str_(str), end_(str + len) {}
|
||||
|
||||
void ExpectC(char expected) {
|
||||
int c = GetC();
|
||||
USE(c);
|
||||
ASSERT(c == expected);
|
||||
}
|
||||
|
||||
int GetC() {
|
||||
if (str_ >= end_) return EOF;
|
||||
return *str_++;
|
||||
}
|
||||
|
||||
int GetInt() {
|
||||
int result;
|
||||
GetBytes(reinterpret_cast<Address>(&result), sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
Address GetAddress() {
|
||||
Address result;
|
||||
GetBytes(reinterpret_cast<Address>(&result), sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
void GetBytes(Address a, int size) {
|
||||
ASSERT(str_ + size <= end_);
|
||||
memcpy(a, str_, size);
|
||||
str_ += size;
|
||||
}
|
||||
|
||||
char* GetString() {
|
||||
ExpectC('[');
|
||||
int size = GetInt();
|
||||
ExpectC(']');
|
||||
char* s = NewArray<char>(size + 1);
|
||||
GetBytes(reinterpret_cast<Address>(s), size);
|
||||
s[size] = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
private:
|
||||
const byte* str_;
|
||||
const byte* end_;
|
||||
};
|
||||
|
||||
|
||||
// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
|
||||
|
||||
|
||||
// TODO(erikcorry): Get rid of this superclass when we are using the new
|
||||
// snapshot code exclusively.
|
||||
class GenericDeserializer: public ObjectVisitor {
|
||||
public:
|
||||
virtual void GetLog() = 0;
|
||||
virtual void Deserialize() = 0;
|
||||
};
|
||||
|
||||
|
||||
// TODO(erikcorry): Get rid of this class.
|
||||
class Deserializer: public GenericDeserializer {
|
||||
public:
|
||||
// Create a deserializer. The snapshot is held in str and has size len.
|
||||
Deserializer(const byte* str, int len);
|
||||
|
||||
virtual ~Deserializer();
|
||||
|
||||
// Read the flags from the header of the file, and set those that
|
||||
// should be inherited from the snapshot.
|
||||
void GetFlags();
|
||||
|
||||
// Read saved profiling information from the file and log it if required.
|
||||
void GetLog();
|
||||
|
||||
// Deserialize the snapshot into an empty heap.
|
||||
void Deserialize();
|
||||
|
||||
int roots() { return roots_; }
|
||||
int objects() { return objects_; }
|
||||
|
||||
#ifdef DEBUG
|
||||
// Check for the presence of "tag" in the serialized stream
|
||||
virtual void Synchronize(const char* tag);
|
||||
#endif
|
||||
|
||||
private:
|
||||
virtual void VisitPointers(Object** start, Object** end);
|
||||
virtual void VisitCodeTarget(RelocInfo* rinfo);
|
||||
virtual void VisitExternalReferences(Address* start, Address* end);
|
||||
virtual void VisitRuntimeEntry(RelocInfo* rinfo);
|
||||
|
||||
Address GetEncodedAddress();
|
||||
|
||||
// Read other global information (except flags) from the header of the file.
|
||||
void GetHeader();
|
||||
// Read a stack of handles from the file bottom first.
|
||||
void GetGlobalHandleStack(List<Handle<Object> >* stack);
|
||||
// Read the context stack from the file.
|
||||
void GetContextStack();
|
||||
|
||||
Object* GetObject();
|
||||
|
||||
// Get the encoded address. In debug mode we make sure
|
||||
// it matches the given expectations.
|
||||
void ExpectEncodedAddress(Address expected);
|
||||
|
||||
// Given an encoded address (the result of
|
||||
// RelativeAddress::Encode), return the object to which it points,
|
||||
// which will be either an Smi or a HeapObject in the current heap.
|
||||
Object* Resolve(Address encoded_address);
|
||||
|
||||
SnapshotReader reader_;
|
||||
bool root_; // Deserializing a root?
|
||||
int roots_; // number of roots visited
|
||||
int objects_; // number of objects serialized
|
||||
|
||||
bool has_log_; // The file has log information.
|
||||
|
||||
// Resolve caches the following:
|
||||
List<Page*> map_pages_; // All pages in the map space.
|
||||
List<Page*> cell_pages_; // All pages in the cell space.
|
||||
List<Page*> old_pointer_pages_; // All pages in the old pointer space.
|
||||
List<Page*> old_data_pages_; // All pages in the old data space.
|
||||
List<Page*> code_pages_; // All pages in the code space.
|
||||
List<Object*> large_objects_; // All known large objects.
|
||||
// A list of global handles at deserialization time.
|
||||
List<Object**> global_handles_;
|
||||
|
||||
ExternalReferenceDecoder* reference_decoder_;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool expect_debug_information_;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Deserializer);
|
||||
};
|
||||
|
||||
|
||||
class SnapshotByteSource {
|
||||
public:
|
||||
SnapshotByteSource(const byte* array, int length)
|
||||
@ -407,6 +153,7 @@ class SnapshotByteSource {
|
||||
int position_;
|
||||
};
|
||||
|
||||
|
||||
// It is very common to have a reference to the object at word 10 in space 2,
|
||||
// the object at word 5 in space 2 and the object at word 28 in space 4. This
|
||||
// only works for objects in the first page of a space.
|
||||
@ -436,10 +183,9 @@ class SnapshotByteSource {
|
||||
f(14, 32) \
|
||||
f(15, 36)
|
||||
|
||||
// The SerDes class is a common superclass for Serializer2 and Deserializer2
|
||||
// The SerDes class is a common superclass for Serializer and Deserializer
|
||||
// which is used to store common constants and methods used by both.
|
||||
// TODO(erikcorry): This should inherit from ObjectVisitor.
|
||||
class SerDes: public GenericDeserializer {
|
||||
class SerDes: public ObjectVisitor {
|
||||
protected:
|
||||
enum DataType {
|
||||
RAW_DATA_SERIALIZATION = 0,
|
||||
@ -483,16 +229,15 @@ class SerDes: public GenericDeserializer {
|
||||
|
||||
|
||||
// A Deserializer reads a snapshot and reconstructs the Object graph it defines.
|
||||
class Deserializer2: public SerDes {
|
||||
class Deserializer: public SerDes {
|
||||
public:
|
||||
// Create a deserializer from a snapshot byte source.
|
||||
explicit Deserializer2(SnapshotByteSource* source);
|
||||
explicit Deserializer(SnapshotByteSource* source);
|
||||
|
||||
virtual ~Deserializer2() { }
|
||||
virtual ~Deserializer() { }
|
||||
|
||||
// Deserialize the snapshot into an empty heap.
|
||||
void Deserialize();
|
||||
void GetLog() { } // TODO(erikcorry): Get rid of this.
|
||||
#ifdef DEBUG
|
||||
virtual void Synchronize(const char* tag);
|
||||
#endif
|
||||
@ -530,7 +275,7 @@ class Deserializer2: public SerDes {
|
||||
// START_NEW_PAGE_SERIALIZATION tag.
|
||||
Address last_object_address_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Deserializer2);
|
||||
DISALLOW_COPY_AND_ASSIGN(Deserializer);
|
||||
};
|
||||
|
||||
|
||||
@ -545,15 +290,26 @@ class SnapshotByteSink {
|
||||
};
|
||||
|
||||
|
||||
class Serializer2 : public SerDes {
|
||||
class Serializer : public SerDes {
|
||||
public:
|
||||
explicit Serializer2(SnapshotByteSink* sink);
|
||||
explicit Serializer(SnapshotByteSink* sink);
|
||||
// Serialize the current state of the heap. This operation destroys the
|
||||
// heap contents.
|
||||
void Serialize();
|
||||
void VisitPointers(Object** start, Object** end);
|
||||
void GetLog() { } // TODO(erikcorry): Get rid of this.
|
||||
void Deserialize() { } // TODO(erikcorry): Get rid of this.
|
||||
|
||||
static void Enable() {
|
||||
if (!serialization_enabled_) {
|
||||
ASSERT(!too_late_to_enable_now_);
|
||||
}
|
||||
serialization_enabled_ = true;
|
||||
}
|
||||
|
||||
static void Disable() { serialization_enabled_ = false; }
|
||||
// Call this when you have made use of the fact that there is no serialization
|
||||
// going on.
|
||||
static void TooLateToEnableNow() { too_late_to_enable_now_ = true; }
|
||||
static bool enabled() { return serialization_enabled_; }
|
||||
#ifdef DEBUG
|
||||
virtual void Synchronize(const char* tag);
|
||||
#endif
|
||||
@ -565,7 +321,7 @@ class Serializer2 : public SerDes {
|
||||
};
|
||||
class ObjectSerializer : public ObjectVisitor {
|
||||
public:
|
||||
ObjectSerializer(Serializer2* serializer,
|
||||
ObjectSerializer(Serializer* serializer,
|
||||
Object* o,
|
||||
SnapshotByteSink* sink,
|
||||
ReferenceRepresentation representation)
|
||||
@ -591,7 +347,7 @@ class Serializer2 : public SerDes {
|
||||
private:
|
||||
void OutputRawData(Address up_to);
|
||||
|
||||
Serializer2* serializer_;
|
||||
Serializer* serializer_;
|
||||
HeapObject* object_;
|
||||
SnapshotByteSink* sink_;
|
||||
ReferenceRepresentation reference_representation_;
|
||||
@ -626,11 +382,14 @@ class Serializer2 : public SerDes {
|
||||
SnapshotByteSink* sink_;
|
||||
int current_root_index_;
|
||||
ExternalReferenceEncoder* external_reference_encoder_;
|
||||
static bool serialization_enabled_;
|
||||
// Did we already make use of the fact that serialization was not enabled?
|
||||
static bool too_late_to_enable_now_;
|
||||
|
||||
friend class ObjectSerializer;
|
||||
friend class Deserializer2;
|
||||
friend class Deserializer;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Serializer2);
|
||||
DISALLOW_COPY_AND_ASSIGN(Serializer);
|
||||
};
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -38,15 +38,8 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
bool Snapshot::Deserialize(const byte* content, int len) {
|
||||
Deserializer des(content, len);
|
||||
des.GetFlags();
|
||||
return V8::Initialize(&des);
|
||||
}
|
||||
|
||||
|
||||
bool Snapshot::Deserialize2(const byte* content, int len) {
|
||||
SnapshotByteSource source(content, len);
|
||||
Deserializer2 deserializer(&source);
|
||||
Deserializer deserializer(&source);
|
||||
return V8::Initialize(&deserializer);
|
||||
}
|
||||
|
||||
@ -56,46 +49,17 @@ bool Snapshot::Initialize(const char* snapshot_file) {
|
||||
int len;
|
||||
byte* str = ReadBytes(snapshot_file, &len);
|
||||
if (!str) return false;
|
||||
bool result = Deserialize(str, len);
|
||||
DeleteArray(str);
|
||||
return result;
|
||||
} else if (size_ > 0) {
|
||||
return Deserialize(data_, size_);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Snapshot::Initialize2(const char* snapshot_file) {
|
||||
if (snapshot_file) {
|
||||
int len;
|
||||
byte* str = ReadBytes(snapshot_file, &len);
|
||||
if (!str) return false;
|
||||
Deserialize2(str, len);
|
||||
Deserialize(str, len);
|
||||
DeleteArray(str);
|
||||
return true;
|
||||
} else if (size_ > 0) {
|
||||
Deserialize2(data_, size_);
|
||||
Deserialize(data_, size_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Snapshot::WriteToFile(const char* snapshot_file) {
|
||||
Serializer ser;
|
||||
ser.Serialize();
|
||||
byte* str;
|
||||
int len;
|
||||
ser.Finalize(&str, &len);
|
||||
|
||||
int written = WriteBytes(snapshot_file, str, len);
|
||||
|
||||
DeleteArray(str);
|
||||
return written == len;
|
||||
}
|
||||
|
||||
|
||||
class FileByteSink : public SnapshotByteSink {
|
||||
public:
|
||||
explicit FileByteSink(const char* snapshot_file) {
|
||||
@ -121,9 +85,9 @@ class FileByteSink : public SnapshotByteSink {
|
||||
};
|
||||
|
||||
|
||||
bool Snapshot::WriteToFile2(const char* snapshot_file) {
|
||||
bool Snapshot::WriteToFile(const char* snapshot_file) {
|
||||
FileByteSink file(snapshot_file);
|
||||
Serializer2 ser(&file);
|
||||
Serializer ser(&file);
|
||||
ser.Serialize();
|
||||
return true;
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ class Snapshot {
|
||||
// NULL, use the internal snapshot instead. Returns false if no snapshot
|
||||
// could be found.
|
||||
static bool Initialize(const char* snapshot_file = NULL);
|
||||
static bool Initialize2(const char* snapshot_file = NULL);
|
||||
|
||||
// Returns whether or not the snapshot is enabled.
|
||||
static bool IsEnabled() { return size_ != 0; }
|
||||
@ -45,14 +44,12 @@ class Snapshot {
|
||||
// Write snapshot to the given file. Returns true if snapshot was written
|
||||
// successfully.
|
||||
static bool WriteToFile(const char* snapshot_file);
|
||||
static bool WriteToFile2(const char* snapshot_file);
|
||||
|
||||
private:
|
||||
static const byte data_[];
|
||||
static int size_;
|
||||
|
||||
static bool Deserialize(const byte* content, int len);
|
||||
static bool Deserialize2(const byte* content, int len);
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Snapshot);
|
||||
};
|
||||
|
@ -43,7 +43,7 @@ bool V8::has_been_setup_ = false;
|
||||
bool V8::has_been_disposed_ = false;
|
||||
bool V8::has_fatal_error_ = false;
|
||||
|
||||
bool V8::Initialize(GenericDeserializer *des) {
|
||||
bool V8::Initialize(Deserializer *des) {
|
||||
bool create_heap_objects = des == NULL;
|
||||
if (has_been_disposed_ || has_fatal_error_) return false;
|
||||
if (IsRunning()) return true;
|
||||
@ -59,7 +59,6 @@ bool V8::Initialize(GenericDeserializer *des) {
|
||||
|
||||
// Enable logging before setting up the heap
|
||||
Logger::Setup();
|
||||
if (des) des->GetLog();
|
||||
|
||||
// Setup the platform OS support.
|
||||
OS::Setup();
|
||||
|
4
src/v8.h
4
src/v8.h
@ -72,6 +72,8 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class Deserializer;
|
||||
|
||||
class V8 : public AllStatic {
|
||||
public:
|
||||
// Global actions.
|
||||
@ -80,7 +82,7 @@ class V8 : public AllStatic {
|
||||
// created from scratch. If a non-null Deserializer is given, the
|
||||
// initial state is created by reading the deserialized data into an
|
||||
// empty heap.
|
||||
static bool Initialize(GenericDeserializer* des);
|
||||
static bool Initialize(Deserializer* des);
|
||||
static void TearDown();
|
||||
static bool IsRunning() { return is_running_; }
|
||||
// To be dead you have to have lived
|
||||
|
@ -33,12 +33,6 @@ test-debug/DebuggerAgent: PASS, (PASS || FAIL) if $system == linux
|
||||
# BUG(382): Weird test. Can't guarantee that it never times out.
|
||||
test-api/ApplyInterruption: PASS || TIMEOUT
|
||||
|
||||
# This is about to go away anyway since new snapshot code is on the way.
|
||||
test-serialize/Deserialize: FAIL
|
||||
test-serialize/DeserializeAndRunScript: FAIL || CRASH
|
||||
test-serialize/DeserializeNatives: FAIL || CRASH
|
||||
test-serialize/DeserializeExtensions: FAIL || CRASH
|
||||
|
||||
# These tests always fail. They are here to test test.py. If
|
||||
# they don't fail then test.py has failed.
|
||||
test-serialize/TestThatAlwaysFails: FAIL
|
||||
|
@ -174,83 +174,32 @@ TEST(ExternalReferenceDecoder) {
|
||||
|
||||
|
||||
static void Serialize() {
|
||||
#ifdef DEBUG
|
||||
FLAG_debug_serialization = true;
|
||||
#endif
|
||||
StatsTable::SetCounterFunction(counter_function);
|
||||
|
||||
v8::HandleScope scope;
|
||||
const int kExtensionCount = 1;
|
||||
const char* extension_list[kExtensionCount] = { "v8/gc" };
|
||||
v8::ExtensionConfiguration extensions(kExtensionCount, extension_list);
|
||||
Serializer::Enable();
|
||||
v8::Persistent<v8::Context> env = v8::Context::New(&extensions);
|
||||
env->Enter();
|
||||
|
||||
Snapshot::WriteToFile(FLAG_testing_serialization_file);
|
||||
}
|
||||
|
||||
|
||||
static void Serialize2() {
|
||||
// We have to create one context. One reason for this is so that the builtins
|
||||
// can be loaded from v8natives.js and their addresses can be processed. This
|
||||
// will clear the pending fixups array, which would otherwise contain GC roots
|
||||
// that would confuse the serialization/deserialization process.
|
||||
v8::Persistent<v8::Context> env = v8::Context::New();
|
||||
env.Dispose();
|
||||
Snapshot::WriteToFile2(FLAG_testing_serialization_file);
|
||||
}
|
||||
|
||||
|
||||
// Test that the whole heap can be serialized when running from a
|
||||
// bootstrapped heap.
|
||||
// (Smoke test.)
|
||||
TEST(Serialize) {
|
||||
if (Snapshot::IsEnabled()) return;
|
||||
Serialize();
|
||||
Snapshot::WriteToFile(FLAG_testing_serialization_file);
|
||||
}
|
||||
|
||||
|
||||
// Test that the whole heap can be serialized.
|
||||
TEST(Serialize2) {
|
||||
TEST(Serialize) {
|
||||
Serializer::Enable();
|
||||
v8::V8::Initialize();
|
||||
Serialize2();
|
||||
Serialize();
|
||||
}
|
||||
|
||||
|
||||
// Test that the heap isn't destroyed after a serialization.
|
||||
TEST(SerializeNondestructive) {
|
||||
if (Snapshot::IsEnabled()) return;
|
||||
StatsTable::SetCounterFunction(counter_function);
|
||||
v8::HandleScope scope;
|
||||
Serializer::Enable();
|
||||
v8::Persistent<v8::Context> env = v8::Context::New();
|
||||
v8::Context::Scope context_scope(env);
|
||||
Serializer().Serialize();
|
||||
const char* c_source = "\"abcd\".charAt(2) == 'c'";
|
||||
v8::Local<v8::String> source = v8::String::New(c_source);
|
||||
v8::Local<v8::Script> script = v8::Script::Compile(source);
|
||||
v8::Local<v8::Value> value = script->Run();
|
||||
CHECK(value->BooleanValue());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Tests that the heap can be deserialized.
|
||||
|
||||
static void Deserialize() {
|
||||
#ifdef DEBUG
|
||||
FLAG_debug_serialization = true;
|
||||
#endif
|
||||
CHECK(Snapshot::Initialize(FLAG_testing_serialization_file));
|
||||
}
|
||||
|
||||
|
||||
static void Deserialize2() {
|
||||
CHECK(Snapshot::Initialize2(FLAG_testing_serialization_file));
|
||||
}
|
||||
|
||||
|
||||
static void SanityCheck() {
|
||||
v8::HandleScope scope;
|
||||
#ifdef DEBUG
|
||||
@ -269,15 +218,6 @@ DEPENDENT_TEST(Deserialize, Serialize) {
|
||||
|
||||
Deserialize();
|
||||
|
||||
SanityCheck();
|
||||
}
|
||||
|
||||
|
||||
DEPENDENT_TEST(Deserialize2, Serialize2) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
Deserialize2();
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
v8::Persistent<v8::Context> env = v8::Context::New();
|
||||
@ -287,23 +227,11 @@ DEPENDENT_TEST(Deserialize2, Serialize2) {
|
||||
}
|
||||
|
||||
|
||||
DEPENDENT_TEST(DeserializeAndRunScript, Serialize) {
|
||||
DEPENDENT_TEST(DeserializeAndRunScript2, Serialize) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
Deserialize();
|
||||
|
||||
const char* c_source = "\"1234\".length";
|
||||
v8::Local<v8::String> source = v8::String::New(c_source);
|
||||
v8::Local<v8::Script> script = v8::Script::Compile(source);
|
||||
CHECK_EQ(4, script->Run()->Int32Value());
|
||||
}
|
||||
|
||||
|
||||
DEPENDENT_TEST(DeserializeAndRunScript2, Serialize2) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
Deserialize2();
|
||||
|
||||
v8::Persistent<v8::Context> env = v8::Context::New();
|
||||
env->Enter();
|
||||
|
||||
@ -314,31 +242,6 @@ DEPENDENT_TEST(DeserializeAndRunScript2, Serialize2) {
|
||||
}
|
||||
|
||||
|
||||
DEPENDENT_TEST(DeserializeNatives, Serialize) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
Deserialize();
|
||||
|
||||
const char* c_source = "\"abcd\".charAt(2) == 'c'";
|
||||
v8::Local<v8::String> source = v8::String::New(c_source);
|
||||
v8::Local<v8::Script> script = v8::Script::Compile(source);
|
||||
v8::Local<v8::Value> value = script->Run();
|
||||
CHECK(value->BooleanValue());
|
||||
}
|
||||
|
||||
|
||||
DEPENDENT_TEST(DeserializeExtensions, Serialize) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
Deserialize();
|
||||
const char* c_source = "gc();";
|
||||
v8::Local<v8::String> source = v8::String::New(c_source);
|
||||
v8::Local<v8::Script> script = v8::Script::Compile(source);
|
||||
v8::Local<v8::Value> value = script->Run();
|
||||
CHECK(value->IsUndefined());
|
||||
}
|
||||
|
||||
|
||||
TEST(TestThatAlwaysSucceeds) {
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user