| Index: src/snapshot/serialize.cc
 | 
| diff --git a/src/snapshot/serialize.cc b/src/snapshot/serialize.cc
 | 
| index 66da378617571ccb915303bb828cd01fe0e8448d..9ee63f03fe46dcb72c1442bae48cabe63a3e86f0 100644
 | 
| --- a/src/snapshot/serialize.cc
 | 
| +++ b/src/snapshot/serialize.cc
 | 
| @@ -642,11 +642,17 @@ MaybeHandle<SharedFunctionInfo> Deserializer::DeserializeCode(
 | 
|      return Handle<SharedFunctionInfo>();
 | 
|    } else {
 | 
|      deserializing_user_code_ = true;
 | 
| -    DisallowHeapAllocation no_gc;
 | 
| -    Object* root;
 | 
| -    VisitPointer(&root);
 | 
| -    DeserializeDeferredObjects();
 | 
| -    return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root));
 | 
| +    HandleScope scope(isolate);
 | 
| +    Handle<SharedFunctionInfo> result;
 | 
| +    {
 | 
| +      DisallowHeapAllocation no_gc;
 | 
| +      Object* root;
 | 
| +      VisitPointer(&root);
 | 
| +      DeserializeDeferredObjects();
 | 
| +      result = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root));
 | 
| +    }
 | 
| +    CommitNewInternalizedStrings(isolate);
 | 
| +    return scope.CloseAndEscape(result);
 | 
|    }
 | 
|  }
 | 
|  
 | 
| @@ -711,8 +717,10 @@ class StringTableInsertionKey : public HashTableKey {
 | 
|      return handle(string_, isolate);
 | 
|    }
 | 
|  
 | 
| + private:
 | 
|    String* string_;
 | 
|    uint32_t hash_;
 | 
| +  DisallowHeapAllocation no_gc;
 | 
|  };
 | 
|  
 | 
|  
 | 
| @@ -725,12 +733,15 @@ HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj, int space) {
 | 
|        if (string->IsInternalizedString()) {
 | 
|          // Canonicalize the internalized string. If it already exists in the
 | 
|          // string table, set it to forward to the existing one.
 | 
| -        DisallowHeapAllocation no_gc;
 | 
| -        HandleScope scope(isolate_);
 | 
|          StringTableInsertionKey key(string);
 | 
| -        String* canonical = *StringTable::LookupKey(isolate_, &key);
 | 
| -        string->SetForwardedInternalizedString(canonical);
 | 
| -        return canonical;
 | 
| +        String* canonical = StringTable::LookupKeyIfExists(isolate_, &key);
 | 
| +        if (canonical == NULL) {
 | 
| +          new_internalized_strings_.Add(handle(string));
 | 
| +          return string;
 | 
| +        } else {
 | 
| +          string->SetForwardedInternalizedString(canonical);
 | 
| +          return canonical;
 | 
| +        }
 | 
|        }
 | 
|      } else if (obj->IsScript()) {
 | 
|        // Assign a new script id to avoid collision.
 | 
| @@ -767,6 +778,17 @@ HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj, int space) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void Deserializer::CommitNewInternalizedStrings(Isolate* isolate) {
 | 
| +  StringTable::EnsureCapacityForDeserialization(
 | 
| +      isolate, new_internalized_strings_.length());
 | 
| +  for (Handle<String> string : new_internalized_strings_) {
 | 
| +    StringTableInsertionKey key(*string);
 | 
| +    DCHECK_NULL(StringTable::LookupKeyIfExists(isolate, &key));
 | 
| +    StringTable::LookupKey(isolate, &key);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
|  HeapObject* Deserializer::GetBackReferencedObject(int space) {
 | 
|    HeapObject* obj;
 | 
|    BackReference back_reference(source_.GetInt());
 | 
| @@ -2348,8 +2370,6 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
 | 
|  void CodeSerializer::SerializeGeneric(HeapObject* heap_object,
 | 
|                                        HowToCode how_to_code,
 | 
|                                        WhereToPoint where_to_point) {
 | 
| -  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);
 | 
| @@ -2471,10 +2491,6 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
 | 
|          CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
 | 
|    }
 | 
|  
 | 
| -  // Eagerly expand string table to avoid allocations during deserialization.
 | 
| -  StringTable::EnsureCapacityForDeserialization(isolate,
 | 
| -                                                scd->NumInternalizedStrings());
 | 
| -
 | 
|    Deserializer deserializer(scd.get());
 | 
|    deserializer.SetAttachedObjects(attached_objects);
 | 
|  
 | 
| @@ -2633,7 +2649,6 @@ SerializedCodeData::SerializedCodeData(const List<byte>& payload,
 | 
|    SetHeaderValue(kCpuFeaturesOffset,
 | 
|                   static_cast<uint32_t>(CpuFeatures::SupportedFeatures()));
 | 
|    SetHeaderValue(kFlagHashOffset, FlagList::Hash());
 | 
| -  SetHeaderValue(kNumInternalizedStringsOffset, cs.num_internalized_strings());
 | 
|    SetHeaderValue(kNumReservationsOffset, reservations.length());
 | 
|    SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
 | 
|    SetHeaderValue(kPayloadLengthOffset, payload.length());
 | 
| @@ -2711,10 +2726,6 @@ Vector<const byte> SerializedCodeData::Payload() const {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -int SerializedCodeData::NumInternalizedStrings() const {
 | 
| -  return GetHeaderValue(kNumInternalizedStringsOffset);
 | 
| -}
 | 
| -
 | 
|  Vector<const uint32_t> SerializedCodeData::CodeStubKeys() const {
 | 
|    int reservations_size = GetHeaderValue(kNumReservationsOffset) * kInt32Size;
 | 
|    const byte* start = data_ + kHeaderSize + reservations_size;
 | 
| 
 |