| Index: src/serialize.cc
|
| diff --git a/src/serialize.cc b/src/serialize.cc
|
| index 89ba1be099afc6d9a295907b54d002c7711fa5f6..fe84894ef6f780dd7c2211e4483db5050692aa96 100644
|
| --- a/src/serialize.cc
|
| +++ b/src/serialize.cc
|
| @@ -718,6 +718,7 @@ class CodeAddressMap: public CodeEventLogger {
|
|
|
| Deserializer::Deserializer(SnapshotByteSource* source)
|
| : isolate_(NULL),
|
| + deserialize_code_(false),
|
| source_(source),
|
| external_reference_decoder_(NULL) {
|
| for (int i = 0; i < LAST_SPACE + 1; i++) {
|
| @@ -832,6 +833,54 @@ void Deserializer::RelinkAllocationSite(AllocationSite* site) {
|
| }
|
|
|
|
|
| +// Used to insert a deserialized internalized string into the string table.
|
| +class StringTableInsertionKey : public HashTableKey {
|
| + public:
|
| + explicit StringTableInsertionKey(String* string)
|
| + : string_(string), hash_(HashForObject(string)) {
|
| + ASSERT(string->IsInternalizedString());
|
| + }
|
| +
|
| + virtual bool IsMatch(Object* string) {
|
| + // We know that all entries in a hash table had their hash keys created.
|
| + // Use that knowledge to have fast failure.
|
| + if (hash_ != HashForObject(string)) return false;
|
| + // We want to compare the content of two internalized strings here.
|
| + return string_->SlowEquals(String::cast(string));
|
| + }
|
| +
|
| + virtual uint32_t Hash() V8_OVERRIDE { return hash_; }
|
| +
|
| + virtual uint32_t HashForObject(Object* key) V8_OVERRIDE {
|
| + return String::cast(key)->Hash();
|
| + }
|
| +
|
| + MUST_USE_RESULT virtual Handle<Object> AsHandle(Isolate* isolate)
|
| + V8_OVERRIDE {
|
| + return handle(string_, isolate);
|
| + }
|
| +
|
| + String* string_;
|
| + uint32_t hash_;
|
| +};
|
| +
|
| +
|
| +HeapObject* Deserializer::ProcessObjectFromSerializedCode(HeapObject* obj) {
|
| + if (obj->IsString()) {
|
| + String* string = String::cast(obj);
|
| + // Uninitialize hash field as the hash seed may have changed.
|
| + string->set_hash_field(String::kEmptyHashField);
|
| + if (string->IsInternalizedString()) {
|
| + DisallowHeapAllocation no_gc;
|
| + HandleScope scope(isolate_);
|
| + StringTableInsertionKey key(string);
|
| + return *StringTable::LookupKey(isolate_, &key);
|
| + }
|
| + }
|
| + return obj;
|
| +}
|
| +
|
| +
|
| // This routine writes the new object into the pointer provided and then
|
| // returns true if the new object was in young space and false otherwise.
|
| // The reason for this strange interface is that otherwise the object is
|
| @@ -843,7 +892,6 @@ void Deserializer::ReadObject(int space_number,
|
| Address address = Allocate(space_number, size);
|
| HeapObject* obj = HeapObject::FromAddress(address);
|
| isolate_->heap()->OnAllocationEvent(obj, size);
|
| - *write_back = obj;
|
| Object** current = reinterpret_cast<Object**>(address);
|
| Object** limit = current + (size >> kPointerSizeLog2);
|
| if (FLAG_log_snapshot_positions) {
|
| @@ -854,10 +902,12 @@ void Deserializer::ReadObject(int space_number,
|
| // TODO(mvstanton): consider treating the heap()->allocation_sites_list()
|
| // as a (weak) root. If this root is relocated correctly,
|
| // RelinkAllocationSite() isn't necessary.
|
| - if (obj->IsAllocationSite()) {
|
| - RelinkAllocationSite(AllocationSite::cast(obj));
|
| - }
|
| + if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj));
|
| +
|
| + // Fix up strings from serialized user code.
|
| + if (deserialize_code_) obj = ProcessObjectFromSerializedCode(obj);
|
|
|
| + *write_back = obj;
|
| #ifdef DEBUG
|
| bool is_codespace = (space_number == CODE_SPACE);
|
| ASSERT(obj->IsCode() == is_codespace);
|
| @@ -921,13 +971,13 @@ void Deserializer::ReadChunk(Object** current,
|
| emit_write_barrier = (space_number == NEW_SPACE); \
|
| new_object = GetAddressFromEnd(data & kSpaceMask); \
|
| } else if (where == kBuiltin) { \
|
| + ASSERT(deserialize_code_); \
|
| int builtin_id = source_->GetInt(); \
|
| ASSERT_LE(0, builtin_id); \
|
| ASSERT_LT(builtin_id, Builtins::builtin_count); \
|
| Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \
|
| new_object = isolate->builtins()->builtin(name); \
|
| emit_write_barrier = false; \
|
| - PrintF("BUILTIN how within %d, %d\n", how, within); \
|
| } else { \
|
| ASSERT(where == kBackrefWithSkip); \
|
| int skip = source_->GetInt(); \
|
| @@ -1859,8 +1909,6 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
|
|
| // TODO(yangguo) wire up stubs from stub cache.
|
| // TODO(yangguo) wire up script source.
|
| - // TODO(yangguo) wire up internalized strings
|
| - ASSERT(!heap_object->IsInternalizedString());
|
| // TODO(yangguo) We cannot deal with different hash seeds yet.
|
| ASSERT(!heap_object->IsHashTable());
|
|
|
| @@ -1916,6 +1964,7 @@ Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) {
|
| SerializedCodeData scd(data);
|
| SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
|
| Deserializer deserializer(&payload);
|
| + deserializer.ExpectSerializedCode();
|
| STATIC_ASSERT(NEW_SPACE == 0);
|
| // TODO(yangguo) what happens if remaining new space is too small?
|
| for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
|
|
|