Chromium Code Reviews| Index: runtime/vm/raw_object_snapshot.cc |
| diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc |
| index 27ec70df7f8bf49e65ec7b0e3f029a72bf6df90a..bc2570c547aca0b6631c207b828c8314ed8c1638 100644 |
| --- a/runtime/vm/raw_object_snapshot.cc |
| +++ b/runtime/vm/raw_object_snapshot.cc |
| @@ -2204,9 +2204,9 @@ void RawGrowableObjectArray::WriteTo(SnapshotWriter* writer, |
| RawLinkedHashMap* LinkedHashMap::ReadFrom(SnapshotReader* reader, |
| - intptr_t object_id, |
| - intptr_t tags, |
| - Snapshot::Kind kind) { |
| + intptr_t object_id, |
| + intptr_t tags, |
| + Snapshot::Kind kind) { |
| ASSERT(reader != NULL); |
| LinkedHashMap& map = LinkedHashMap::ZoneHandle( |
| @@ -2222,20 +2222,39 @@ RawLinkedHashMap* LinkedHashMap::ReadFrom(SnapshotReader* reader, |
| reader->AddBackRef(object_id, &map, kIsDeserialized); |
| // Set the object tags. |
| map.set_tags(tags); |
| - // Read and set the fields. |
| - intptr_t num_flds = (map.raw()->to() - map.raw()->from()); |
| - for (intptr_t i = 0; i <= num_flds; i++) { |
| - (*reader->PassiveObjectHandle()) = reader->ReadObjectRef(); |
| - map.StorePointer((map.raw()->from() + i), |
| - reader->PassiveObjectHandle()->raw()); |
| + |
|
siva
2015/06/01 22:19:36
Maybe add comments here to match the comments on t
koda
2015/06/01 23:01:01
Done.
|
| + *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl(); |
| + map.SetTypeArguments(*reader->TypeArgumentsHandle()); |
| + |
| + intptr_t len = reader->ReadSmiValue(); |
| + intptr_t used_data = (len << 1); |
| + map.SetUsedData(used_data); |
| + map.SetDeletedKeys(0); |
| + intptr_t index_size = Utils::Maximum(Utils::RoundUpToPowerOfTwo(used_data), |
| + static_cast<unsigned int>(16)); |
| + Array& data = *reader->ArrayHandle(); |
| + data = Array::New(index_size, HEAP_SPACE(kind)); |
| + map.SetData(data); |
| + // The index and hashMask is regenerated by the maps themselves on demand. |
| + // Thus, the index will probably be allocated in new space (unless it's huge). |
| + // TODO(koda): Eagerly rehash here when no keys have user-defined '==', and |
| + // in particular, if/when (const) maps are needed in the VM isolate snapshot. |
|
siva
2015/06/01 22:19:36
We need an assertion to make sure we don't write t
koda
2015/06/01 23:01:01
Added an explicit assertion here, for documentatio
|
| + map.SetHashMask(0); // Prefer sentinel 0 over null for better type feedback. |
| + |
| + // Read the keys and values. |
| + bool is_canonical = RawObject::IsCanonical(tags); |
| + for (intptr_t i = 0; i < used_data; i++) { |
| + *reader->PassiveObjectHandle() = |
| + is_canonical ? reader->ReadObjectImpl() : reader->ReadObjectRef(); |
| + data.SetAt(i, *reader->PassiveObjectHandle()); |
| } |
| return map.raw(); |
| } |
| void RawLinkedHashMap::WriteTo(SnapshotWriter* writer, |
| - intptr_t object_id, |
| - Snapshot::Kind kind) { |
| + intptr_t object_id, |
| + Snapshot::Kind kind) { |
| if (kind == Snapshot::kFull || kind == Snapshot::kScript) { |
| // The immutable maps that seed map literals are not yet VM-internal, so |
| // we don't reach this. |
| @@ -2248,14 +2267,45 @@ void RawLinkedHashMap::WriteTo(SnapshotWriter* writer, |
| // Write out the class and tags information. |
| writer->WriteIndexedObject(kLinkedHashMapCid); |
| - writer->WriteTags(writer->GetObjectTags(this)); |
| + const uword tags = writer->GetObjectTags(this); |
| + writer->WriteTags(tags); |
| - // Write out all the object pointer fields. |
| - // TODO(koda): Serialize only used parts of data_ (after compaction), to |
| - // reduce space and support per-isolate salted hash codes. All allowed keys |
| - // have types for which we can rehash without running Dart code. |
| - SnapshotWriterVisitor visitor(writer); |
| - visitor.VisitPointers(from(), to()); |
| + // Write out the type arguments. |
| + writer->WriteObjectImpl(ptr()->type_arguments_); |
| + |
| + const intptr_t used_data = Smi::Value(ptr()->used_data_); |
| + ASSERT((used_data & 1) == 0); // Keys + values, so must be even. |
| + const intptr_t deleted_keys = Smi::Value(ptr()->deleted_keys_); |
| + |
| + // Write out the number of (not deleted) key/value pairs that will follow. |
| + writer->Write<RawObject*>(Smi::New((used_data >> 1) - deleted_keys)); |
| + |
| + // Write out the keys and values. |
| + const bool is_canonical = RawObject::IsCanonical(tags); |
| + RawArray* data_array = ptr()->data_; |
| + RawObject** data_elements = data_array->ptr()->data(); |
| + ASSERT(used_data <= Smi::Value(data_array->ptr()->length_)); |
| +#if defined(DEBUG) |
| + intptr_t deleted_keys_found = 0; |
| +#endif // DEBUG |
| + for (intptr_t i = 0; i < used_data; i += 2) { |
| + RawObject* key = data_elements[i]; |
| + if (key == data_array) { |
| +#if defined(DEBUG) |
| + ++deleted_keys_found; |
| +#endif // DEBUG |
| + continue; |
| + } |
| + RawObject* value = data_elements[i + 1]; |
| + if (is_canonical) { |
| + writer->WriteObjectImpl(key); |
| + writer->WriteObjectImpl(value); |
| + } else { |
| + writer->WriteObjectRef(key); |
| + writer->WriteObjectRef(value); |
| + } |
| + } |
| + ASSERT(deleted_keys_found == deleted_keys); |
| } |