From 7aba7e6dac70e40980070d6086521ec8fc4eb709 Mon Sep 17 00:00:00 2001 From: "crowder%fiverocks.com" Date: Wed, 30 Jan 2008 02:36:33 +0000 Subject: [PATCH] Bug 331043 - Improve hash performance using _rotr intrinsic (js/src hunk), patch by Michael Moy with updates by me and r=wtc, r=brendan, a=brendan git-svn-id: svn://10.0.0.236/trunk@244447 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js/src/jsbit.h | 18 ++++++++++++++++++ mozilla/js/src/jsdhash.c | 2 +- mozilla/js/src/jshash.c | 2 +- mozilla/js/src/jsscope.c | 14 +++++++------- mozilla/js/src/jsstr.c | 3 ++- mozilla/js/src/liveconnect/jsj_hash.c | 2 +- mozilla/js/src/xpconnect/src/xpcmaps.cpp | 3 ++- 7 files changed, 32 insertions(+), 12 deletions(-) diff --git a/mozilla/js/src/jsbit.h b/mozilla/js/src/jsbit.h index 896c8889ea8..e11bb97e8ce 100644 --- a/mozilla/js/src/jsbit.h +++ b/mozilla/js/src/jsbit.h @@ -227,6 +227,24 @@ extern JSUword js_FloorLog2wImpl(JSUword n); #endif +/* + * Macros for rotate left. There is no rotate operation in the C Language so + * the construct (a << 4) | (a >> 28) is used instead. Most compilers convert + * this to a rotate instruction but some versions of MSVC don't without a + * little help. To get MSVC to generate a rotate instruction, we have to use + * the _rotl intrinsic and use a pragma to make _rotl inline. + * + * MSVC in VS2005 will do an inline rotate instruction on the above construct. + */ + +#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \ + defined(_M_X64)) +#include +#pragma intrinsic(_rotl) +#define JS_ROTATE_LEFT32(a, bits) _rotl(a, bits) +#else +#define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits)))) +#endif JS_END_EXTERN_C #endif /* jsbit_h___ */ diff --git a/mozilla/js/src/jsdhash.c b/mozilla/js/src/jsdhash.c index 8db9d709615..830a5953bd9 100644 --- a/mozilla/js/src/jsdhash.c +++ b/mozilla/js/src/jsdhash.c @@ -103,7 +103,7 @@ JS_DHashStringKey(JSDHashTable *table, const void *key) h = 0; for (s = (const unsigned char *) key; *s != '\0'; s++) - h = (h >> (JS_DHASH_BITS - 4)) ^ (h << 4) ^ *s; + h = JS_ROTATE_LEFT32(h, 4) ^ *s; return h; } diff --git a/mozilla/js/src/jshash.c b/mozilla/js/src/jshash.c index 7b9adaedb6c..5fe5f7839c4 100644 --- a/mozilla/js/src/jshash.c +++ b/mozilla/js/src/jshash.c @@ -465,7 +465,7 @@ JS_HashString(const void *key) h = 0; for (s = (const unsigned char *)key; *s; s++) - h = (h >> (JS_HASH_BITS - 4)) ^ (h << 4) ^ *s; + h = JS_ROTATE_LEFT32(h, 4) ^ *s; return h; } diff --git a/mozilla/js/src/jsscope.c b/mozilla/js/src/jsscope.c index 151c6554735..2d1ac317405 100644 --- a/mozilla/js/src/jsscope.c +++ b/mozilla/js/src/jsscope.c @@ -403,18 +403,18 @@ js_HashScopeProperty(JSDHashTable *table, const void *key) hash = 0; gsop = sprop->getter; if (gsop) - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ (jsword)gsop; + hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsword)gsop; gsop = sprop->setter; if (gsop) - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ (jsword)gsop; + hash = JS_ROTATE_LEFT32(hash, 4) ^ (jsword)gsop; - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) + hash = JS_ROTATE_LEFT32(hash, 4) ^ (sprop->flags & ~SPROP_FLAGS_NOT_MATCHED); - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->attrs; - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->shortid; - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->slot; - hash = (hash >> (JS_DHASH_BITS - 4)) ^ (hash << 4) ^ sprop->id; + hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->attrs; + hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->shortid; + hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->slot; + hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->id; return hash; } diff --git a/mozilla/js/src/jsstr.c b/mozilla/js/src/jsstr.c index cc8df1ceafa..0f2587b7c15 100644 --- a/mozilla/js/src/jsstr.c +++ b/mozilla/js/src/jsstr.c @@ -69,6 +69,7 @@ #include "jsopcode.h" #include "jsregexp.h" #include "jsstr.h" +#include "jsbit.h" #define JSSTRDEP_RECURSION_LIMIT 100 @@ -2768,7 +2769,7 @@ js_HashString(JSString *str) JSSTRING_CHARS_AND_LENGTH(str, s, n); for (h = 0; n; s++, n--) - h = (h >> (JS_HASH_BITS - 4)) ^ (h << 4) ^ *s; + h = JS_ROTATE_LEFT32(h, 4) ^ *s; return h; } diff --git a/mozilla/js/src/liveconnect/jsj_hash.c b/mozilla/js/src/liveconnect/jsj_hash.c index ca9d4941837..001b279edbd 100644 --- a/mozilla/js/src/liveconnect/jsj_hash.c +++ b/mozilla/js/src/liveconnect/jsj_hash.c @@ -471,7 +471,7 @@ JSJ_HashString(const void *key) h = 0; for (s = key; *s; s++) - h = (h >> 28) ^ (h << 4) ^ *s; + h = JS_ROTATE_LEFT32(h, 4) ^ *s; return h; } diff --git a/mozilla/js/src/xpconnect/src/xpcmaps.cpp b/mozilla/js/src/xpconnect/src/xpcmaps.cpp index 6dc112c9ff1..162d77a385d 100644 --- a/mozilla/js/src/xpconnect/src/xpcmaps.cpp +++ b/mozilla/js/src/xpconnect/src/xpcmaps.cpp @@ -41,6 +41,7 @@ /* Private maps (hashtables). */ #include "xpcprivate.h" +#include "jsbit.h" /***************************************************************************/ // static shared... @@ -504,7 +505,7 @@ XPCNativeScriptableSharedMap::Entry::Hash(JSDHashTable *table, const void *key) h = (JSDHashNumber) obj->GetFlags(); for (s = (const unsigned char*) obj->GetJSClass()->name; *s != '\0'; s++) - h = (h >> (JS_DHASH_BITS - 4)) ^ (h << 4) ^ *s; + h = JS_ROTATE_LEFT32(h, 4) ^ *s; return h; }