Index: runtime/vm/clustered_snapshot.h |
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h |
index b2bdd0c6a28021d3ba689a1b346ffd7880013c62..6cf9c39e5b8e1bc83fc8a33cb04d619c78bc0b68 100644 |
--- a/runtime/vm/clustered_snapshot.h |
+++ b/runtime/vm/clustered_snapshot.h |
@@ -12,6 +12,7 @@ |
#include "vm/exceptions.h" |
#include "vm/globals.h" |
#include "vm/growable_array.h" |
+#include "vm/hash_map.h" |
#include "vm/heap.h" |
#include "vm/isolate.h" |
#include "vm/object.h" |
@@ -83,15 +84,34 @@ class DeserializationCluster : public ZoneAllocated { |
}; |
-enum { |
- kRefTagSize = 1, |
- kRefTagShift = 1, |
- kRefTagMask = 1, |
- kSmiRefTag = 0x0, |
- kHeapRefTag = 0x1, |
+class SmiObjectIdPair { |
+ public: |
+ SmiObjectIdPair() : smi_(NULL), id_(0) { } |
+ RawSmi* smi_; |
+ intptr_t id_; |
+ |
+ bool operator==(const SmiObjectIdPair& other) const { |
+ return (smi_ == other.smi_) && (id_ == other.id_); |
+ } |
+}; |
+ |
+ |
+class SmiObjectIdPairTrait { |
+ public: |
+ typedef RawSmi* Key; |
+ typedef intptr_t Value; |
+ typedef SmiObjectIdPair Pair; |
+ |
+ static Key KeyOf(Pair kv) { return kv.smi_; } |
+ static Value ValueOf(Pair kv) { return kv.id_; } |
+ static inline intptr_t Hashcode(Key key) { return Smi::Value(key); } |
+ static inline bool IsKeyEqual(Pair kv, Key key) { return kv.smi_ == key; } |
}; |
+typedef DirectChainedHashMap<SmiObjectIdPairTrait> SmiObjectIdMap; |
+ |
+ |
class Serializer : public StackResource { |
public: |
Serializer(Thread* thread, |
@@ -114,13 +134,36 @@ class Serializer : public StackResource { |
void AssignRef(RawObject* object) { |
ASSERT(next_ref_index_ != 0); |
- heap_->SetObjectId(object, next_ref_index_); |
- ASSERT(heap_->GetObjectId(object) == next_ref_index_); |
+ if (object->IsHeapObject()) { |
+ heap_->SetObjectId(object, next_ref_index_); |
+ ASSERT(heap_->GetObjectId(object) == next_ref_index_); |
+ } else { |
+ RawSmi* smi = Smi::RawCast(object); |
+ SmiObjectIdPair* existing_pair = smi_ids_.Lookup(smi); |
+ if (existing_pair != NULL) { |
+ ASSERT(existing_pair->id_ == 1); |
+ existing_pair->id_ = next_ref_index_; |
+ } else { |
+ SmiObjectIdPair new_pair; |
+ new_pair.smi_ = smi; |
+ new_pair.id_ = next_ref_index_; |
+ smi_ids_.Insert(new_pair); |
+ } |
+ } |
next_ref_index_++; |
} |
void Push(RawObject* object) { |
if (!object->IsHeapObject()) { |
+ RawSmi* smi = Smi::RawCast(object); |
+ if (smi_ids_.Lookup(smi) == NULL) { |
+ SmiObjectIdPair pair; |
+ pair.smi_ = smi; |
+ pair.id_ = 1; |
+ smi_ids_.Insert(pair); |
+ stack_.Add(object); |
+ num_written_objects_++; |
+ } |
return; |
} |
@@ -180,9 +223,12 @@ class Serializer : public StackResource { |
void WriteRef(RawObject* object) { |
if (!object->IsHeapObject()) { |
- ASSERT(static_cast<intptr_t>(kSmiRefTag) == |
- static_cast<intptr_t>(kSmiTag)); |
- Write<intptr_t>(reinterpret_cast<intptr_t>(object)); |
+ RawSmi* smi = Smi::RawCast(object); |
+ intptr_t id = smi_ids_.Lookup(smi)->id_; |
+ if (id == 0) { |
+ FATAL("Missing ref"); |
+ } |
+ Write<int32_t>(id); |
return; |
} |
@@ -200,7 +246,7 @@ class Serializer : public StackResource { |
} |
FATAL("Missing ref"); |
} |
- Write<intptr_t>((id << kRefTagShift) | kHeapRefTag); |
+ Write<int32_t>(id); |
} |
void WriteTokenPosition(TokenPosition pos) { |
@@ -234,6 +280,7 @@ class Serializer : public StackResource { |
intptr_t num_base_objects_; |
intptr_t num_written_objects_; |
intptr_t next_ref_index_; |
+ SmiObjectIdMap smi_ids_; |
DISALLOW_IMPLICIT_CONSTRUCTORS(Serializer); |
}; |
@@ -300,13 +347,8 @@ class Deserializer : public StackResource { |
} |
RawObject* ReadRef() { |
- intptr_t index = Read<intptr_t>(); |
- if ((index & kRefTagMask) == kSmiRefTag) { |
- ASSERT(static_cast<intptr_t>(kSmiRefTag) == |
- static_cast<intptr_t>(kSmiTag)); |
- return reinterpret_cast<RawSmi*>(index); |
- } |
- return Ref(index >> kRefTagShift); |
+ int32_t index = Read<int32_t>(); |
+ return Ref(index); |
} |
TokenPosition ReadTokenPosition() { |