Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(527)

Side by Side Diff: runtime/vm/hash_table.h

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/hash_map_test.cc ('k') | runtime/vm/hash_table_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef RUNTIME_VM_HASH_TABLE_H_ 5 #ifndef RUNTIME_VM_HASH_TABLE_H_
6 #define RUNTIME_VM_HASH_TABLE_H_ 6 #define RUNTIME_VM_HASH_TABLE_H_
7 7
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/object.h" 9 #include "vm/object.h"
10 10
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 // The header tracks the number of entries in each state. 65 // The header tracks the number of entries in each state.
66 // Any object except Object::sentinel() and Object::transition_sentinel() 66 // Any object except Object::sentinel() and Object::transition_sentinel()
67 // may be stored as a key. Any object may be stored in a payload. 67 // may be stored as a key. Any object may be stored in a payload.
68 // 68 //
69 // Parameters 69 // Parameters
70 // KeyTraits: defines static methods 70 // KeyTraits: defines static methods
71 // bool IsMatch(const Key& key, const Object& obj) and 71 // bool IsMatch(const Key& key, const Object& obj) and
72 // uword Hash(const Key& key) for any number of desired lookup key types. 72 // uword Hash(const Key& key) for any number of desired lookup key types.
73 // kPayloadSize: number of components of the payload in each entry. 73 // kPayloadSize: number of components of the payload in each entry.
74 // kMetaDataSize: number of elements reserved (e.g., for iteration order data). 74 // kMetaDataSize: number of elements reserved (e.g., for iteration order data).
75 template<typename KeyTraits, intptr_t kPayloadSize, intptr_t kMetaDataSize> 75 template <typename KeyTraits, intptr_t kPayloadSize, intptr_t kMetaDataSize>
76 class HashTable : public ValueObject { 76 class HashTable : public ValueObject {
77 public: 77 public:
78 typedef KeyTraits Traits; 78 typedef KeyTraits Traits;
79 // Uses the passed in handles for all handle operations. 79 // Uses the passed in handles for all handle operations.
80 // 'Release' must be called at the end to obtain the final table 80 // 'Release' must be called at the end to obtain the final table
81 // after potential growth/shrinkage. 81 // after potential growth/shrinkage.
82 HashTable(Object* key, Smi* index, Array* data) 82 HashTable(Object* key, Smi* index, Array* data)
83 : key_handle_(key), 83 : key_handle_(key),
84 smi_handle_(index), 84 smi_handle_(index),
85 data_(data), 85 data_(data),
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 return kFirstKeyIndex + (kEntrySize * num_entries); 120 return kFirstKeyIndex + (kEntrySize * num_entries);
121 } 121 }
122 122
123 // Initializes an empty table. 123 // Initializes an empty table.
124 void Initialize() const { 124 void Initialize() const {
125 ASSERT(data_->Length() >= ArrayLengthForNumOccupied(0)); 125 ASSERT(data_->Length() >= ArrayLengthForNumOccupied(0));
126 *smi_handle_ = Smi::New(0); 126 *smi_handle_ = Smi::New(0);
127 data_->SetAt(kOccupiedEntriesIndex, *smi_handle_); 127 data_->SetAt(kOccupiedEntriesIndex, *smi_handle_);
128 data_->SetAt(kDeletedEntriesIndex, *smi_handle_); 128 data_->SetAt(kDeletedEntriesIndex, *smi_handle_);
129 129
130 NOT_IN_PRODUCT( 130 #if !defined(PRODUCT)
131 data_->SetAt(kNumGrowsIndex, *smi_handle_); 131 data_->SetAt(kNumGrowsIndex, *smi_handle_);
132 data_->SetAt(kNumLT5LookupsIndex, *smi_handle_); 132 data_->SetAt(kNumLT5LookupsIndex, *smi_handle_);
133 data_->SetAt(kNumLT25LookupsIndex, *smi_handle_); 133 data_->SetAt(kNumLT25LookupsIndex, *smi_handle_);
134 data_->SetAt(kNumGT25LookupsIndex, *smi_handle_); 134 data_->SetAt(kNumGT25LookupsIndex, *smi_handle_);
135 ) // !PRODUCT 135 #endif // !defined(PRODUCT)
136 136
137 for (intptr_t i = kHeaderSize; i < data_->Length(); ++i) { 137 for (intptr_t i = kHeaderSize; i < data_->Length(); ++i) {
138 data_->SetAt(i, Object::sentinel()); 138 data_->SetAt(i, Object::sentinel());
139 } 139 }
140 } 140 }
141 141
142 // Returns whether 'key' matches any key in the table. 142 // Returns whether 'key' matches any key in the table.
143 template<typename Key> 143 template <typename Key>
144 bool ContainsKey(const Key& key) const { 144 bool ContainsKey(const Key& key) const {
145 return FindKey(key) != -1; 145 return FindKey(key) != -1;
146 } 146 }
147 147
148 // Returns the entry that matches 'key', or -1 if none exists. 148 // Returns the entry that matches 'key', or -1 if none exists.
149 template<typename Key> 149 template <typename Key>
150 intptr_t FindKey(const Key& key) const { 150 intptr_t FindKey(const Key& key) const {
151 const intptr_t num_entries = NumEntries(); 151 const intptr_t num_entries = NumEntries();
152 ASSERT(NumOccupied() < num_entries); 152 ASSERT(NumOccupied() < num_entries);
153 // TODO(koda): Add salt. 153 // TODO(koda): Add salt.
154 NOT_IN_PRODUCT(intptr_t collisions = 0;) 154 NOT_IN_PRODUCT(intptr_t collisions = 0;)
155 uword hash = KeyTraits::Hash(key); 155 uword hash = KeyTraits::Hash(key);
156 intptr_t probe = hash % num_entries; 156 intptr_t probe = hash % num_entries;
157 // TODO(koda): Consider quadratic probing. 157 // TODO(koda): Consider quadratic probing.
158 while (true) { 158 while (true) {
159 if (IsUnused(probe)) { 159 if (IsUnused(probe)) {
(...skipping 12 matching lines...) Expand all
172 probe = (probe == num_entries) ? 0 : probe; 172 probe = (probe == num_entries) ? 0 : probe;
173 } 173 }
174 UNREACHABLE(); 174 UNREACHABLE();
175 return -1; 175 return -1;
176 } 176 }
177 177
178 // Sets *entry to either: 178 // Sets *entry to either:
179 // - an occupied entry matching 'key', and returns true, or 179 // - an occupied entry matching 'key', and returns true, or
180 // - an unused/deleted entry where a matching key may be inserted, 180 // - an unused/deleted entry where a matching key may be inserted,
181 // and returns false. 181 // and returns false.
182 template<typename Key> 182 template <typename Key>
183 bool FindKeyOrDeletedOrUnused(const Key& key, intptr_t* entry) const { 183 bool FindKeyOrDeletedOrUnused(const Key& key, intptr_t* entry) const {
184 const intptr_t num_entries = NumEntries(); 184 const intptr_t num_entries = NumEntries();
185 ASSERT(entry != NULL); 185 ASSERT(entry != NULL);
186 ASSERT(NumOccupied() < num_entries); 186 ASSERT(NumOccupied() < num_entries);
187 NOT_IN_PRODUCT(intptr_t collisions = 0;) 187 NOT_IN_PRODUCT(intptr_t collisions = 0;)
188 uword hash = KeyTraits::Hash(key); 188 uword hash = KeyTraits::Hash(key);
189 intptr_t probe = hash % num_entries; 189 intptr_t probe = hash % num_entries;
190 intptr_t deleted = -1; 190 intptr_t deleted = -1;
191 // TODO(koda): Consider quadratic probing. 191 // TODO(koda): Consider quadratic probing.
192 while (true) { 192 while (true) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 InternalSetKey(entry, Object::transition_sentinel()); 264 InternalSetKey(entry, Object::transition_sentinel());
265 AdjustSmiValueAt(kOccupiedEntriesIndex, -1); 265 AdjustSmiValueAt(kOccupiedEntriesIndex, -1);
266 AdjustSmiValueAt(kDeletedEntriesIndex, 1); 266 AdjustSmiValueAt(kDeletedEntriesIndex, 1);
267 } 267 }
268 intptr_t NumEntries() const { 268 intptr_t NumEntries() const {
269 return (data_->Length() - kFirstKeyIndex) / kEntrySize; 269 return (data_->Length() - kFirstKeyIndex) / kEntrySize;
270 } 270 }
271 intptr_t NumUnused() const { 271 intptr_t NumUnused() const {
272 return NumEntries() - NumOccupied() - NumDeleted(); 272 return NumEntries() - NumOccupied() - NumDeleted();
273 } 273 }
274 intptr_t NumOccupied() const { 274 intptr_t NumOccupied() const { return GetSmiValueAt(kOccupiedEntriesIndex); }
275 return GetSmiValueAt(kOccupiedEntriesIndex); 275 intptr_t NumDeleted() const { return GetSmiValueAt(kDeletedEntriesIndex); }
276 } 276 Object& KeyHandle() const { return *key_handle_; }
277 intptr_t NumDeleted() const { 277 Smi& SmiHandle() const { return *smi_handle_; }
278 return GetSmiValueAt(kDeletedEntriesIndex);
279 }
280 Object& KeyHandle() const {
281 return *key_handle_;
282 }
283 Smi& SmiHandle() const {
284 return *smi_handle_;
285 }
286 278
287 NOT_IN_PRODUCT( 279 #if !defined(PRODUCT)
288 intptr_t NumGrows() const { 280 intptr_t NumGrows() const { return GetSmiValueAt(kNumGrowsIndex); }
289 return GetSmiValueAt(kNumGrowsIndex);
290 }
291 intptr_t NumLT5Collisions() const { 281 intptr_t NumLT5Collisions() const {
292 return GetSmiValueAt(kNumLT5LookupsIndex); 282 return GetSmiValueAt(kNumLT5LookupsIndex);
293 } 283 }
294 intptr_t NumLT25Collisions() const { 284 intptr_t NumLT25Collisions() const {
295 return GetSmiValueAt(kNumLT25LookupsIndex); 285 return GetSmiValueAt(kNumLT25LookupsIndex);
296 } 286 }
297 intptr_t NumGT25Collisions() const { 287 intptr_t NumGT25Collisions() const {
298 return GetSmiValueAt(kNumGT25LookupsIndex); 288 return GetSmiValueAt(kNumGT25LookupsIndex);
299 } 289 }
300 void UpdateGrowth() const { 290 void UpdateGrowth() const { AdjustSmiValueAt(kNumGrowsIndex, 1); }
301 AdjustSmiValueAt(kNumGrowsIndex, 1);
302 }
303 void UpdateCollisions(intptr_t collisions) const { 291 void UpdateCollisions(intptr_t collisions) const {
304 if (data_->raw()->IsVMHeapObject()) { 292 if (data_->raw()->IsVMHeapObject()) {
305 return; 293 return;
306 } 294 }
307 if (collisions < 5) { 295 if (collisions < 5) {
308 AdjustSmiValueAt(kNumLT5LookupsIndex, 1); 296 AdjustSmiValueAt(kNumLT5LookupsIndex, 1);
309 } else if (collisions < 25) { 297 } else if (collisions < 25) {
310 AdjustSmiValueAt(kNumLT25LookupsIndex, 1); 298 AdjustSmiValueAt(kNumLT25LookupsIndex, 1);
311 } else { 299 } else {
312 AdjustSmiValueAt(kNumGT25LookupsIndex, 1); 300 AdjustSmiValueAt(kNumGT25LookupsIndex, 1);
313 } 301 }
314 } 302 }
315 void PrintStats() const { 303 void PrintStats() const {
316 if (!KeyTraits::ReportStats()) { 304 if (!KeyTraits::ReportStats()) {
317 return; 305 return;
318 } 306 }
307 // clang-format off
319 OS::Print("Stats for %s table :\n" 308 OS::Print("Stats for %s table :\n"
320 " Size of table = %" Pd ",Number of Occupied entries = %" Pd "\n" 309 " Size of table = %" Pd ",Number of Occupied entries = %" Pd "\n"
321 " Number of Grows = %" Pd "\n" 310 " Number of Grows = %" Pd "\n"
322 " Number of look ups with < 5 collisions = %" Pd "\n" 311 " Number of look ups with < 5 collisions = %" Pd "\n"
323 " Number of look ups with < 25 collisions = %" Pd "\n" 312 " Number of look ups with < 25 collisions = %" Pd "\n"
324 " Number of look ups with > 25 collisions = %" Pd "\n", 313 " Number of look ups with > 25 collisions = %" Pd "\n",
325 KeyTraits::Name(), 314 KeyTraits::Name(),
326 NumEntries(), NumOccupied(), 315 NumEntries(), NumOccupied(),
327 NumGrows(), 316 NumGrows(),
328 NumLT5Collisions(), NumLT25Collisions(), NumGT25Collisions()); 317 NumLT5Collisions(), NumLT25Collisions(), NumGT25Collisions());
318 // clang-format on
329 } 319 }
330 ) // !PRODUCT 320 #endif // !PRODUCT
331 321
332 protected: 322 protected:
333 static const intptr_t kOccupiedEntriesIndex = 0; 323 static const intptr_t kOccupiedEntriesIndex = 0;
334 static const intptr_t kDeletedEntriesIndex = 1; 324 static const intptr_t kDeletedEntriesIndex = 1;
335 #if defined(PRODUCT) 325 #if defined(PRODUCT)
336 static const intptr_t kHeaderSize = kDeletedEntriesIndex + 1; 326 static const intptr_t kHeaderSize = kDeletedEntriesIndex + 1;
337 #else 327 #else
338 static const intptr_t kNumGrowsIndex = 2; 328 static const intptr_t kNumGrowsIndex = 2;
339 static const intptr_t kNumLT5LookupsIndex = 3; 329 static const intptr_t kNumLT5LookupsIndex = 3;
340 static const intptr_t kNumLT25LookupsIndex = 4; 330 static const intptr_t kNumLT25LookupsIndex = 4;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 Smi* smi_handle_; 372 Smi* smi_handle_;
383 // Exactly one of these is non-NULL, depending on whether Release was called. 373 // Exactly one of these is non-NULL, depending on whether Release was called.
384 Array* data_; 374 Array* data_;
385 Array* released_data_; 375 Array* released_data_;
386 376
387 friend class HashTables; 377 friend class HashTables;
388 }; 378 };
389 379
390 380
391 // Table with unspecified iteration order. No payload overhead or metadata. 381 // Table with unspecified iteration order. No payload overhead or metadata.
392 template<typename KeyTraits, intptr_t kUserPayloadSize> 382 template <typename KeyTraits, intptr_t kUserPayloadSize>
393 class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> { 383 class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> {
394 public: 384 public:
395 typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable; 385 typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable;
396 static const intptr_t kPayloadSize = kUserPayloadSize; 386 static const intptr_t kPayloadSize = kUserPayloadSize;
397 explicit UnorderedHashTable(RawArray* data) 387 explicit UnorderedHashTable(RawArray* data)
398 : BaseTable(Thread::Current()->zone(), data) {} 388 : BaseTable(Thread::Current()->zone(), data) {}
399 UnorderedHashTable(Zone* zone, RawArray* data) : BaseTable(zone, data) {} 389 UnorderedHashTable(Zone* zone, RawArray* data) : BaseTable(zone, data) {}
400 UnorderedHashTable(Object* key, Smi* value, Array* data) 390 UnorderedHashTable(Object* key, Smi* value, Array* data)
401 : BaseTable(key, value, data) {} 391 : BaseTable(key, value, data) {}
402 // Note: Does not check for concurrent modification. 392 // Note: Does not check for concurrent modification.
403 class Iterator { 393 class Iterator {
404 public: 394 public:
405 explicit Iterator(const UnorderedHashTable* table) 395 explicit Iterator(const UnorderedHashTable* table)
406 : table_(table), entry_(-1) {} 396 : table_(table), entry_(-1) {}
407 bool MoveNext() { 397 bool MoveNext() {
408 while (entry_ < (table_->NumEntries() - 1)) { 398 while (entry_ < (table_->NumEntries() - 1)) {
409 ++entry_; 399 ++entry_;
410 if (table_->IsOccupied(entry_)) { 400 if (table_->IsOccupied(entry_)) {
411 return true; 401 return true;
412 } 402 }
413 } 403 }
414 return false; 404 return false;
415 } 405 }
416 intptr_t Current() { 406 intptr_t Current() { return entry_; }
417 return entry_;
418 }
419 407
420 private: 408 private:
421 const UnorderedHashTable* table_; 409 const UnorderedHashTable* table_;
422 intptr_t entry_; 410 intptr_t entry_;
423 }; 411 };
424 412
425 // No extra book-keeping needed for Initialize, InsertKey, DeleteEntry. 413 // No extra book-keeping needed for Initialize, InsertKey, DeleteEntry.
426 }; 414 };
427 415
428 416
429 class HashTables : public AllStatic { 417 class HashTables : public AllStatic {
430 public: 418 public:
431 // Allocates and initializes a table. 419 // Allocates and initializes a table.
432 template<typename Table> 420 template <typename Table>
433 static RawArray* New(intptr_t initial_capacity, 421 static RawArray* New(intptr_t initial_capacity,
434 Heap::Space space = Heap::kNew) { 422 Heap::Space space = Heap::kNew) {
435 Table table(Thread::Current()->zone(), Array::New( 423 Table table(
436 Table::ArrayLengthForNumOccupied(initial_capacity), space)); 424 Thread::Current()->zone(),
425 Array::New(Table::ArrayLengthForNumOccupied(initial_capacity), space));
437 table.Initialize(); 426 table.Initialize();
438 return table.Release().raw(); 427 return table.Release().raw();
439 } 428 }
440 429
441 template<typename Table> 430 template <typename Table>
442 static RawArray* New(const Array& array) { 431 static RawArray* New(const Array& array) {
443 Table table(Thread::Current()->zone(), array.raw()); 432 Table table(Thread::Current()->zone(), array.raw());
444 table.Initialize(); 433 table.Initialize();
445 return table.Release().raw(); 434 return table.Release().raw();
446 } 435 }
447 436
448 // Clears 'to' and inserts all elements from 'from', in iteration order. 437 // Clears 'to' and inserts all elements from 'from', in iteration order.
449 // The tables must have the same user payload size. 438 // The tables must have the same user payload size.
450 template<typename From, typename To> 439 template <typename From, typename To>
451 static void Copy(const From& from, const To& to) { 440 static void Copy(const From& from, const To& to) {
452 COMPILE_ASSERT(From::kPayloadSize == To::kPayloadSize); 441 COMPILE_ASSERT(From::kPayloadSize == To::kPayloadSize);
453 to.Initialize(); 442 to.Initialize();
454 ASSERT(from.NumOccupied() < to.NumEntries()); 443 ASSERT(from.NumOccupied() < to.NumEntries());
455 typename From::Iterator it(&from); 444 typename From::Iterator it(&from);
456 Object& obj = Object::Handle(); 445 Object& obj = Object::Handle();
457 while (it.MoveNext()) { 446 while (it.MoveNext()) {
458 intptr_t from_entry = it.Current(); 447 intptr_t from_entry = it.Current();
459 obj = from.GetKey(from_entry); 448 obj = from.GetKey(from_entry);
460 intptr_t to_entry = -1; 449 intptr_t to_entry = -1;
461 const Object& key = obj; 450 const Object& key = obj;
462 bool present = to.FindKeyOrDeletedOrUnused(key, &to_entry); 451 bool present = to.FindKeyOrDeletedOrUnused(key, &to_entry);
463 ASSERT(!present); 452 ASSERT(!present);
464 to.InsertKey(to_entry, obj); 453 to.InsertKey(to_entry, obj);
465 for (intptr_t i = 0; i < From::kPayloadSize; ++i) { 454 for (intptr_t i = 0; i < From::kPayloadSize; ++i) {
466 obj = from.GetPayload(from_entry, i); 455 obj = from.GetPayload(from_entry, i);
467 to.UpdatePayload(to_entry, i, obj); 456 to.UpdatePayload(to_entry, i, obj);
468 } 457 }
469 } 458 }
470 } 459 }
471 460
472 template<typename Table> 461 template <typename Table>
473 static void EnsureLoadFactor(double low, double high, const Table& table) { 462 static void EnsureLoadFactor(double low, double high, const Table& table) {
474 double current = (1 + table.NumOccupied() + table.NumDeleted()) / 463 double current = (1 + table.NumOccupied() + table.NumDeleted()) /
475 static_cast<double>(table.NumEntries()); 464 static_cast<double>(table.NumEntries());
476 if (low <= current && current < high) { 465 if (low <= current && current < high) {
477 return; 466 return;
478 } 467 }
479 double target = (low + high) / 2.0; 468 double target = (low + high) / 2.0;
480 intptr_t new_capacity = (1 + table.NumOccupied()) / target; 469 intptr_t new_capacity = (1 + table.NumOccupied()) / target;
481 Table new_table(New<Table>( 470 Table new_table(New<Table>(new_capacity,
482 new_capacity, 471 table.data_->IsOld() ? Heap::kOld : Heap::kNew));
483 table.data_->IsOld() ? Heap::kOld : Heap::kNew));
484 Copy(table, new_table); 472 Copy(table, new_table);
485 *table.data_ = new_table.Release().raw(); 473 *table.data_ = new_table.Release().raw();
486 NOT_IN_PRODUCT(table.UpdateGrowth(); table.PrintStats();) 474 NOT_IN_PRODUCT(table.UpdateGrowth(); table.PrintStats();)
487 } 475 }
488 476
489 // Serializes a table by concatenating its entries as an array. 477 // Serializes a table by concatenating its entries as an array.
490 template<typename Table> 478 template <typename Table>
491 static RawArray* ToArray(const Table& table, bool include_payload) { 479 static RawArray* ToArray(const Table& table, bool include_payload) {
492 const intptr_t entry_size = include_payload ? (1 + Table::kPayloadSize) : 1; 480 const intptr_t entry_size = include_payload ? (1 + Table::kPayloadSize) : 1;
493 Array& result = Array::Handle(Array::New(table.NumOccupied() * entry_size)); 481 Array& result = Array::Handle(Array::New(table.NumOccupied() * entry_size));
494 typename Table::Iterator it(&table); 482 typename Table::Iterator it(&table);
495 Object& obj = Object::Handle(); 483 Object& obj = Object::Handle();
496 intptr_t result_index = 0; 484 intptr_t result_index = 0;
497 while (it.MoveNext()) { 485 while (it.MoveNext()) {
498 intptr_t entry = it.Current(); 486 intptr_t entry = it.Current();
499 obj = table.GetKey(entry); 487 obj = table.GetKey(entry);
500 result.SetAt(result_index++, obj); 488 result.SetAt(result_index++, obj);
501 if (include_payload) { 489 if (include_payload) {
502 for (intptr_t i = 0; i < Table::kPayloadSize; ++i) { 490 for (intptr_t i = 0; i < Table::kPayloadSize; ++i) {
503 obj = table.GetPayload(entry, i); 491 obj = table.GetPayload(entry, i);
504 result.SetAt(result_index++, obj); 492 result.SetAt(result_index++, obj);
505 } 493 }
506 } 494 }
507 } 495 }
508 return result.raw(); 496 return result.raw();
509 } 497 }
510 }; 498 };
511 499
512 500
513 template<typename BaseIterTable> 501 template <typename BaseIterTable>
514 class HashMap : public BaseIterTable { 502 class HashMap : public BaseIterTable {
515 public: 503 public:
516 explicit HashMap(RawArray* data) 504 explicit HashMap(RawArray* data)
517 : BaseIterTable(Thread::Current()->zone(), data) {} 505 : BaseIterTable(Thread::Current()->zone(), data) {}
518 HashMap(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} 506 HashMap(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {}
519 HashMap(Object* key, Smi* value, Array* data) 507 HashMap(Object* key, Smi* value, Array* data)
520 : BaseIterTable(key, value, data) {} 508 : BaseIterTable(key, value, data) {}
521 template<typename Key> 509 template <typename Key>
522 RawObject* GetOrNull(const Key& key, bool* present = NULL) const { 510 RawObject* GetOrNull(const Key& key, bool* present = NULL) const {
523 intptr_t entry = BaseIterTable::FindKey(key); 511 intptr_t entry = BaseIterTable::FindKey(key);
524 if (present != NULL) { 512 if (present != NULL) {
525 *present = (entry != -1); 513 *present = (entry != -1);
526 } 514 }
527 return (entry == -1) ? Object::null() : BaseIterTable::GetPayload(entry, 0); 515 return (entry == -1) ? Object::null() : BaseIterTable::GetPayload(entry, 0);
528 } 516 }
529 bool UpdateOrInsert(const Object& key, const Object& value) const { 517 bool UpdateOrInsert(const Object& key, const Object& value) const {
530 EnsureCapacity(); 518 EnsureCapacity();
531 intptr_t entry = -1; 519 intptr_t entry = -1;
532 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry); 520 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry);
533 if (!present) { 521 if (!present) {
534 BaseIterTable::InsertKey(entry, key); 522 BaseIterTable::InsertKey(entry, key);
535 } 523 }
536 BaseIterTable::UpdatePayload(entry, 0, value); 524 BaseIterTable::UpdatePayload(entry, 0, value);
537 return present; 525 return present;
538 } 526 }
539 // Update the value of an existing key. Note that 'key' need not be an Object. 527 // Update the value of an existing key. Note that 'key' need not be an Object.
540 template<typename Key> 528 template <typename Key>
541 void UpdateValue(const Key& key, const Object& value) const { 529 void UpdateValue(const Key& key, const Object& value) const {
542 intptr_t entry = BaseIterTable::FindKey(key); 530 intptr_t entry = BaseIterTable::FindKey(key);
543 ASSERT(entry != -1); 531 ASSERT(entry != -1);
544 BaseIterTable::UpdatePayload(entry, 0, value); 532 BaseIterTable::UpdatePayload(entry, 0, value);
545 } 533 }
546 // If 'key' is not present, maps it to 'value_if_absent'. Returns the final 534 // If 'key' is not present, maps it to 'value_if_absent'. Returns the final
547 // value in the map. 535 // value in the map.
548 RawObject* InsertOrGetValue(const Object& key, 536 RawObject* InsertOrGetValue(const Object& key,
549 const Object& value_if_absent) const { 537 const Object& value_if_absent) const {
550 EnsureCapacity(); 538 EnsureCapacity();
551 intptr_t entry = -1; 539 intptr_t entry = -1;
552 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) { 540 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
553 BaseIterTable::InsertKey(entry, key); 541 BaseIterTable::InsertKey(entry, key);
554 BaseIterTable::UpdatePayload(entry, 0, value_if_absent); 542 BaseIterTable::UpdatePayload(entry, 0, value_if_absent);
555 return value_if_absent.raw(); 543 return value_if_absent.raw();
556 } else { 544 } else {
557 return BaseIterTable::GetPayload(entry, 0); 545 return BaseIterTable::GetPayload(entry, 0);
558 } 546 }
559 } 547 }
560 // Like InsertOrGetValue, but calls NewKey to allocate a key object if needed. 548 // Like InsertOrGetValue, but calls NewKey to allocate a key object if needed.
561 template<typename Key> 549 template <typename Key>
562 RawObject* InsertNewOrGetValue(const Key& key, 550 RawObject* InsertNewOrGetValue(const Key& key,
563 const Object& value_if_absent) const { 551 const Object& value_if_absent) const {
564 EnsureCapacity(); 552 EnsureCapacity();
565 intptr_t entry = -1; 553 intptr_t entry = -1;
566 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) { 554 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
567 BaseIterTable::KeyHandle() = 555 BaseIterTable::KeyHandle() =
568 BaseIterTable::BaseTable::Traits::NewKey(key); 556 BaseIterTable::BaseTable::Traits::NewKey(key);
569 BaseIterTable::InsertKey(entry, BaseIterTable::KeyHandle()); 557 BaseIterTable::InsertKey(entry, BaseIterTable::KeyHandle());
570 BaseIterTable::UpdatePayload(entry, 0, value_if_absent); 558 BaseIterTable::UpdatePayload(entry, 0, value_if_absent);
571 return value_if_absent.raw(); 559 return value_if_absent.raw();
572 } else { 560 } else {
573 return BaseIterTable::GetPayload(entry, 0); 561 return BaseIterTable::GetPayload(entry, 0);
574 } 562 }
575 } 563 }
576 564
577 template<typename Key> 565 template <typename Key>
578 bool Remove(const Key& key) const { 566 bool Remove(const Key& key) const {
579 intptr_t entry = BaseIterTable::FindKey(key); 567 intptr_t entry = BaseIterTable::FindKey(key);
580 if (entry == -1) { 568 if (entry == -1) {
581 return false; 569 return false;
582 } else { 570 } else {
583 BaseIterTable::DeleteEntry(entry); 571 BaseIterTable::DeleteEntry(entry);
584 return true; 572 return true;
585 } 573 }
586 } 574 }
587 575
588 void Clear() const { 576 void Clear() const { BaseIterTable::Initialize(); }
589 BaseIterTable::Initialize();
590 }
591 577
592 protected: 578 protected:
593 void EnsureCapacity() const { 579 void EnsureCapacity() const {
594 static const double kMaxLoadFactor = 0.75; 580 static const double kMaxLoadFactor = 0.75;
595 // We currently never shrink. 581 // We currently never shrink.
596 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); 582 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this);
597 } 583 }
598 }; 584 };
599 585
600 586
601 template<typename KeyTraits> 587 template <typename KeyTraits>
602 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > { 588 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > {
603 public: 589 public:
604 typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap; 590 typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap;
605 explicit UnorderedHashMap(RawArray* data) 591 explicit UnorderedHashMap(RawArray* data)
606 : BaseMap(Thread::Current()->zone(), data) {} 592 : BaseMap(Thread::Current()->zone(), data) {}
607 UnorderedHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {} 593 UnorderedHashMap(Zone* zone, RawArray* data) : BaseMap(zone, data) {}
608 UnorderedHashMap(Object* key, Smi* value, Array* data) 594 UnorderedHashMap(Object* key, Smi* value, Array* data)
609 : BaseMap(key, value, data) {} 595 : BaseMap(key, value, data) {}
610 }; 596 };
611 597
612 598
613 template<typename BaseIterTable> 599 template <typename BaseIterTable>
614 class HashSet : public BaseIterTable { 600 class HashSet : public BaseIterTable {
615 public: 601 public:
616 explicit HashSet(RawArray* data) 602 explicit HashSet(RawArray* data)
617 : BaseIterTable(Thread::Current()->zone(), data) {} 603 : BaseIterTable(Thread::Current()->zone(), data) {}
618 HashSet(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {} 604 HashSet(Zone* zone, RawArray* data) : BaseIterTable(zone, data) {}
619 HashSet(Object* key, Smi* value, Array* data) 605 HashSet(Object* key, Smi* value, Array* data)
620 : BaseIterTable(key, value, data) {} 606 : BaseIterTable(key, value, data) {}
621 bool Insert(const Object& key) { 607 bool Insert(const Object& key) {
622 EnsureCapacity(); 608 EnsureCapacity();
623 intptr_t entry = -1; 609 intptr_t entry = -1;
(...skipping 11 matching lines...) Expand all
635 intptr_t entry = -1; 621 intptr_t entry = -1;
636 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) { 622 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
637 BaseIterTable::InsertKey(entry, key); 623 BaseIterTable::InsertKey(entry, key);
638 return key.raw(); 624 return key.raw();
639 } else { 625 } else {
640 return BaseIterTable::GetKey(entry); 626 return BaseIterTable::GetKey(entry);
641 } 627 }
642 } 628 }
643 629
644 // Like InsertOrGet, but calls NewKey to allocate a key object if needed. 630 // Like InsertOrGet, but calls NewKey to allocate a key object if needed.
645 template<typename Key> 631 template <typename Key>
646 RawObject* InsertNewOrGet(const Key& key) const { 632 RawObject* InsertNewOrGet(const Key& key) const {
647 EnsureCapacity(); 633 EnsureCapacity();
648 intptr_t entry = -1; 634 intptr_t entry = -1;
649 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) { 635 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
650 BaseIterTable::KeyHandle() = 636 BaseIterTable::KeyHandle() =
651 BaseIterTable::BaseTable::Traits::NewKey(key); 637 BaseIterTable::BaseTable::Traits::NewKey(key);
652 BaseIterTable::InsertKey(entry, BaseIterTable::KeyHandle()); 638 BaseIterTable::InsertKey(entry, BaseIterTable::KeyHandle());
653 return BaseIterTable::KeyHandle().raw(); 639 return BaseIterTable::KeyHandle().raw();
654 } else { 640 } else {
655 return BaseIterTable::GetKey(entry); 641 return BaseIterTable::GetKey(entry);
656 } 642 }
657 } 643 }
658 644
659 template<typename Key> 645 template <typename Key>
660 RawObject* GetOrNull(const Key& key, bool* present = NULL) const { 646 RawObject* GetOrNull(const Key& key, bool* present = NULL) const {
661 intptr_t entry = BaseIterTable::FindKey(key); 647 intptr_t entry = BaseIterTable::FindKey(key);
662 if (present != NULL) { 648 if (present != NULL) {
663 *present = (entry != -1); 649 *present = (entry != -1);
664 } 650 }
665 return (entry == -1) ? Object::null() : BaseIterTable::GetKey(entry); 651 return (entry == -1) ? Object::null() : BaseIterTable::GetKey(entry);
666 } 652 }
667 653
668 template<typename Key> 654 template <typename Key>
669 bool Remove(const Key& key) const { 655 bool Remove(const Key& key) const {
670 intptr_t entry = BaseIterTable::FindKey(key); 656 intptr_t entry = BaseIterTable::FindKey(key);
671 if (entry == -1) { 657 if (entry == -1) {
672 return false; 658 return false;
673 } else { 659 } else {
674 BaseIterTable::DeleteEntry(entry); 660 BaseIterTable::DeleteEntry(entry);
675 return true; 661 return true;
676 } 662 }
677 } 663 }
678 664
679 void Clear() const { 665 void Clear() const { BaseIterTable::Initialize(); }
680 BaseIterTable::Initialize();
681 }
682 666
683 protected: 667 protected:
684 void EnsureCapacity() const { 668 void EnsureCapacity() const {
685 static const double kMaxLoadFactor = 0.75; 669 static const double kMaxLoadFactor = 0.75;
686 // We currently never shrink. 670 // We currently never shrink.
687 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this); 671 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this);
688 } 672 }
689 }; 673 };
690 674
691 675
692 template<typename KeyTraits> 676 template <typename KeyTraits>
693 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > { 677 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > {
694 public: 678 public:
695 typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet; 679 typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet;
696 explicit UnorderedHashSet(RawArray* data) 680 explicit UnorderedHashSet(RawArray* data)
697 : BaseSet(Thread::Current()->zone(), data) { 681 : BaseSet(Thread::Current()->zone(), data) {
698 ASSERT(data != Array::null()); 682 ASSERT(data != Array::null());
699 } 683 }
700 UnorderedHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {} 684 UnorderedHashSet(Zone* zone, RawArray* data) : BaseSet(zone, data) {}
701 UnorderedHashSet(Object* key, Smi* value, Array* data) 685 UnorderedHashSet(Object* key, Smi* value, Array* data)
702 : BaseSet(key, value, data) {} 686 : BaseSet(key, value, data) {}
703 }; 687 };
704 688
705 } // namespace dart 689 } // namespace dart
706 690
707 #endif // RUNTIME_VM_HASH_TABLE_H_ 691 #endif // RUNTIME_VM_HASH_TABLE_H_
OLDNEW
« no previous file with comments | « runtime/vm/hash_map_test.cc ('k') | runtime/vm/hash_table_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698