Changeset 9501 in webkit for trunk/JavaScriptCore/kjs/ustring.cpp


Ignore:
Timestamp:
Jun 27, 2005, 5:02:08 PM (20 years ago)
Author:
mjs
Message:

Reviewed by Darin.

  • replace hash functions with better ones
  • JavaScriptCore.pbproj/project.pbxproj: Add new file to build.
  • kjs/interpreter_map.cpp: (KJS::InterpreterMap::computeHash): Use shared pointer hash.
  • kjs/pointer_hash.h: Added. (KJS::pointerHash): Pointer hash based on 32-bit mix and 64-bit mix hashes.
  • kjs/protected_values.cpp: (KJS::ProtectedValues::computeHash): Use shared pointer hash.
  • kjs/ustring.cpp: (KJS::UString::Rep::computeHash): Use SuperFastHash algorithm.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/ustring.cpp

    r9172 r9501  
    263263const unsigned PHI = 0x9e3779b9U;
    264264
    265 // This hash algorithm comes from:
    266 // http://burtleburtle.net/bob/hash/hashfaq.html
    267 // http://burtleburtle.net/bob/hash/doobs.html
    268 unsigned UString::Rep::computeHash(const UChar *s, int length)
    269 {
    270     int prefixLength = length < 8 ? length : 8;
    271     int suffixPosition = length < 16 ? 8 : length - 8;
    272 
    273     unsigned h = PHI;
    274     h += length;
    275     h += (h << 10);
    276     h ^= (h << 6);
    277 
    278     for (int i = 0; i < prefixLength; i++) {
    279         h += s[i].uc;
    280         h += (h << 10);
    281         h ^= (h << 6);
    282     }
    283     for (int i = suffixPosition; i < length; i++){
    284         h += s[i].uc;
    285         h += (h << 10);
    286         h ^= (h << 6);
    287     }
    288 
    289     h += (h << 3);
    290     h ^= (h >> 11);
    291     h += (h << 15);
    292  
    293     if (h == 0)
    294         h = 0x80000000;
    295 
    296     return h;
    297 }
    298 
    299 // This hash algorithm comes from:
    300 // http://burtleburtle.net/bob/hash/hashfaq.html
    301 // http://burtleburtle.net/bob/hash/doobs.html
     265// Paul Hsieh's SuperFastHash
     266// http://www.azillionmonkeys.com/qed/hash.html
     267unsigned UString::Rep::computeHash(const UChar *s, int len)
     268{
     269  unsigned l = len;
     270  uint32_t hash = PHI;
     271  uint32_t tmp;
     272
     273  int rem = l & 1;
     274  l >>= 1;
     275
     276  // Main loop
     277  for (; l > 0; l--) {
     278    hash += s[0].uc;
     279    tmp = (s[1].uc << 11) ^ hash;
     280    hash = (hash << 16) ^ tmp;
     281    s += 2;
     282    hash += hash >> 11;
     283  }
     284
     285  // Handle end case
     286  if (rem) {
     287    hash += s[0].uc;
     288    hash ^= hash << 11;
     289    hash += hash >> 17;
     290  }
     291
     292  // Force "avalanching" of final 127 bits
     293  hash ^= hash << 3;
     294  hash += hash >> 5;
     295  hash ^= hash << 2;
     296  hash += hash >> 15;
     297  hash ^= hash << 10;
     298
     299  // this avoids ever returning a hash code of 0, since that is used to
     300  // signal "hash not computed yet", using a value that is likely to be
     301  // effectively the same as 0 when the low bits are masked
     302  if (hash == 0)
     303    hash = 0x80000000;
     304
     305  return hash;
     306}
     307
     308// Paul Hsieh's SuperFastHash
     309// http://www.azillionmonkeys.com/qed/hash.html
    302310unsigned UString::Rep::computeHash(const char *s)
    303311{
    304     int length = strlen(s);
    305     int prefixLength = length < 8 ? length : 8;
    306     int suffixPosition = length < 16 ? 8 : length - 8;
    307 
    308     unsigned h = PHI;
    309     h += length;
    310     h += (h << 10);
    311     h ^= (h << 6);
    312 
    313     for (int i = 0; i < prefixLength; i++) {
    314         h += (unsigned char)s[i];
    315         h += (h << 10);
    316         h ^= (h << 6);
    317     }
    318     for (int i = suffixPosition; i < length; i++) {
    319         h += (unsigned char)s[i];
    320         h += (h << 10);
    321         h ^= (h << 6);
    322     }
    323 
    324     h += (h << 3);
    325     h ^= (h >> 11);
    326     h += (h << 15);
    327 
    328     if (h == 0)
    329         h = 0x80000000;
    330 
    331     return h;
     312  // This hash is designed to work on 16-bit chunks at a time. But since the normal case
     313  // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
     314  // were 16-bit chunks, which should give matching results
     315
     316  uint32_t hash = PHI;
     317  uint32_t tmp;
     318  unsigned l = strlen(s);
     319 
     320  int rem = l & 1;
     321  l >>= 1;
     322
     323  // Main loop
     324  for (; l > 0; l--) {
     325    hash += (unsigned char)s[0];
     326    tmp = ((unsigned char)s[1] << 11) ^ hash;
     327    hash = (hash << 16) ^ tmp;
     328    s += 2;
     329    hash += hash >> 11;
     330  }
     331
     332  // Handle end case
     333  if (rem) {
     334    hash += (unsigned char)s[0];
     335    hash ^= hash << 11;
     336    hash += hash >> 17;
     337  }
     338
     339  // Force "avalanching" of final 127 bits
     340  hash ^= hash << 3;
     341  hash += hash >> 5;
     342  hash ^= hash << 2;
     343  hash += hash >> 15;
     344  hash ^= hash << 10;
     345 
     346  // this avoids ever returning a hash code of 0, since that is used to
     347  // signal "hash not computed yet", using a value that is likely to be
     348  // effectively the same as 0 when the low bits are masked
     349  if (hash == 0)
     350    hash = 0x80000000;
     351
     352  return hash;
    332353}
    333354
Note: See TracChangeset for help on using the changeset viewer.