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);
}
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);
// 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")
}
}
+
void GlobalHandles::TearDown() {
// Reset all the lists.
set_head(NULL);
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
}
+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,
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");
}
+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.
return !i::FLAG_help;
}
+ if (i::FLAG_new_snapshot) {
+ return main2(argc, argv);
+ }
+
v8::V8::SetCounterFunction(counter_callback);
v8::HandleScope scope;
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: {
*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();
}
}
+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();
unsigned int data = object_start[bytes_processed_so_far_ + i];
sink_->Put(data, "byte");
}
+ bytes_processed_so_far_ += skipped;
}
- bytes_processed_so_far_ += skipped;
}
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();
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
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);
if (!str) return false;
Deserialize2(str, len);
DeleteArray(str);
+ return true;
} else if (size_ > 0) {
Deserialize2(data_, size_);
+ return true;
}
- return true;
+ return false;
}
// 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.
}
-// 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.)