Introduce a switch for the new snapshot code and switch
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 30 Oct 2009 10:23:12 +0000 (10:23 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 30 Oct 2009 10:23:12 +0000 (10:23 +0000)
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

src/api.cc
src/arm/assembler-arm.h
src/flag-definitions.h
src/global-handles.cc
src/ia32/assembler-ia32.h
src/mksnapshot.cc
src/serialize.cc
src/serialize.h
src/snapshot-common.cc
src/x64/assembler-x64.h
test/cctest/test-serialize.cc

index 4cb655d0a43f1097ed3bda29bdab6dceb9b403a1..bde5fdc1a2e0182345cbd7a6c7838e31ae12f695 100644 (file)
@@ -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);
 }
 
 
index d617c7e18ef018be26d287152c29fa621f1ac365..0bb942aa853275359073ad2a818cea5215353db1 100644 (file)
@@ -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);
index 1ceb6722e1316d569ae3f9b934abbd90b3b6b956..d8b0633f931fb1d1a88ca20f212a381aeb89cc10 100644 (file)
@@ -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")
index c6cc288e6abd33289c10c36a4e1ad3c94eb6bbd0..a57c8b0c278dc472311d8e143ccb84d1534bc8b7 100644 (file)
@@ -399,6 +399,7 @@ void GlobalHandles::IterateRoots(ObjectVisitor* v) {
   }
 }
 
+
 void GlobalHandles::TearDown() {
   // Reset all the lists.
   set_head(NULL);
index a431d04c66c9bf74bc5a73bbe4b8ddb337d345d2..29e8a545bc2ba5c5d59da4d93b80dcbc464a5e83 100644 (file)
@@ -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
index 80789ebbeaa894b512859888fc295fbd1aff1a89..083d11f28096ed5d783504246bbf2f321eb87f60 100644 (file)
@@ -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;
 
index 6eedeef37bf932d6938d7df94467de18551fe3ca..398ccc7c97659a80e6c0e23e72b5436d0ffad0f4 100644 (file)
@@ -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;
 }
 
 
index cefff78cac7fcbabd6c9ac568b4f9f9c2c34631c..5966cbc3b10bae18f7fad4af0ed3eea41ac59b77 100644 (file)
@@ -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);
index b258a15c0128afad1f9bb472fe40c388e355ef13..875cc9667db58c9495896d9419537746608037fd 100644 (file)
@@ -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;
 }
 
 
index 617f092bb46087163a47570c190eb1ea4e9e1a40..474d4b861356fc3e253f32b8c9c29b34d2178a7f 100644 (file)
@@ -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.
index 01e07157a1029c6548c0d27524cc1988377f14df..2a58ac8747310943e05ad7684bd119135194dfde 100644 (file)
@@ -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.)