| Index: runtime/vm/hash_table.h | 
| diff --git a/runtime/vm/hash_table.h b/runtime/vm/hash_table.h | 
| index 15317a17fa45d720af013076fb89fe779e63d276..8408f23e2eb12b8feb97b8a92b4e009419f3c309 100644 | 
| --- a/runtime/vm/hash_table.h | 
| +++ b/runtime/vm/hash_table.h | 
| @@ -85,23 +85,21 @@ template<typename KeyTraits, intptr_t kPayloadSize, intptr_t kMetaDataSize> | 
| class HashTable : public ValueObject { | 
| public: | 
| typedef KeyTraits Traits; | 
| +  // Uses the passed in handles for all handle operations. | 
| +  // 'Release' must be called at the end to obtain the final table | 
| +  // after potential growth/shrinkage. | 
| +  HashTable(Object* key, Smi* index, Array* data) | 
| +      : key_handle_(key), | 
| +        smi_handle_(index), | 
| +        data_(data), | 
| +        released_data_(NULL) {} | 
| // Uses 'zone' for handle allocation. 'Release' must be called at the end | 
| // to obtain the final table after potential growth/shrinkage. | 
| HashTable(Zone* zone, RawArray* data) | 
| -      : zone_(zone), | 
| -        key_handle_(Object::Handle(zone_)), | 
| -        smi_handle_(Smi::Handle(zone_)), | 
| -        data_(&Array::Handle(zone_, data)), | 
| +      : key_handle_(&Object::Handle(zone)), | 
| +        smi_handle_(&Smi::Handle(zone)), | 
| +        data_(&Array::Handle(zone, data)), | 
| released_data_(NULL) {} | 
| -  // Like above, except uses current zone. | 
| -  explicit HashTable(RawArray* data) | 
| -      : zone_(Thread::Current()->zone()), | 
| -        key_handle_(Object::Handle(zone_)), | 
| -        smi_handle_(Smi::Handle(zone_)), | 
| -        data_(&Array::Handle(zone_, data)), | 
| -        released_data_(NULL) { | 
| -    ASSERT(!data_->IsNull()); | 
| -  } | 
|  | 
| // Returns the final table. The handle is cleared when this HashTable is | 
| // destroyed. | 
| @@ -134,15 +132,15 @@ class HashTable : public ValueObject { | 
| // Initializes an empty table. | 
| void Initialize() const { | 
| ASSERT(data_->Length() >= ArrayLengthForNumOccupied(0)); | 
| -    smi_handle_ = Smi::New(0); | 
| -    data_->SetAt(kOccupiedEntriesIndex, smi_handle_); | 
| -    data_->SetAt(kDeletedEntriesIndex, smi_handle_); | 
| +    *smi_handle_ = Smi::New(0); | 
| +    data_->SetAt(kOccupiedEntriesIndex, *smi_handle_); | 
| +    data_->SetAt(kDeletedEntriesIndex, *smi_handle_); | 
|  | 
| NOT_IN_PRODUCT( | 
| -    data_->SetAt(kNumGrowsIndex, smi_handle_); | 
| -    data_->SetAt(kNumLT5LookupsIndex, smi_handle_); | 
| -    data_->SetAt(kNumLT25LookupsIndex, smi_handle_); | 
| -    data_->SetAt(kNumGT25LookupsIndex, smi_handle_); | 
| +    data_->SetAt(kNumGrowsIndex, *smi_handle_); | 
| +    data_->SetAt(kNumLT5LookupsIndex, *smi_handle_); | 
| +    data_->SetAt(kNumLT25LookupsIndex, *smi_handle_); | 
| +    data_->SetAt(kNumGT25LookupsIndex, *smi_handle_); | 
| )  // !PRODUCT | 
|  | 
| for (intptr_t i = kHeaderSize; i < data_->Length(); ++i) { | 
| @@ -171,8 +169,8 @@ NOT_IN_PRODUCT( | 
| NOT_IN_PRODUCT(UpdateCollisions(collisions);) | 
| return -1; | 
| } else if (!IsDeleted(probe)) { | 
| -        key_handle_ = GetKey(probe); | 
| -        if (KeyTraits::IsMatch(key, key_handle_)) { | 
| +        *key_handle_ = GetKey(probe); | 
| +        if (KeyTraits::IsMatch(key, *key_handle_)) { | 
| NOT_IN_PRODUCT(UpdateCollisions(collisions);) | 
| return probe; | 
| } | 
| @@ -210,8 +208,8 @@ NOT_IN_PRODUCT( | 
| deleted = probe; | 
| } | 
| } else { | 
| -        key_handle_ = GetKey(probe); | 
| -        if (KeyTraits::IsMatch(key, key_handle_)) { | 
| +        *key_handle_ = GetKey(probe); | 
| +        if (KeyTraits::IsMatch(key, *key_handle_)) { | 
| *entry = probe; | 
| NOT_IN_PRODUCT(UpdateCollisions(collisions);) | 
| return true; | 
| @@ -289,10 +287,10 @@ NOT_IN_PRODUCT( | 
| return GetSmiValueAt(kDeletedEntriesIndex); | 
| } | 
| Object& KeyHandle() const { | 
| -    return key_handle_; | 
| +    return *key_handle_; | 
| } | 
| Smi& SmiHandle() const { | 
| -    return smi_handle_; | 
| +    return *smi_handle_; | 
| } | 
|  | 
| NOT_IN_PRODUCT( | 
| @@ -376,24 +374,21 @@ NOT_IN_PRODUCT( | 
|  | 
| intptr_t GetSmiValueAt(intptr_t index) const { | 
| ASSERT(!data_->IsNull()); | 
| -    ASSERT(Object::Handle(zone(), data_->At(index)).IsSmi()); | 
| +    ASSERT(!data_->At(index)->IsHeapObject()); | 
| return Smi::Value(Smi::RawCast(data_->At(index))); | 
| } | 
|  | 
| void SetSmiValueAt(intptr_t index, intptr_t value) const { | 
| -    smi_handle_ = Smi::New(value); | 
| -    data_->SetAt(index, smi_handle_); | 
| +    *smi_handle_ = Smi::New(value); | 
| +    data_->SetAt(index, *smi_handle_); | 
| } | 
|  | 
| void AdjustSmiValueAt(intptr_t index, intptr_t delta) const { | 
| SetSmiValueAt(index, (GetSmiValueAt(index) + delta)); | 
| } | 
|  | 
| -  Zone* zone() const { return zone_; } | 
| - | 
| -  Zone* zone_; | 
| -  Object& key_handle_; | 
| -  Smi& smi_handle_; | 
| +  Object* key_handle_; | 
| +  Smi* smi_handle_; | 
| // Exactly one of these is non-NULL, depending on whether Release was called. | 
| Array* data_; | 
| Array* released_data_; | 
| @@ -408,9 +403,11 @@ class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> { | 
| public: | 
| typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable; | 
| static const intptr_t kPayloadSize = kUserPayloadSize; | 
| -  explicit UnorderedHashTable(RawArray* data) : BaseTable(data) {} | 
| -  UnorderedHashTable(Zone* zone, RawArray* data) | 
| -      : BaseTable(zone, data) {} | 
| +  explicit UnorderedHashTable(RawArray* data) | 
| +      : BaseTable(Thread::Current()->zone(), data) {} | 
| +  UnorderedHashTable(Zone* zone, RawArray* data) : BaseTable(zone, data) {} | 
| +  UnorderedHashTable(Object* key, Smi* value, Array* data) | 
| +      : BaseTable(key, value, data) {} | 
| // Note: Does not check for concurrent modification. | 
| class Iterator { | 
| public: | 
| @@ -447,9 +444,12 @@ class EnumIndexHashTable | 
| typedef HashTable<KeyTraits, kUserPayloadSize + 1, 1> BaseTable; | 
| static const intptr_t kPayloadSize = kUserPayloadSize; | 
| static const intptr_t kNextEnumIndex = BaseTable::kMetaDataIndex; | 
| +  EnumIndexHashTable(Object* key, Smi* value, Array* data) | 
| +      : BaseTable(key, value, data) {} | 
| EnumIndexHashTable(Zone* zone, RawArray* data) | 
| : BaseTable(zone, data) {} | 
| -  explicit EnumIndexHashTable(RawArray* data) : BaseTable(data) {} | 
| +  explicit EnumIndexHashTable(RawArray* data) | 
| +      : BaseTable(Thread::Current()->zone(), data) {} | 
| // Note: Does not check for concurrent modification. | 
| class Iterator { | 
| public: | 
| @@ -509,7 +509,7 @@ class HashTables : public AllStatic { | 
| template<typename Table> | 
| static RawArray* New(intptr_t initial_capacity, | 
| Heap::Space space = Heap::kNew) { | 
| -    Table table(Array::New( | 
| +    Table table(Thread::Current()->zone(), Array::New( | 
| Table::ArrayLengthForNumOccupied(initial_capacity), space)); | 
| table.Initialize(); | 
| return table.Release().raw(); | 
| @@ -517,7 +517,7 @@ class HashTables : public AllStatic { | 
|  | 
| template<typename Table> | 
| static RawArray* New(const Array& array) { | 
| -    Table table(array.raw()); | 
| +    Table table(Thread::Current()->zone(), array.raw()); | 
| table.Initialize(); | 
| return table.Release().raw(); | 
| } | 
| @@ -590,8 +590,11 @@ class HashTables : public AllStatic { | 
| template<typename BaseIterTable> | 
| class HashMap : public BaseIterTable { | 
| public: | 
| -  explicit HashMap(RawArray* data) : BaseIterTable(data) {} | 
| +  explicit HashMap(RawArray* data) | 
| +      : BaseIterTable(Thread::Current()->zone(), data) {} | 
| HashMap(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} | 
| +  HashMap(Object* key, Smi* value, Array* data) | 
| +      : BaseIterTable(key, value, data) {} | 
| template<typename Key> | 
| RawObject* GetOrNull(const Key& key, bool* present = NULL) const { | 
| intptr_t entry = BaseIterTable::FindKey(key); | 
| @@ -676,8 +679,11 @@ template<typename KeyTraits> | 
| class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > { | 
| public: | 
| typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap; | 
| -  explicit UnorderedHashMap(RawArray* data) : BaseMap(data) {} | 
| +  explicit UnorderedHashMap(RawArray* data) | 
| +      : BaseMap(Thread::Current()->zone(), data) {} | 
| UnorderedHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} | 
| +  UnorderedHashMap(Object* key, Smi* value, Array* data) | 
| +      : BaseMap(key, value, data) {} | 
| }; | 
|  | 
|  | 
| @@ -685,16 +691,22 @@ template<typename KeyTraits> | 
| class EnumIndexHashMap : public HashMap<EnumIndexHashTable<KeyTraits, 1> > { | 
| public: | 
| typedef HashMap<EnumIndexHashTable<KeyTraits, 1> > BaseMap; | 
| -  explicit EnumIndexHashMap(RawArray* data) : BaseMap(data) {} | 
| +  explicit EnumIndexHashMap(RawArray* data) | 
| +      : BaseMap(Thread::Current()->zone(), data) {} | 
| EnumIndexHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} | 
| +  EnumIndexHashMap(Object* key, Smi* value, Array* data) | 
| +      : BaseMap(key, value, data) {} | 
| }; | 
|  | 
|  | 
| template<typename BaseIterTable> | 
| class HashSet : public BaseIterTable { | 
| public: | 
| -  explicit HashSet(RawArray* data) : BaseIterTable(data) {} | 
| +  explicit HashSet(RawArray* data) | 
| +      : BaseIterTable(Thread::Current()->zone(), data) {} | 
| HashSet(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} | 
| +  HashSet(Object* key, Smi* value, Array* data) | 
| +      : BaseIterTable(key, value, data) {} | 
| bool Insert(const Object& key) { | 
| EnsureCapacity(); | 
| intptr_t entry = -1; | 
| @@ -770,10 +782,13 @@ template<typename KeyTraits> | 
| class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > { | 
| public: | 
| typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet; | 
| -  explicit UnorderedHashSet(RawArray* data) : BaseSet(data) { | 
| +  explicit UnorderedHashSet(RawArray* data) | 
| +      : BaseSet(Thread::Current()->zone(), data) { | 
| ASSERT(data != Array::null()); | 
| } | 
| UnorderedHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} | 
| +  UnorderedHashSet(Object* key, Smi* value, Array* data) | 
| +      : BaseSet(key, value, data) {} | 
| }; | 
|  | 
|  | 
| @@ -781,8 +796,11 @@ template<typename KeyTraits> | 
| class EnumIndexHashSet : public HashSet<EnumIndexHashTable<KeyTraits, 0> > { | 
| public: | 
| typedef HashSet<EnumIndexHashTable<KeyTraits, 0> > BaseSet; | 
| -  explicit EnumIndexHashSet(RawArray* data) : BaseSet(data) {} | 
| +  explicit EnumIndexHashSet(RawArray* data) | 
| +      : BaseSet(Thread::Current()->zone(), data) {} | 
| EnumIndexHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} | 
| +  EnumIndexHashSet(Object* key, Smi* value, Array* data) | 
| +      : BaseSet(key, value, data) {} | 
| }; | 
|  | 
| }  // namespace dart | 
|  |