[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677

darin darin at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 07:38:48 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit 4c386e0d12115de7623ad04ace04564c2b9f0216
Author: darin <darin at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Apr 25 21:51:12 2003 +0000

            Reviewed by Maciej.
    
            - move from linear probing to double hashing, gives an 0.7% speedup in iBench JavaScript
    
            * kjs/property_map.h: Remove the hash function.
            * kjs/property_map.cpp: Added statistics for rehashes and removes.
            Moved from linear probing to double hashing, using the hash modulo
            (table size minus one) plus one for the probing distance.
    
            * kjs/ustring.h: Use unsigned instead of int for hash function result.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@4188 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index c7e1d46..193925a 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,16 @@
+2003-04-25  Darin Adler  <darin at apple.com>
+
+        Reviewed by Maciej.
+
+        - move from linear probing to double hashing, gives an 0.7% speedup in iBench JavaScript
+
+        * kjs/property_map.h: Remove the hash function.
+        * kjs/property_map.cpp: Added statistics for rehashes and removes.
+        Moved from linear probing to double hashing, using the hash modulo
+        (table size minus one) plus one for the probing distance.
+
+        * kjs/ustring.h: Use unsigned instead of int for hash function result.
+
 === Safari-75 ===
 
 === Safari-74 ===
diff --git a/JavaScriptCore/ChangeLog-2003-10-25 b/JavaScriptCore/ChangeLog-2003-10-25
index c7e1d46..193925a 100644
--- a/JavaScriptCore/ChangeLog-2003-10-25
+++ b/JavaScriptCore/ChangeLog-2003-10-25
@@ -1,3 +1,16 @@
+2003-04-25  Darin Adler  <darin at apple.com>
+
+        Reviewed by Maciej.
+
+        - move from linear probing to double hashing, gives an 0.7% speedup in iBench JavaScript
+
+        * kjs/property_map.h: Remove the hash function.
+        * kjs/property_map.cpp: Added statistics for rehashes and removes.
+        Moved from linear probing to double hashing, using the hash modulo
+        (table size minus one) plus one for the probing distance.
+
+        * kjs/ustring.h: Use unsigned instead of int for hash function result.
+
 === Safari-75 ===
 
 === Safari-74 ===
diff --git a/JavaScriptCore/kjs/property_map.cpp b/JavaScriptCore/kjs/property_map.cpp
index 10fad9f..345241d 100644
--- a/JavaScriptCore/kjs/property_map.cpp
+++ b/JavaScriptCore/kjs/property_map.cpp
@@ -41,6 +41,8 @@ namespace KJS {
 
 static int numProbes;
 static int numCollisions;
+static int numRehashes;
+static int numRemoves;
 
 struct PropertyMapStatisticsExitLogger { ~PropertyMapStatisticsExitLogger(); };
 
@@ -51,6 +53,8 @@ PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
     printf("\nKJS::PropertyMap statistics\n\n");
     printf("%d probes\n", numProbes);
     printf("%d collisions (%.1f%%)\n", numCollisions, 100.0 * numCollisions / numProbes);
+    printf("%d rehashes\n", numRehashes);
+    printf("%d removes\n", numRemoves);
 }
 
 #endif
@@ -97,7 +101,7 @@ PropertyMap::~PropertyMap()
     for (int i = 0; i < _table->size; i++) {
         UString::Rep *key = _table->entries[i].key;
         if (key)
-	  key->deref();
+            key->deref();
     }
     free(_table);
 }
@@ -125,13 +129,10 @@ void PropertyMap::clear()
     _table->keyCount = 0;
 }
 
-inline int PropertyMap::hash(const UString::Rep *s) const
-{
-    return s->hash() & _table->sizeMask;
-}
-
 ValueImp *PropertyMap::get(const Identifier &name, int &attributes) const
 {
+    assert(!name.isNull());
+    
     UString::Rep *rep = name._ustring.rep;
     
     if (!_table) {
@@ -145,7 +146,9 @@ ValueImp *PropertyMap::get(const Identifier &name, int &attributes) const
         return 0;
     }
     
-    int i = hash(rep);
+    unsigned h = rep->hash();
+    int i = h & _table->sizeMask;
+    int k = 0;
 #if DUMP_STATISTICS
     ++numProbes;
     numCollisions += _table->entries[i].key && _table->entries[i].key != rep;
@@ -155,13 +158,20 @@ ValueImp *PropertyMap::get(const Identifier &name, int &attributes) const
             attributes = _table->entries[i].attributes;
             return _table->entries[i].value;
         }
-        i = (i + 1) & _table->sizeMask;
+        if (k == 0)
+            k = 1 | (h % _table->sizeMask);
+        i = (i + k) & _table->sizeMask;
+#if DUMP_STATISTICS
+        ++numRehashes;
+#endif
     }
     return 0;
 }
 
 ValueImp *PropertyMap::get(const Identifier &name) const
 {
+    assert(!name.isNull());
+    
     UString::Rep *rep = name._ustring.rep;
 
     if (!_table) {
@@ -173,7 +183,9 @@ ValueImp *PropertyMap::get(const Identifier &name) const
         return 0;
     }
     
-    int i = hash(rep);
+    unsigned h = rep->hash();
+    int i = h & _table->sizeMask;
+    int k = 0;
 #if DUMP_STATISTICS
     ++numProbes;
     numCollisions += _table->entries[i].key && _table->entries[i].key != rep;
@@ -181,7 +193,12 @@ ValueImp *PropertyMap::get(const Identifier &name) const
     while (UString::Rep *key = _table->entries[i].key) {
         if (rep == key)
             return _table->entries[i].value;
-        i = (i + 1) & _table->sizeMask;
+        if (k == 0)
+            k = 1 | (h % _table->sizeMask);
+        i = (i + k) & _table->sizeMask;
+#if DUMP_STATISTICS
+        ++numRehashes;
+#endif
     }
     return 0;
 }
@@ -190,30 +207,35 @@ ValueImp *PropertyMap::get(const Identifier &name) const
 static void printAttributes(int attributes)
 {
     if (attributes == 0)
-        printf ("None ");
-    if (attributes & ReadOnly)
-        printf ("ReadOnly ");
-    if (attributes & DontEnum)
-        printf ("DontEnum ");
-    if (attributes & DontDelete)
-        printf ("DontDelete ");
-    if (attributes & Internal)
-        printf ("Internal ");
-    if (attributes & Function)
-        printf ("Function ");
+        printf("None");
+    else {
+        if (attributes & ReadOnly)
+            printf("ReadOnly ");
+        if (attributes & DontEnum)
+            printf("DontEnum ");
+        if (attributes & DontDelete)
+            printf("DontDelete ");
+        if (attributes & Internal)
+            printf("Internal ");
+        if (attributes & Function)
+            printf("Function ");
+    }
 }
 #endif
 
 void PropertyMap::put(const Identifier &name, ValueImp *value, int attributes)
 {
+    assert(!name.isNull());
+    assert(value != 0);
+    
     checkConsistency();
 
     UString::Rep *rep = name._ustring.rep;
     
 #if DEBUG_PROPERTIES
-    printf ("adding property %s, attributes = 0x%08x (", name.ascii(), attributes);
+    printf("adding property %s, attributes = 0x%08x (", name.ascii(), attributes);
     printAttributes(attributes);
-    printf (")\n");
+    printf(")\n");
 #endif
     
 #if USE_SINGLE_ENTRY
@@ -238,7 +260,9 @@ void PropertyMap::put(const Identifier &name, ValueImp *value, int attributes)
     if (!_table || _table->keyCount * 2 >= _table->size)
         expand();
     
-    int i = hash(rep);
+    unsigned h = rep->hash();
+    int i = h & _table->sizeMask;
+    int k = 0;
 #if DUMP_STATISTICS
     ++numProbes;
     numCollisions += _table->entries[i].key && _table->entries[i].key != rep;
@@ -250,7 +274,17 @@ void PropertyMap::put(const Identifier &name, ValueImp *value, int attributes)
             // Attributes are intentionally not updated.
             return;
         }
-        i = (i + 1) & _table->sizeMask;
+        // If we find the deleted-element sentinel, insert on top of it.
+        if (key == &UString::Rep::null) {
+            key->deref();
+            break;
+        }
+        if (k == 0)
+            k = 1 | (h % _table->sizeMask);
+        i = (i + k) & _table->sizeMask;
+#if DUMP_STATISTICS
+        ++numRehashes;
+#endif
     }
     
     // Create a new hash table entry.
@@ -263,17 +297,26 @@ void PropertyMap::put(const Identifier &name, ValueImp *value, int attributes)
     checkConsistency();
 }
 
-inline void PropertyMap::insert(UString::Rep *key, ValueImp *value, int attributes)
+void PropertyMap::insert(UString::Rep *key, ValueImp *value, int attributes)
 {
     assert(_table);
 
-    int i = hash(key);
+    unsigned h = key->hash();
+    int i = h & _table->sizeMask;
+    int k = 0;
 #if DUMP_STATISTICS
     ++numProbes;
     numCollisions += _table->entries[i].key && _table->entries[i].key != key;
 #endif
-    while (_table->entries[i].key)
-        i = (i + 1) & _table->sizeMask;
+    while (_table->entries[i].key) {
+        assert(_table->entries[i].key != &UString::Rep::null);
+        if (k == 0)
+            k = 1 | (h % _table->sizeMask);
+        i = (i + k) & _table->sizeMask;
+#if DUMP_STATISTICS
+        ++numRehashes;
+#endif
+    }
     
     _table->entries[i].key = key;
     _table->entries[i].value = value;
@@ -302,8 +345,13 @@ void PropertyMap::expand()
     
     for (int i = 0; i != oldTableSize; ++i) {
         UString::Rep *key = oldTable->entries[i].key;
-        if (key)
-            insert(key, oldTable->entries[i].value, oldTable->entries[i].attributes);
+        if (key) {
+            // Don't copy deleted-element sentinels.
+            if (key == &UString::Rep::null)
+                key->deref();
+            else
+                insert(key, oldTable->entries[i].value, oldTable->entries[i].attributes);
+        }
     }
 
     free(oldTable);
@@ -313,6 +361,8 @@ void PropertyMap::expand()
 
 void PropertyMap::remove(const Identifier &name)
 {
+    assert(!name.isNull());
+    
     checkConsistency();
 
     UString::Rep *rep = name._ustring.rep;
@@ -332,35 +382,39 @@ void PropertyMap::remove(const Identifier &name)
     }
 
     // Find the thing to remove.
-    int i = hash(rep);
+    unsigned h = rep->hash();
+    int i = h & _table->sizeMask;
+    int k = 0;
 #if DUMP_STATISTICS
     ++numProbes;
+    ++numRemoves;
     numCollisions += _table->entries[i].key && _table->entries[i].key != rep;
 #endif
     while ((key = _table->entries[i].key)) {
         if (rep == key)
             break;
-        i = (i + 1) & _table->sizeMask;
+        if (k == 0)
+            k = 1 | (h % _table->sizeMask);
+        i = (i + k) & _table->sizeMask;
+#if DUMP_STATISTICS
+        ++numRehashes;
+#endif
     }
     if (!key)
         return;
     
-    // Remove the one key.
+    // Replace this one element with the deleted sentinel,
+    // &UString::Rep::null; also set value to 0 and attributes to DontEnum
+    // to help callers that iterate all keys not have to check for the sentinel.
     key->deref();
-    _table->entries[i].key = 0;
+    key = &UString::Rep::null;
+    key->ref();
+    _table->entries[i].key = key;
+    _table->entries[i].value = 0;
+    _table->entries[i].attributes = DontEnum;
     assert(_table->keyCount >= 1);
     --_table->keyCount;
     
-    // Reinsert all the items to the right in the same cluster.
-    while (1) {
-        i = (i + 1) & _table->sizeMask;
-        key = _table->entries[i].key;
-        if (!key)
-            break;
-        _table->entries[i].key = 0;
-        insert(key, _table->entries[i].value, _table->entries[i].attributes);
-    }
-
     checkConsistency();
 }
 
@@ -378,9 +432,12 @@ void PropertyMap::mark() const
     }
 
     for (int i = 0; i != _table->size; ++i) {
-        if (_table->entries[i].key) {
+        UString::Rep *key = _table->entries[i].key;
+        if (key) {
             ValueImp *v = _table->entries[i].value;
-            if (!v->marked())
+            // Check v against 0 to handle deleted elements
+            // without comparing key to UString::Rep::null.
+            if (v && !v->marked())
                 v->mark();
         }
     }
@@ -422,7 +479,8 @@ void PropertyMap::addSparseArrayPropertiesToReferenceList(ReferenceList &list, c
 
     for (int i = 0; i != _table->size; ++i) {
         UString::Rep *key = _table->entries[i].key;
-        if (key) {
+        if (key && key != &UString::Rep::null)
+        {
             UString k(key);
             bool fitsInUInt32;
             k.toUInt32(&fitsInUInt32);
@@ -499,7 +557,8 @@ void PropertyMap::checkConsistency()
         UString::Rep *rep = _table->entries[j].key;
         if (!rep)
             continue;
-        int i = hash(rep);
+        unsigned h = rep->hash();
+        int i = h & _table->sizeMask;
         while (UString::Rep *key = _table->entries[i].key) {
             if (rep == key)
                 break;
diff --git a/JavaScriptCore/kjs/property_map.h b/JavaScriptCore/kjs/property_map.h
index 033578b..6f26e51 100644
--- a/JavaScriptCore/kjs/property_map.h
+++ b/JavaScriptCore/kjs/property_map.h
@@ -77,7 +77,6 @@ namespace KJS {
         void restore(const SavedProperties &p);
 
     private:
-        int hash(const UString::Rep *) const;
         static bool keysMatch(const UString::Rep *, const UString::Rep *);
         void expand();
         
diff --git a/JavaScriptCore/kjs/ustring.h b/JavaScriptCore/kjs/ustring.h
index 0d374f0..8232913 100644
--- a/JavaScriptCore/kjs/ustring.h
+++ b/JavaScriptCore/kjs/ustring.h
@@ -213,7 +213,7 @@ namespace KJS {
       UChar *data() const { return dat; }
       int size() const { return len; }
       
-      int hash() const { if (_hash == 0) _hash = computeHash(dat, len); return _hash; }
+      unsigned hash() const { if (_hash == 0) _hash = computeHash(dat, len); return _hash; }
       static unsigned computeHash(const UChar *, int length);
       static unsigned computeHash(const char *);
 
@@ -224,7 +224,7 @@ namespace KJS {
       int len;
       int capacity;
       int rc;
-      mutable int _hash;
+      mutable unsigned _hash;
       
       enum { capacityForIdentifier = 0x10000000 };
       

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list