Commit dbd7f20d authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Introduce a switch for the new snapshot code and switch

it on by default.  Includes bug fixes for new snapshots.
Review URL: http://codereview.chromium.org/342054

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3184 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 07cd399b
......@@ -2621,11 +2621,12 @@ bool v8::V8::Initialize() {
if (i::V8::IsRunning()) return true;
ENTER_V8;
HandleScope scope;
if (i::Snapshot::Initialize()) {
return true;
if (i::FLAG_new_snapshot) {
if (i::Snapshot::Initialize2()) return true;
} else {
return i::V8::Initialize(NULL);
if (i::Snapshot::Initialize()) return true;
}
return i::V8::Initialize(NULL);
}
......
......@@ -437,13 +437,25 @@ class Assembler : public Malloced {
INLINE(static Address target_address_at(Address pc));
INLINE(static void set_target_address_at(Address pc, Address target));
// Modify the code target address in a constant pool entry.
inline static void set_target_at(Address constant_pool_entry, Address target);
// This sets the branch destination (which is in the constant pool on ARM).
// This is for calls and branches within generated code.
inline static void set_target_at(Address constant_pool_entry,
Address target) {
set_target_address_at(constant_pool_entry, target);
}
// This sets the branch destination (which is in the constant pool on ARM).
// This is for calls and branches to runtime code.
inline static void set_external_target_at(Address constant_pool_entry,
Address target) {
set_target_address_at(constant_pool_entry, target);
}
// Here we are patching the address in the constant pool, not the actual call
// instruction. The address in the constant pool is the same size as a
// pointer.
static const int kCallTargetSize = kPointerSize;
static const int kExternalTargetSize = kPointerSize;
// Size of an instruction.
static const int kInstrSize = sizeof(Instr);
......
......@@ -196,6 +196,7 @@ DEFINE_bool(canonicalize_object_literal_maps, true,
// mksnapshot.cc
DEFINE_bool(h, false, "print this message")
DEFINE_bool(new_snapshot, true, "use new snapshot implementation")
// parser.cc
DEFINE_bool(allow_natives_syntax, false, "allow natives syntax")
......
......@@ -399,6 +399,7 @@ void GlobalHandles::IterateRoots(ObjectVisitor* v) {
}
}
void GlobalHandles::TearDown() {
// Reset all the lists.
set_head(NULL);
......
......@@ -440,12 +440,21 @@ class Assembler : public Malloced {
inline static void set_target_address_at(Address pc, Address target);
// This sets the branch destination (which is in the instruction on x86).
// This is for calls and branches within generated code.
inline static void set_target_at(Address instruction_payload,
Address target) {
set_target_address_at(instruction_payload, target);
}
// This sets the branch destination (which is in the instruction on x86).
// This is for calls and branches to runtime code.
inline static void set_external_target_at(Address instruction_payload,
Address target) {
set_target_address_at(instruction_payload, target);
}
static const int kCallTargetSize = kPointerSize;
static const int kExternalTargetSize = kPointerSize;
// Distance between the address of the code target in the call instruction
// and the return address
......
......@@ -109,6 +109,48 @@ static int* counter_callback(const char* name) {
}
class CppByteSink : public i::SnapshotByteSink {
public:
explicit CppByteSink(const char* snapshot_file) : bytes_written_(0) {
fp_ = i::OS::FOpen(snapshot_file, "wb");
if (fp_ == NULL) {
i::PrintF("Unable to write to snapshot file \"%s\"\n", snapshot_file);
exit(1);
}
fprintf(fp_, "// Autogenerated snapshot file. Do not edit.\n\n");
fprintf(fp_, "#include \"v8.h\"\n");
fprintf(fp_, "#include \"platform.h\"\n\n");
fprintf(fp_, "#include \"snapshot.h\"\n\n");
fprintf(fp_, "namespace v8 {\nnamespace internal {\n\n");
fprintf(fp_, "const byte Snapshot::data_[] = {");
}
virtual ~CppByteSink() {
if (fp_ != NULL) {
fprintf(fp_, "};\n\n");
fprintf(fp_, "int Snapshot::size_ = %d;\n\n", bytes_written_);
fprintf(fp_, "} } // namespace v8::internal\n");
fclose(fp_);
}
}
virtual void Put(int byte, const char* description) {
if (bytes_written_ != 0) {
fprintf(fp_, ",");
}
fprintf(fp_, "%d", byte);
bytes_written_++;
if ((bytes_written_ & 0x3f) == 0) {
fprintf(fp_, "\n");
}
}
private:
FILE* fp_;
int bytes_written_;
};
// 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,
......@@ -116,7 +158,7 @@ static int WriteInternalSnapshotToFile(const char* filename,
int size) {
FILE* f = i::OS::FOpen(filename, "wb");
if (f == NULL) {
i::OS::PrintError("Cannot open file %s for reading.\n", filename);
i::OS::PrintError("Cannot open file %s for writing.\n", filename);
return 0;
}
fprintf(f, "// Autogenerated snapshot file. Do not edit.\n\n");
......@@ -140,6 +182,23 @@ static int WriteInternalSnapshotToFile(const char* filename,
}
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);
ser.Serialize();
return 0;
}
int main(int argc, char** argv) {
#ifdef ENABLE_LOGGING_AND_PROFILING
// By default, log code create information in the snapshot.
......@@ -154,6 +213,10 @@ int main(int argc, char** argv) {
return !i::FLAG_help;
}
if (i::FLAG_new_snapshot) {
return main2(argc, argv);
}
v8::V8::SetCounterFunction(counter_callback);
v8::HandleScope scope;
......
......@@ -1927,10 +1927,8 @@ bool Deserializer2::ReadObject(Object** write_back) {
case RAW_DATA_SERIALIZATION: {
int size = source_->GetInt();
byte* raw_data_out = reinterpret_cast<byte*>(current);
for (int j = 0; j < size; j++) {
*raw_data_out++ = source_->Get();
}
current = reinterpret_cast<Object**>(raw_data_out);
source_->CopyRaw(raw_data_out, size);
current = reinterpret_cast<Object**>(raw_data_out + size);
break;
}
case OBJECT_SERIALIZATION: {
......@@ -1984,6 +1982,15 @@ bool Deserializer2::ReadObject(Object** write_back) {
*current++ = reinterpret_cast<Object*>(address);
break;
}
case EXTERNAL_BRANCH_TARGET_SERIALIZATION: {
int reference_id = source_->GetInt();
Address address = external_reference_decoder_->Decode(reference_id);
Address location_of_branch_data = reinterpret_cast<Address>(current);
Assembler::set_external_target_at(location_of_branch_data, address);
location_of_branch_data += Assembler::kExternalTargetSize;
current = reinterpret_cast<Object**>(location_of_branch_data);
break;
}
default:
UNREACHABLE();
}
......@@ -2159,6 +2166,18 @@ void Serializer2::ObjectSerializer::VisitExternalReferences(Address* start,
}
void Serializer2::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) {
Address target_start = rinfo->target_address_address();
OutputRawData(target_start);
Address target = rinfo->target_address();
uint32_t encoding = serializer_->EncodeExternalReference(target);
CHECK(target == NULL ? encoding == 0 : encoding != 0);
sink_->Put(EXTERNAL_BRANCH_TARGET_SERIALIZATION, "External reference");
sink_->PutInt(encoding, "reference id");
bytes_processed_so_far_ += Assembler::kExternalTargetSize;
}
void Serializer2::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
Address target_start = rinfo->target_address_address();
......@@ -2183,8 +2202,8 @@ void Serializer2::ObjectSerializer::OutputRawData(Address up_to) {
unsigned int data = object_start[bytes_processed_so_far_ + i];
sink_->Put(data, "byte");
}
bytes_processed_so_far_ += skipped;
}
bytes_processed_so_far_ += skipped;
}
......
......@@ -363,6 +363,11 @@ class SnapshotByteSource {
return data_[position_++];
}
void CopyRaw(byte* to, int number_of_bytes) {
memcpy(to, data_ + position_, number_of_bytes);
position_ += number_of_bytes;
}
int GetInt() {
// A little unwind to catch the really small ints.
int snapshot_byte = Get();
......@@ -405,6 +410,7 @@ class SerDes: public GenericDeserializer {
BACKREF_SERIALIZATION,
CODE_BACKREF_SERIALIZATION,
EXTERNAL_REFERENCE_SERIALIZATION,
EXTERNAL_BRANCH_TARGET_SERIALIZATION,
SYNCHRONIZE
};
// Our Smi encoding is much more efficient for small positive integers than it
......@@ -521,6 +527,7 @@ class Serializer2 : public SerDes {
void VisitPointers(Object** start, Object** end);
void VisitExternalReferences(Address* start, Address* end);
void VisitCodeTarget(RelocInfo* target);
void VisitRuntimeEntry(RelocInfo* reloc);
private:
void OutputRawData(Address up_to);
......
......@@ -73,10 +73,12 @@ bool Snapshot::Initialize2(const char* snapshot_file) {
if (!str) return false;
Deserialize2(str, len);
DeleteArray(str);
return true;
} else if (size_ > 0) {
Deserialize2(data_, size_);
return true;
}
return true;
return false;
}
......
......@@ -458,14 +458,25 @@ class Assembler : public Malloced {
// the relative displacements stored in the code.
static inline Address target_address_at(Address pc);
static inline void set_target_address_at(Address pc, Address target);
// This sets the branch destination (which is in the instruction on x64).
// This is for calls and branches within generated code.
inline static void set_target_at(Address instruction_payload,
Address target) {
set_target_address_at(instruction_payload, target);
}
// This sets the branch destination (which is a load instruction on x64).
// This is for calls and branches to runtime code.
inline static void set_external_target_at(Address instruction_payload,
Address target) {
*reinterpret_cast<Address*>(instruction_payload) = target;
}
inline Handle<Object> code_target_object_handle_at(Address pc);
// Number of bytes taken up by the branch target in the code.
static const int kCallTargetSize = 4; // Use 32-bit displacement.
static const int kCallTargetSize = 4; // Use 32-bit displacement.
static const int kExternalTargetSize = 8; // Use 64-bit absolute.
// Distance between the address of the code target in the call instruction
// and the return address pushed on the stack.
static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
......
......@@ -197,15 +197,6 @@ static void Serialize2() {
}
// Test that the whole heap can be serialized when running from the
// internal snapshot.
// (Smoke test.)
TEST(SerializeInternal) {
Snapshot::Initialize(NULL);
Serialize();
}
// Test that the whole heap can be serialized when running from a
// bootstrapped heap.
// (Smoke test.)
......
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