From 9a78cb5d5f5d97fa735f4272c434c524b781bb31 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Wed, 19 Aug 2009 15:23:54 -0700 Subject: [PATCH] Use thread-local RNG for Math.random() (511328, r=shaver,waldo). --- js/src/jscntxt.cpp | 2 + js/src/jscntxt.h | 11 ++---- js/src/jsmath.cpp | 95 ++++++++++++---------------------------------- js/src/jsmath.h | 5 +-- 4 files changed, 30 insertions(+), 83 deletions(-) diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 97b5d60abfd..ce93c37c36e 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -58,6 +58,7 @@ #include "jsfun.h" #include "jsgc.h" #include "jslock.h" +#include "jsmath.h" #include "jsnum.h" #include "jsobj.h" #include "jsopcode.h" @@ -83,6 +84,7 @@ InitThreadData(JSThreadData *data) #ifdef JS_TRACER js_InitJIT(&data->traceMonitor); #endif + js_InitRandom(data); } static void diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index af79b64bd3e..0a24cd140e0 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -250,6 +250,9 @@ struct JSThreadData { /* Property cache for faster call/get/set invocation. */ JSPropertyCache propertyCache; + /* Random number generator state, used by jsmath.cpp. */ + int64 rngSeed; + #ifdef JS_TRACER /* Trace-tree JIT recorder/interpreter state. */ JSTraceMonitor traceMonitor; @@ -456,14 +459,6 @@ struct JSRuntime { */ JSSetSlotRequest *setSlotRequests; - /* Random number generator state, used by jsmath.c. */ - JSBool rngInitialized; - int64 rngMultiplier; - int64 rngAddend; - int64 rngMask; - int64 rngSeed; - jsdouble rngDscale; - /* Well-known numbers held for use by this runtime's contexts. */ jsdouble *jsNaN; jsdouble *jsNegativeInfinity; diff --git a/js/src/jsmath.cpp b/js/src/jsmath.cpp index dd6fd51665c..cd805f18cab 100644 --- a/js/src/jsmath.cpp +++ b/js/src/jsmath.cpp @@ -427,90 +427,47 @@ math_pow(JSContext *cx, uintN argc, jsval *vp) return js_NewNumberInRootedValue(cx, z, vp); } +static const int64 RNG_MULTIPLIER = 0x5DEECE66DLL; +static const int64 RNG_ADDEND = 0xBLL; +static const int64 RNG_MASK = (1LL << 48) - 1; +static const jsdouble RNG_DSCALE = jsdouble(1LL << 53); + /* * Math.random() support, lifted from java.util.Random.java. */ -static void -random_setSeed(JSRuntime *rt, int64 seed) +static inline void +random_setSeed(JSThreadData *data, int64 seed) { - int64 tmp; - - JSLL_I2L(tmp, 1000); - JSLL_DIV(seed, seed, tmp); - JSLL_XOR(tmp, seed, rt->rngMultiplier); - JSLL_AND(rt->rngSeed, tmp, rt->rngMask); + data->rngSeed = (seed ^ RNG_MULTIPLIER) & RNG_MASK; } void -js_random_init(JSRuntime *rt) +js_InitRandom(JSThreadData *data) { - int64 tmp, tmp2; - - /* Do at most once. */ - if (rt->rngInitialized) - return; - rt->rngInitialized = JS_TRUE; - - /* rt->rngMultiplier = 0x5DEECE66DL */ - JSLL_ISHL(tmp, 0x5, 32); - JSLL_UI2L(tmp2, 0xDEECE66DL); - JSLL_OR(rt->rngMultiplier, tmp, tmp2); - - /* rt->rngAddend = 0xBL */ - JSLL_I2L(rt->rngAddend, 0xBL); - - /* rt->rngMask = (1L << 48) - 1 */ - JSLL_I2L(tmp, 1); - JSLL_SHL(tmp2, tmp, 48); - JSLL_SUB(rt->rngMask, tmp2, tmp); - - /* rt->rngDscale = (jsdouble)(1L << 53) */ - JSLL_SHL(tmp2, tmp, 53); - JSLL_L2D(rt->rngDscale, tmp2); - /* Finally, set the seed from current time. */ - random_setSeed(rt, PRMJ_Now()); + random_setSeed(data, PRMJ_Now() / 1000); } -static uint32 -random_next(JSRuntime *rt, int bits) +static inline uint64 +random_next(JSThreadData *data, int bits) { - int64 nextseed, tmp; - uint32 retval; - - JSLL_MUL(nextseed, rt->rngSeed, rt->rngMultiplier); - JSLL_ADD(nextseed, nextseed, rt->rngAddend); - JSLL_AND(nextseed, nextseed, rt->rngMask); - rt->rngSeed = nextseed; - JSLL_USHR(tmp, nextseed, 48 - bits); - JSLL_L2I(retval, tmp); - return retval; + uint64 nextseed = data->rngSeed * RNG_MULTIPLIER; + nextseed += RNG_ADDEND; + nextseed &= RNG_MASK; + data->rngSeed = nextseed; + return nextseed >> (48 - bits); } -jsdouble -js_random_nextDouble(JSRuntime *rt) +static inline jsdouble +random_nextDouble(JSThreadData *data) { - int64 tmp, tmp2; - jsdouble d; - - JSLL_ISHL(tmp, random_next(rt, 26), 27); - JSLL_UI2L(tmp2, random_next(rt, 27)); - JSLL_ADD(tmp, tmp, tmp2); - JSLL_L2D(d, tmp); - return d / rt->rngDscale; + return jsdouble((random_next(data, 26) << 27) + random_next(data, 27)) / RNG_DSCALE; } static JSBool math_random(JSContext *cx, uintN argc, jsval *vp) { - JSRuntime *rt; - jsdouble z; - - rt = cx->runtime; - JS_LOCK_RUNTIME(rt); - js_random_init(rt); - z = js_random_nextDouble(rt); - JS_UNLOCK_RUNTIME(rt); + jsdouble z = random_nextDouble(JS_THREAD_DATA(cx)); return js_NewNumberInRootedValue(cx, z, vp); } @@ -716,13 +673,9 @@ math_pow_tn(jsdouble d, jsdouble p) } static jsdouble FASTCALL -math_random_tn(JSRuntime* rt) +math_random_tn(JSContext *cx) { - JS_LOCK_RUNTIME(rt); - js_random_init(rt); - jsdouble z = js_random_nextDouble(rt); - JS_UNLOCK_RUNTIME(rt); - return z; + return random_nextDouble(JS_THREAD_DATA(cx)); } static jsdouble FASTCALL @@ -752,7 +705,7 @@ JS_DEFINE_TRCINFO_1(math_min, JS_DEFINE_TRCINFO_1(math_pow, (2, (static, DOUBLE, math_pow_tn, DOUBLE, DOUBLE, 1, 1))) JS_DEFINE_TRCINFO_1(math_random, - (1, (static, DOUBLE, math_random_tn, RUNTIME, 0, 0))) + (1, (static, DOUBLE, math_random_tn, CONTEXT, 0, 0))) JS_DEFINE_TRCINFO_1(math_round, (1, (static, DOUBLE, math_round_tn, DOUBLE, 1, 1))) JS_DEFINE_TRCINFO_1(math_ceil, diff --git a/js/src/jsmath.h b/js/src/jsmath.h index 63c8741945e..d6c67814374 100644 --- a/js/src/jsmath.h +++ b/js/src/jsmath.h @@ -51,10 +51,7 @@ extern JSObject * js_InitMathClass(JSContext *cx, JSObject *obj); extern void -js_random_init(JSRuntime *rt); - -extern jsdouble -js_random_nextDouble(JSRuntime *rt); +js_InitRandom(JSThreadData *data); JS_END_EXTERN_C