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

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

Issue 397413002: Reimplement Symbols using hash table template. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 5 months 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/vm/hash_table_test.cc » ('j') | runtime/vm/symbols.cc » ('J')
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 VM_HASH_TABLE_H_ 5 #ifndef VM_HASH_TABLE_H_
6 #define VM_HASH_TABLE_H_ 6 #define VM_HASH_TABLE_H_
7 7
8 // Temporarily used when sorting the indices in EnumIndexHashTable. 8 // Temporarily used when sorting the indices in EnumIndexHashTable.
9 // TODO(koda): Remove these dependencies before using in production. 9 // TODO(koda): Remove these dependencies before using in production.
10 #include <map> 10 #include <map>
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 // 71 //
72 // Parameters 72 // Parameters
73 // KeyTraits: defines static methods 73 // KeyTraits: defines static methods
74 // bool IsMatch(const Key& key, const Object& obj) and 74 // bool IsMatch(const Key& key, const Object& obj) and
75 // uword Hash(const Key& key) for any number of desired lookup key types. 75 // uword Hash(const Key& key) for any number of desired lookup key types.
76 // kPayloadSize: number of components of the payload in each entry. 76 // kPayloadSize: number of components of the payload in each entry.
77 // kMetaDataSize: number of elements reserved (e.g., for iteration order data). 77 // kMetaDataSize: number of elements reserved (e.g., for iteration order data).
78 template<typename KeyTraits, intptr_t kPayloadSize, intptr_t kMetaDataSize> 78 template<typename KeyTraits, intptr_t kPayloadSize, intptr_t kMetaDataSize>
79 class HashTable : public ValueObject { 79 class HashTable : public ValueObject {
80 public: 80 public:
81 typedef KeyTraits Traits;
81 explicit HashTable(Array& data) : data_(data) {} 82 explicit HashTable(Array& data) : data_(data) {}
82 83
83 RawArray* Release() { 84 RawArray* Release() {
84 ASSERT(!data_.IsNull()); 85 ASSERT(!data_.IsNull());
85 RawArray* array = data_.raw(); 86 RawArray* array = data_.raw();
86 data_ = Array::null(); 87 data_ = Array::null();
87 return array; 88 return array;
88 } 89 }
89 90
90 ~HashTable() { 91 ~HashTable() {
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 } 377 }
377 378
378 // No extra book-keeping needed for DeleteEntry. 379 // No extra book-keeping needed for DeleteEntry.
379 }; 380 };
380 381
381 382
382 class HashTables : public AllStatic { 383 class HashTables : public AllStatic {
383 public: 384 public:
384 // Allocates and initializes a table. 385 // Allocates and initializes a table.
385 template<typename Table> 386 template<typename Table>
386 static RawArray* New(intptr_t initial_capacity) { 387 static RawArray* New(intptr_t initial_capacity,
388 Heap::Space space = Heap::kNew) {
387 Table table(Array::Handle(Array::New( 389 Table table(Array::Handle(Array::New(
388 Table::ArrayLengthForNumOccupied(initial_capacity)))); 390 Table::ArrayLengthForNumOccupied(initial_capacity), space)));
389 table.Initialize(); 391 table.Initialize();
390 return table.Release(); 392 return table.Release();
391 } 393 }
392 394
393 // Clears 'to' and inserts all elements from 'from', in iteration order. 395 // Clears 'to' and inserts all elements from 'from', in iteration order.
394 // The tables must have the same user payload size. 396 // The tables must have the same user payload size.
395 template<typename From, typename To> 397 template<typename From, typename To>
396 static void Copy(const From& from, const To& to) { 398 static void Copy(const From& from, const To& to) {
397 COMPILE_ASSERT(From::kPayloadSize == To::kPayloadSize); 399 COMPILE_ASSERT(From::kPayloadSize == To::kPayloadSize);
398 to.Initialize(); 400 to.Initialize();
(...skipping 17 matching lines...) Expand all
416 418
417 template<typename Table> 419 template<typename Table>
418 static void EnsureLoadFactor(double low, double high, const Table& table) { 420 static void EnsureLoadFactor(double low, double high, const Table& table) {
419 double current = (1 + table.NumOccupied() + table.NumDeleted()) / 421 double current = (1 + table.NumOccupied() + table.NumDeleted()) /
420 static_cast<double>(table.NumEntries()); 422 static_cast<double>(table.NumEntries());
421 if (low <= current && current < high) { 423 if (low <= current && current < high) {
422 return; 424 return;
423 } 425 }
424 double target = (low + high) / 2.0; 426 double target = (low + high) / 2.0;
425 intptr_t new_capacity = (1 + table.NumOccupied()) / target; 427 intptr_t new_capacity = (1 + table.NumOccupied()) / target;
426 Table new_table(Array::Handle(New<Table>(new_capacity))); 428 Table new_table(Array::Handle(New<Table>(
429 new_capacity,
430 table.data_.IsOld() ? Heap::kOld : Heap::kNew)));
427 Copy(table, new_table); 431 Copy(table, new_table);
428 table.data_ = new_table.Release(); 432 table.data_ = new_table.Release();
429 } 433 }
430 434
431 // Serializes a table by concatenating its entries as an array. 435 // Serializes a table by concatenating its entries as an array.
432 template<typename Table> 436 template<typename Table>
433 static RawArray* ToArray(const Table& table, bool include_payload) { 437 static RawArray* ToArray(const Table& table, bool include_payload) {
434 const intptr_t entry_size = include_payload ? (1 + Table::kPayloadSize) : 1; 438 const intptr_t entry_size = include_payload ? (1 + Table::kPayloadSize) : 1;
435 Array& result = Array::Handle(Array::New(table.NumOccupied() * entry_size)); 439 Array& result = Array::Handle(Array::New(table.NumOccupied() * entry_size));
436 typename Table::Iterator it(&table); 440 typename Table::Iterator it(&table);
(...skipping 21 matching lines...) Expand all
458 explicit HashMap(Array& data) : BaseIterTable(data) {} 462 explicit HashMap(Array& data) : BaseIterTable(data) {}
459 template<typename Key> 463 template<typename Key>
460 RawObject* GetOrNull(const Key& key, bool* present = NULL) const { 464 RawObject* GetOrNull(const Key& key, bool* present = NULL) const {
461 intptr_t entry = BaseIterTable::FindKey(key); 465 intptr_t entry = BaseIterTable::FindKey(key);
462 if (present != NULL) { 466 if (present != NULL) {
463 *present = (entry != -1); 467 *present = (entry != -1);
464 } 468 }
465 return (entry == -1) ? Object::null() : BaseIterTable::GetPayload(entry, 0); 469 return (entry == -1) ? Object::null() : BaseIterTable::GetPayload(entry, 0);
466 } 470 }
467 bool UpdateOrInsert(const Object& key, const Object& value) const { 471 bool UpdateOrInsert(const Object& key, const Object& value) const {
468 HashTables::EnsureLoadFactor(0.0, 0.75, *this); 472 EnsureCapacity();
469 intptr_t entry = -1; 473 intptr_t entry = -1;
470 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry); 474 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry);
471 if (!present) { 475 if (!present) {
472 BaseIterTable::InsertKey(entry, key); 476 BaseIterTable::InsertKey(entry, key);
473 } 477 }
474 BaseIterTable::UpdatePayload(entry, 0, value); 478 BaseIterTable::UpdatePayload(entry, 0, value);
475 return present; 479 return present;
476 } 480 }
477 // Update the value of an existing key. Note that 'key' need not be an Object. 481 // Update the value of an existing key. Note that 'key' need not be an Object.
478 template<typename Key> 482 template<typename Key>
479 void UpdateValue(const Key& key, const Object& value) const { 483 void UpdateValue(const Key& key, const Object& value) const {
480 intptr_t entry = BaseIterTable::FindKey(key); 484 intptr_t entry = BaseIterTable::FindKey(key);
481 ASSERT(entry != -1); 485 ASSERT(entry != -1);
482 BaseIterTable::UpdatePayload(entry, 0, value); 486 BaseIterTable::UpdatePayload(entry, 0, value);
483 } 487 }
488 // If 'key' is not present, maps it to 'value_if_absent'. Returns the final
489 // value in the map.
490 RawObject* InsertOrGetValue(const Object& key,
491 const Object& value_if_absent) const {
492 EnsureCapacity();
493 intptr_t entry = -1;
494 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
495 BaseIterTable::InsertKey(entry, key);
496 BaseIterTable::UpdatePayload(entry, 0, value_if_absent);
497 return value_if_absent.raw();
498 } else {
499 return BaseIterTable::GetPayload(entry, 0);
500 }
501 }
502 // Like InsertOrGetValue, but calls NewKey to allocate a key object if needed.
503 template<typename Key>
504 RawObject* InsertNewOrGetValue(const Key& key,
505 const Object& value_if_absent) const {
506 EnsureCapacity();
507 intptr_t entry = -1;
508 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
509 Object& new_key = Object::Handle(
510 BaseIterTable::BaseTable::Traits::NewKey(key));
511 BaseIterTable::InsertKey(entry, new_key);
512 BaseIterTable::UpdatePayload(entry, 0, value_if_absent);
513 return value_if_absent.raw();
514 } else {
515 return BaseIterTable::GetPayload(entry, 0);
516 }
517 }
484 518
485 template<typename Key> 519 template<typename Key>
486 bool Remove(const Key& key) const { 520 bool Remove(const Key& key) const {
487 intptr_t entry = BaseIterTable::FindKey(key); 521 intptr_t entry = BaseIterTable::FindKey(key);
488 if (entry == -1) { 522 if (entry == -1) {
489 return false; 523 return false;
490 } else { 524 } else {
491 BaseIterTable::DeleteEntry(entry); 525 BaseIterTable::DeleteEntry(entry);
492 return true; 526 return true;
493 } 527 }
494 } 528 }
529
530 protected:
531 void EnsureCapacity() const {
532 static const double kMaxLoadFactor = 0.75;
533 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this);
534 }
495 }; 535 };
496 536
497 537
498 template<typename KeyTraits> 538 template<typename KeyTraits>
499 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > { 539 class UnorderedHashMap : public HashMap<UnorderedHashTable<KeyTraits, 1> > {
500 public: 540 public:
501 typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap; 541 typedef HashMap<UnorderedHashTable<KeyTraits, 1> > BaseMap;
502 explicit UnorderedHashMap(Array& data) : BaseMap(data) {} 542 explicit UnorderedHashMap(Array& data) : BaseMap(data) {}
503 }; 543 };
504 544
505 545
506 template<typename KeyTraits> 546 template<typename KeyTraits>
507 class EnumIndexHashMap : public HashMap<EnumIndexHashTable<KeyTraits, 1> > { 547 class EnumIndexHashMap : public HashMap<EnumIndexHashTable<KeyTraits, 1> > {
508 public: 548 public:
509 typedef HashMap<EnumIndexHashTable<KeyTraits, 1> > BaseMap; 549 typedef HashMap<EnumIndexHashTable<KeyTraits, 1> > BaseMap;
510 explicit EnumIndexHashMap(Array& data) : BaseMap(data) {} 550 explicit EnumIndexHashMap(Array& data) : BaseMap(data) {}
511 }; 551 };
512 552
513 553
514 template<typename BaseIterTable> 554 template<typename BaseIterTable>
515 class HashSet : public BaseIterTable { 555 class HashSet : public BaseIterTable {
516 public: 556 public:
517 explicit HashSet(Array& data) : BaseIterTable(data) {} 557 explicit HashSet(Array& data) : BaseIterTable(data) {}
518 bool Insert(const Object& key) { 558 bool Insert(const Object& key) {
519 HashTables::EnsureLoadFactor(0.0, 0.75, *this); 559 EnsureCapacity();
520 intptr_t entry = -1; 560 intptr_t entry = -1;
521 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry); 561 bool present = BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry);
522 if (!present) { 562 if (!present) {
523 BaseIterTable::InsertKey(entry, key); 563 BaseIterTable::InsertKey(entry, key);
524 } 564 }
525 return present; 565 return present;
526 } 566 }
567
568 // If 'key' is not present, insert and return it. Else, return the existing
569 // key in the set (useful for canonicalization).
570 RawObject* InsertOrGet(const Object& key) const {
571 EnsureCapacity();
572 intptr_t entry = -1;
573 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
574 BaseIterTable::InsertKey(entry, key);
575 return key.raw();
576 } else {
577 return BaseIterTable::GetPayload(entry, 0);
578 }
579 }
580
581 // Like InsertOrGet, but calls NewKey to allocate a key object if needed.
582 template<typename Key>
583 RawObject* InsertNewOrGet(const Key& key) const {
584 EnsureCapacity();
585 intptr_t entry = -1;
586 if (!BaseIterTable::FindKeyOrDeletedOrUnused(key, &entry)) {
587 Object& new_key = Object::Handle(
588 BaseIterTable::BaseTable::Traits::NewKey(key));
589 BaseIterTable::InsertKey(entry, new_key);
590 return new_key.raw();
591 } else {
592 return BaseIterTable::GetKey(entry);
593 }
594 }
595
596 template<typename Key>
597 RawObject* GetOrNull(const Key& key, bool* present = NULL) const {
598 intptr_t entry = BaseIterTable::FindKey(key);
599 if (present != NULL) {
600 *present = (entry != -1);
601 }
602 return (entry == -1) ? Object::null() : BaseIterTable::GetKey(entry);
603 }
604
527 template<typename Key> 605 template<typename Key>
528 bool Remove(const Key& key) const { 606 bool Remove(const Key& key) const {
529 intptr_t entry = BaseIterTable::FindKey(key); 607 intptr_t entry = BaseIterTable::FindKey(key);
530 if (entry == -1) { 608 if (entry == -1) {
531 return false; 609 return false;
532 } else { 610 } else {
533 BaseIterTable::DeleteEntry(entry); 611 BaseIterTable::DeleteEntry(entry);
534 return true; 612 return true;
535 } 613 }
536 } 614 }
615
616 protected:
617 void EnsureCapacity() const {
618 static const double kMaxLoadFactor = 0.75;
619 HashTables::EnsureLoadFactor(0.0, kMaxLoadFactor, *this);
620 }
537 }; 621 };
538 622
539 623
540 template<typename KeyTraits> 624 template<typename KeyTraits>
541 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > { 625 class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > {
542 public: 626 public:
543 typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet; 627 typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet;
544 explicit UnorderedHashSet(Array& data) : BaseSet(data) {} 628 explicit UnorderedHashSet(Array& data) : BaseSet(data) {}
545 }; 629 };
546 630
547 631
548 template<typename KeyTraits> 632 template<typename KeyTraits>
549 class EnumIndexHashSet : public HashSet<EnumIndexHashTable<KeyTraits, 0> > { 633 class EnumIndexHashSet : public HashSet<EnumIndexHashTable<KeyTraits, 0> > {
550 public: 634 public:
551 typedef HashSet<EnumIndexHashTable<KeyTraits, 0> > BaseSet; 635 typedef HashSet<EnumIndexHashTable<KeyTraits, 0> > BaseSet;
552 explicit EnumIndexHashSet(Array& data) : BaseSet(data) {} 636 explicit EnumIndexHashSet(Array& data) : BaseSet(data) {}
553 }; 637 };
554 638
555 } // namespace dart 639 } // namespace dart
556 640
557 #endif // VM_HASH_TABLE_H_ 641 #endif // VM_HASH_TABLE_H_
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/hash_table_test.cc » ('j') | runtime/vm/symbols.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698