commit 7753ace1354ac231374da0446a5057b6b40780db
Author: yangguo@chromium.org <yangguo@chromium.org>
Date:   Thu Oct 23 08:25:42 2014 +0000

    Small fixes for the code serializer.
    - assertions regarding max heap object size.
    - ensure string table capacity upfront.
    
    R=mvstanton@chromium.org
    
    Review URL: https://codereview.chromium.org/671843003
    
    git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24824 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

diff --git a/src/objects.cc b/src/objects.cc
index 2685a5c..371931c 100644
--- node/deps/v8/src/objects.cc
+++ node/deps/v8/src/objects.cc
@@ -14769,6 +14769,16 @@ MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
 }
 
 
+void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
+                                                   int expected) {
+  Handle<StringTable> table = isolate->factory()->string_table();
+  // We need a key instance for the virtual hash function.
+  InternalizedStringKey dummy_key(Handle<String>::null());
+  table = StringTable::EnsureCapacity(table, expected, &dummy_key);
+  isolate->factory()->set_string_table(table);
+}
+
+
 Handle<String> StringTable::LookupString(Isolate* isolate,
                                          Handle<String> string) {
   InternalizedStringKey key(string);
diff --git a/src/objects.h b/src/objects.h
index 7e509e7..b2b64c2 100644
--- node/deps/v8/src/objects.h
+++ node/deps/v8/src/objects.h
@@ -3446,6 +3446,8 @@ class StringTable: public HashTable<StringTable,
       uint16_t c1,
       uint16_t c2);
 
+  static void EnsureCapacityForDeserialization(Isolate* isolate, int expected);
+
   DECLARE_CAST(StringTable)
 
  private:
diff --git a/src/serialize.cc b/src/serialize.cc
index 5e6de03..95336fb 100644
--- node/deps/v8/src/serialize.cc
+++ node/deps/v8/src/serialize.cc
@@ -1910,7 +1913,7 @@ uint32_t Serializer::AllocateLargeObject(int size) {
 
 uint32_t Serializer::Allocate(int space, int size) {
   CHECK(space >= 0 && space < kNumberOfPreallocatedSpaces);
-  DCHECK(size > 0 && size < Page::kMaxRegularHeapObjectSize);
+  DCHECK(size > 0 && size <= Page::kMaxRegularHeapObjectSize);
   uint32_t new_chunk_size = pending_chunk_[space] + size;
   uint32_t allocation;
   if (new_chunk_size > static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize)) {
@@ -2081,6 +2084,8 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
     PrintF("\n");
   }
 
+  if (heap_object->IsInternalizedString()) num_internalized_strings_++;
+
   // Object has not yet been serialized.  Serialize it here.
   ObjectSerializer serializer(this, heap_object, sink_, how_to_code,
                               where_to_point);
@@ -2201,6 +2206,11 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
     SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
     Deserializer deserializer(&payload);
 
+    // Eagerly expand string table to avoid allocations during deserialization.
+    StringTable::EnsureCapacityForDeserialization(isolate,
+                                                  scd.NumInternalizedStrings());
+
+    // Set reservations.
     STATIC_ASSERT(NEW_SPACE == 0);
     int current_space = NEW_SPACE;
     Vector<const SerializedCodeData::Reservation> res = scd.Reservations();
@@ -2254,7 +2264,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
     Vector<const uint32_t> chunks = cs->FinalAllocationChunks(i);
     for (int j = 0; j < chunks.length(); j++) {
       DCHECK(i == LO_SPACE ||
-             chunks[j] <
+             chunks[j] <=
                  static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
       uint32_t chunk = ChunkSizeBits::encode(chunks[j]) |
                        IsLastChunkBits::encode(j == chunks.length() - 1);
@@ -2277,6 +2287,7 @@ SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
 
   // Set header values.
   SetHeaderValue(kCheckSumOffset, CheckSum(cs->source()));
+  SetHeaderValue(kNumInternalizedStringsOffset, cs->num_internalized_strings());
   SetHeaderValue(kReservationsOffset, reservations.length());
   SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
   SetHeaderValue(kPayloadLengthOffset, payload->length());
diff --git a/src/serialize.h b/src/serialize.h
index 47a244f..df6723c 100644
--- node/deps/v8/src/serialize.h
+++ node/deps/v8/src/serialize.h
@@ -264,7 +264,7 @@ class Deserializer: public SerializerDeserializer {
     DCHECK(space >= 0);
     DCHECK(space < kNumberOfSpaces);
     DCHECK(space == LO_SPACE ||
-           chunk < static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
+           chunk <= static_cast<uint32_t>(Page::kMaxRegularHeapObjectSize));
     Heap::Chunk c = { chunk, NULL, NULL }; reservations_[space].Add(c);
   }
 
@@ -619,17 +619,21 @@ class CodeSerializer : public Serializer {
   static const int kSourceObjectIndex = 0;
   static const int kCodeStubsBaseIndex = 1;
 
-  String* source() {
+  String* source() const {
     DCHECK(!AllowHeapAllocation::IsAllowed());
     return source_;
   }
 
   List<uint32_t>* stub_keys() { return &stub_keys_; }
+  int num_internalized_strings() const { return num_internalized_strings_; }
 
  private:
   CodeSerializer(Isolate* isolate, SnapshotByteSink* sink, String* source,
                  Code* main_code)
-      : Serializer(isolate, sink), source_(source), main_code_(main_code) {
+      : Serializer(isolate, sink),
+        source_(source),
+        main_code_(main_code),
+        num_internalized_strings_(0) {
     set_root_index_wave_front(Heap::kStrongRootListLength);
     InitializeCodeAddressMap();
   }
@@ -652,6 +656,7 @@ class CodeSerializer : public Serializer {
   DisallowHeapAllocation no_gc_;
   String* source_;
   Code* main_code_;
+  int num_internalized_strings_;
   List<uint32_t> stub_keys_;
   DISALLOW_COPY_AND_ASSIGN(CodeSerializer);
 };
@@ -694,6 +699,10 @@ class SerializedCodeData {
     DISALLOW_COPY_AND_ASSIGN(Reservation);
   };
 
+  int NumInternalizedStrings() const {
+    return GetHeaderValue(kNumInternalizedStringsOffset);
+  }
+
   Vector<const Reservation> Reservations() const {
     return Vector<const Reservation>(reinterpret_cast<const Reservation*>(
                                          script_data_->data() + kHeaderSize),
@@ -737,13 +746,15 @@ class SerializedCodeData {
 
   // The data header consists of int-sized entries:
   // [0] version hash
-  // [1] number of code stub keys
-  // [2] payload length
-  // [3..9] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
+  // [1] number of internalized strings
+  // [2] number of code stub keys
+  // [3] payload length
+  // [4..10] reservation sizes for spaces from NEW_SPACE to PROPERTY_CELL_SPACE.
   static const int kCheckSumOffset = 0;
-  static const int kReservationsOffset = 1;
-  static const int kNumCodeStubKeysOffset = 2;
-  static const int kPayloadLengthOffset = 3;
+  static const int kNumInternalizedStringsOffset = 1;
+  static const int kReservationsOffset = 2;
+  static const int kNumCodeStubKeysOffset = 3;
+  static const int kPayloadLengthOffset = 4;
   static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize;
 
   class ChunkSizeBits : public BitField<uint32_t, 0, 31> {};
