Changeset 27176 in webkit for trunk/JavaScriptCore/wtf/HashTable.h
- Timestamp:
- Oct 28, 2007, 1:17:39 AM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/wtf/HashTable.h
r27093 r27176 78 78 #endif 79 79 80 typedef enum { HashItemKnownGood } HashItemKnownGoodTag; 81 82 80 83 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> 81 84 class HashTableConstIterator { … … 104 107 } 105 108 109 HashTableConstIterator(const HashTableType* table, PointerType position, PointerType endPosition, HashItemKnownGoodTag) 110 : m_position(position), m_endPosition(endPosition) 111 { 112 addIterator(table, this); 113 } 114 106 115 public: 107 116 HashTableConstIterator() … … 211 220 212 221 HashTableIterator(HashTableType* table, PointerType pos, PointerType end) : m_iterator(table, pos, end) { } 222 HashTableIterator(HashTableType* table, PointerType pos, PointerType end, HashItemKnownGoodTag tag) : m_iterator(table, pos, end, tag) { } 213 223 214 224 public: … … 256 266 static unsigned hash(const Key& key) { return HashFunctions::hash(key); } 257 267 static bool equal(const Key& a, const Key& b) { return HashFunctions::equal(a, b); } 258 static void translate(Value& location, const Key&, const Value& value , unsigned) { location = value; }268 static void translate(Value& location, const Key&, const Value& value) { location = value; } 259 269 }; 260 270 … … 277 287 278 288 iterator begin() { return makeIterator(m_table); } 279 iterator end() { return make Iterator(m_table + m_tableSize); }289 iterator end() { return makeKnownGoodIterator(m_table + m_tableSize); } 280 290 const_iterator begin() const { return makeConstIterator(m_table); } 281 const_iterator end() const { return make ConstIterator(m_table + m_tableSize); }291 const_iterator end() const { return makeKnownGoodConstIterator(m_table + m_tableSize); } 282 292 283 293 int size() const { return m_keyCount; } … … 291 301 // in the table. 292 302 template<typename T, typename Extra, typename HashTranslator> pair<iterator, bool> add(const T& key, const Extra&); 303 template<typename T, typename Extra, typename HashTranslator> pair<iterator, bool> addPassingHashCode(const T& key, const Extra&); 293 304 294 305 iterator find(const KeyType& key) { return find<KeyType, IdentityTranslatorType>(key); } … … 308 319 static bool isEmptyOrDeletedBucket(const ValueType& value) { return isEmptyBucket(value) || isDeletedBucket(value); } 309 320 321 ValueType* lookup(const Key& key) { return lookup<Key, IdentityTranslatorType>(key); } 322 310 323 private: 311 324 static ValueType* allocateTable(int size); … … 315 328 typedef pair<LookupType, unsigned> FullLookupType; 316 329 317 LookupType lookup(const Key& key) { return lookup<Key, IdentityTranslatorType>(key).first; } 318 template<typename T, typename HashTranslator> FullLookupType lookup(const T&); 330 template<typename T, typename HashTranslator> ValueType* lookup(const T&); 331 LookupType lookupForWriting(const Key& key) { return lookupForWriting<Key, IdentityTranslatorType>(key); }; 332 template<typename T, typename HashTranslator> FullLookupType fullLookupForWriting(const T&); 333 template<typename T, typename HashTranslator> LookupType lookupForWriting(const T&); 319 334 320 335 void remove(ValueType*); … … 337 352 iterator makeIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize); } 338 353 const_iterator makeConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize); } 354 iterator makeKnownGoodIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); } 355 const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); } 339 356 340 357 #if CHECK_HASHTABLE_CONSISTENCY … … 383 400 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> 384 401 template<typename T, typename HashTranslator> 385 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::FullLookupTypeHashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookup(const T& key)402 inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookup(const T& key) 386 403 { 387 404 ASSERT(m_table); 388 405 406 int k = 0; 407 int sizeMask = m_tableSizeMask; 408 ValueType* table = m_table; 389 409 unsigned h = HashTranslator::hash(key); 390 int sizeMask = m_tableSizeMask;391 410 int i = h & sizeMask; 392 int k = 0;393 411 394 412 #if DUMP_HASHTABLE_STATS … … 397 415 #endif 398 416 399 ValueType* table = m_table;400 ValueType* deletedEntry = 0;401 402 417 while (1) { 403 418 ValueType* entry = table + i; 404 405 if (isEmptyBucket(*entry)) 406 return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h); 407 408 if (isDeletedBucket(*entry)) 409 deletedEntry = entry; 410 else if (HashTranslator::equal(Extractor::extract(*entry), key)) 411 return makeLookupResult(entry, true, h); 412 419 420 // we count on the compiler to optimize out this branch 421 if (HashFunctions::safeToCompareToEmptyOrDeleted) { 422 if (HashTranslator::equal(Extractor::extract(*entry), key)) 423 return entry; 424 425 if (isEmptyBucket(*entry)) 426 return 0; 427 } else { 428 if (isEmptyBucket(*entry)) 429 return 0; 430 431 if (!isDeletedBucket(*entry) && HashTranslator::equal(Extractor::extract(*entry), key)) 432 return entry; 433 } 413 434 #if DUMP_HASHTABLE_STATS 414 435 ++probeCount; … … 422 443 423 444 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> 445 template<typename T, typename HashTranslator> 446 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookupForWriting(const T& key) 447 { 448 ASSERT(m_table); 449 450 int k = 0; 451 ValueType* table = m_table; 452 int sizeMask = m_tableSizeMask; 453 unsigned h = HashTranslator::hash(key); 454 int i = h & sizeMask; 455 456 #if DUMP_HASHTABLE_STATS 457 ++HashTableStats::numAccesses; 458 int probeCount = 0; 459 #endif 460 461 ValueType* deletedEntry = 0; 462 463 while (1) { 464 ValueType* entry = table + i; 465 466 // we count on the compiler to optimize out this branch 467 if (HashFunctions::safeToCompareToEmptyOrDeleted) { 468 if (isEmptyBucket(*entry)) 469 return LookupType(deletedEntry ? deletedEntry : entry, false); 470 471 if (HashTranslator::equal(Extractor::extract(*entry), key)) 472 return LookupType(entry, true); 473 474 if (isDeletedBucket(*entry)) 475 deletedEntry = entry; 476 } else { 477 if (isEmptyBucket(*entry)) 478 return LookupType(deletedEntry ? deletedEntry : entry, false); 479 480 if (isDeletedBucket(*entry)) 481 deletedEntry = entry; 482 else if (HashTranslator::equal(Extractor::extract(*entry), key)) 483 return LookupType(entry, true); 484 } 485 #if DUMP_HASHTABLE_STATS 486 ++probeCount; 487 HashTableStats::recordCollisionAtCount(probeCount); 488 #endif 489 if (k == 0) 490 k = 1 | (h % sizeMask); 491 i = (i + k) & sizeMask; 492 } 493 } 494 495 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> 496 template<typename T, typename HashTranslator> 497 inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::fullLookupForWriting(const T& key) 498 { 499 ASSERT(m_table); 500 501 int k = 0; 502 ValueType* table = m_table; 503 int sizeMask = m_tableSizeMask; 504 unsigned h = HashTranslator::hash(key); 505 int i = h & sizeMask; 506 507 #if DUMP_HASHTABLE_STATS 508 ++HashTableStats::numAccesses; 509 int probeCount = 0; 510 #endif 511 512 ValueType* deletedEntry = 0; 513 514 while (1) { 515 ValueType* entry = table + i; 516 517 // we count on the compiler to optimize out this branch 518 if (HashFunctions::safeToCompareToEmptyOrDeleted) { 519 if (isEmptyBucket(*entry)) 520 return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h); 521 522 if (HashTranslator::equal(Extractor::extract(*entry), key)) 523 return makeLookupResult(entry, true, h); 524 525 if (isDeletedBucket(*entry)) 526 deletedEntry = entry; 527 } else { 528 if (isEmptyBucket(*entry)) 529 return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h); 530 531 if (isDeletedBucket(*entry)) 532 deletedEntry = entry; 533 else if (HashTranslator::equal(Extractor::extract(*entry), key)) 534 return makeLookupResult(entry, true, h); 535 } 536 #if DUMP_HASHTABLE_STATS 537 ++probeCount; 538 HashTableStats::recordCollisionAtCount(probeCount); 539 #endif 540 if (k == 0) 541 k = 1 | (h % sizeMask); 542 i = (i + k) & sizeMask; 543 } 544 } 545 546 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> 424 547 template<typename T, typename Extra, typename HashTranslator> 425 inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::add(const T& key, const Extra &extra)548 inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::add(const T& key, const Extra& extra) 426 549 { 427 550 invalidateIterators(); … … 432 555 checkTableConsistency(); 433 556 434 FullLookupType lookupResult = lookup<T, HashTranslator>(key); 435 436 ValueType *entry = lookupResult.first.first; 437 bool found = lookupResult.first.second; 438 unsigned h = lookupResult.second; 439 440 if (found) 441 return std::make_pair(makeIterator(entry), false); 442 443 if (isDeletedBucket(*entry)) 444 --m_deletedCount; 445 446 HashTranslator::translate(*entry, key, extra, h); 557 ASSERT(m_table); 558 559 int k = 0; 560 ValueType* table = m_table; 561 int sizeMask = m_tableSizeMask; 562 unsigned h = HashTranslator::hash(key); 563 int i = h & sizeMask; 564 565 #if DUMP_HASHTABLE_STATS 566 ++HashTableStats::numAccesses; 567 int probeCount = 0; 568 #endif 569 570 ValueType* deletedEntry = 0; 571 ValueType* entry; 572 while (1) { 573 entry = table + i; 574 575 // we count on the compiler to optimize out this branch 576 if (HashFunctions::safeToCompareToEmptyOrDeleted) { 577 if (isEmptyBucket(*entry)) 578 break; 579 580 if (HashTranslator::equal(Extractor::extract(*entry), key)) 581 return std::make_pair(makeKnownGoodIterator(entry), false); 582 583 if (isDeletedBucket(*entry)) 584 deletedEntry = entry; 585 } else { 586 if (isEmptyBucket(*entry)) 587 break; 588 589 if (isDeletedBucket(*entry)) 590 deletedEntry = entry; 591 else if (HashTranslator::equal(Extractor::extract(*entry), key)) 592 return std::make_pair(makeKnownGoodIterator(entry), false); 593 } 594 #if DUMP_HASHTABLE_STATS 595 ++probeCount; 596 HashTableStats::recordCollisionAtCount(probeCount); 597 #endif 598 if (k == 0) 599 k = 1 | (h % sizeMask); 600 i = (i + k) & sizeMask; 601 } 602 603 if (deletedEntry) { 604 entry = deletedEntry; 605 --m_deletedCount; 606 } 607 608 HashTranslator::translate(*entry, key, extra); 609 447 610 ++m_keyCount; 448 611 449 612 if (shouldExpand()) { 450 613 // FIXME: this makes an extra copy on expand. Probably not that bad since … … 455 618 return std::make_pair(find(enteredKey), true); 456 619 } 457 620 458 621 checkTableConsistency(); 459 460 return std::make_pair(makeIterator(entry), true); 622 623 return std::make_pair(makeKnownGoodIterator(entry), true); 624 } 625 626 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> 627 template<typename T, typename Extra, typename HashTranslator> 628 inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::addPassingHashCode(const T& key, const Extra& extra) 629 { 630 invalidateIterators(); 631 632 if (!m_table) 633 expand(); 634 635 checkTableConsistency(); 636 637 FullLookupType lookupResult = fullLookupForWriting<T, HashTranslator>(key); 638 639 ValueType *entry = lookupResult.first.first; 640 bool found = lookupResult.first.second; 641 unsigned h = lookupResult.second; 642 643 if (found) 644 return std::make_pair(makeKnownGoodIterator(entry), false); 645 646 if (isDeletedBucket(*entry)) 647 --m_deletedCount; 648 649 HashTranslator::translate(*entry, key, extra, h); 650 ++m_keyCount; 651 if (shouldExpand()) { 652 // FIXME: this makes an extra copy on expand. Probably not that bad since 653 // expand is rare, but would be better to have a version of expand that can 654 // follow a pivot entry and return the new position 655 KeyType enteredKey = Extractor::extract(*entry); 656 expand(); 657 return std::make_pair(find(enteredKey), true); 658 } 659 660 checkTableConsistency(); 661 662 return std::make_pair(makeKnownGoodIterator(entry), true); 461 663 } 462 664 … … 465 667 { 466 668 ASSERT(m_table); 467 ASSERT(!lookup (Extractor::extract(entry)).second);468 ASSERT(!isDeletedBucket(*(lookup (Extractor::extract(entry)).first)));669 ASSERT(!lookupForWriting(Extractor::extract(entry)).second); 670 ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first))); 469 671 #if DUMP_HASHTABLE_STATS 470 672 ++HashTableStats::numReinserts; 471 673 #endif 472 674 473 Mover<ValueType, Traits::needsDestruction>::move(entry, *(lookup (Extractor::extract(entry)).first));675 Mover<ValueType, Traits::needsDestruction>::move(entry, *(lookupForWriting(Extractor::extract(entry)).first)); 474 676 } 475 677 … … 481 683 return end(); 482 684 483 LookupType result = lookup<T, HashTranslator>(key).first;484 if (! result.second)685 ValueType* entry = lookup<T, HashTranslator>(key); 686 if (!entry) 485 687 return end(); 486 return makeIterator(result.first); 688 689 return makeKnownGoodIterator(entry); 487 690 } 488 691 … … 494 697 return end(); 495 698 496 LookupType result = const_cast<HashTable *>(this)->lookup<T, HashTranslator>(key).first;497 if (! result.second)699 ValueType* entry = const_cast<HashTable *>(this)->lookup<T, HashTranslator>(key); 700 if (!entry) 498 701 return end(); 499 return makeConstIterator(result.first); 702 703 return makeKnownGoodConstIterator(entry); 500 704 } 501 705 … … 507 711 return false; 508 712 509 return const_cast<HashTable *>(this)->lookup<T, HashTranslator>(key) .first.second;713 return const_cast<HashTable *>(this)->lookup<T, HashTranslator>(key); 510 714 } 511 715
Note:
See TracChangeset
for help on using the changeset viewer.