mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-02 07:05:24 +00:00
Use thread-local RNG for Math.random() (511328, r=shaver,waldo).
This commit is contained in:
parent
0c97581323
commit
b4232322c2
@ -58,6 +58,7 @@
|
|||||||
#include "jsfun.h"
|
#include "jsfun.h"
|
||||||
#include "jsgc.h"
|
#include "jsgc.h"
|
||||||
#include "jslock.h"
|
#include "jslock.h"
|
||||||
|
#include "jsmath.h"
|
||||||
#include "jsnum.h"
|
#include "jsnum.h"
|
||||||
#include "jsobj.h"
|
#include "jsobj.h"
|
||||||
#include "jsopcode.h"
|
#include "jsopcode.h"
|
||||||
@ -83,6 +84,7 @@ InitThreadData(JSThreadData *data)
|
|||||||
#ifdef JS_TRACER
|
#ifdef JS_TRACER
|
||||||
js_InitJIT(&data->traceMonitor);
|
js_InitJIT(&data->traceMonitor);
|
||||||
#endif
|
#endif
|
||||||
|
js_InitRandom(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -250,6 +250,9 @@ struct JSThreadData {
|
|||||||
/* Property cache for faster call/get/set invocation. */
|
/* Property cache for faster call/get/set invocation. */
|
||||||
JSPropertyCache propertyCache;
|
JSPropertyCache propertyCache;
|
||||||
|
|
||||||
|
/* Random number generator state, used by jsmath.cpp. */
|
||||||
|
int64 rngSeed;
|
||||||
|
|
||||||
#ifdef JS_TRACER
|
#ifdef JS_TRACER
|
||||||
/* Trace-tree JIT recorder/interpreter state. */
|
/* Trace-tree JIT recorder/interpreter state. */
|
||||||
JSTraceMonitor traceMonitor;
|
JSTraceMonitor traceMonitor;
|
||||||
@ -456,14 +459,6 @@ struct JSRuntime {
|
|||||||
*/
|
*/
|
||||||
JSSetSlotRequest *setSlotRequests;
|
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. */
|
/* Well-known numbers held for use by this runtime's contexts. */
|
||||||
jsdouble *jsNaN;
|
jsdouble *jsNaN;
|
||||||
jsdouble *jsNegativeInfinity;
|
jsdouble *jsNegativeInfinity;
|
||||||
|
@ -427,90 +427,47 @@ math_pow(JSContext *cx, uintN argc, jsval *vp)
|
|||||||
return js_NewNumberInRootedValue(cx, z, 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.
|
* Math.random() support, lifted from java.util.Random.java.
|
||||||
*/
|
*/
|
||||||
static void
|
static inline void
|
||||||
random_setSeed(JSRuntime *rt, int64 seed)
|
random_setSeed(JSThreadData *data, int64 seed)
|
||||||
{
|
{
|
||||||
int64 tmp;
|
data->rngSeed = (seed ^ RNG_MULTIPLIER) & RNG_MASK;
|
||||||
|
|
||||||
JSLL_I2L(tmp, 1000);
|
|
||||||
JSLL_DIV(seed, seed, tmp);
|
|
||||||
JSLL_XOR(tmp, seed, rt->rngMultiplier);
|
|
||||||
JSLL_AND(rt->rngSeed, tmp, rt->rngMask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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. */
|
/* Finally, set the seed from current time. */
|
||||||
random_setSeed(rt, PRMJ_Now());
|
random_setSeed(data, PRMJ_Now() / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32
|
static inline uint64
|
||||||
random_next(JSRuntime *rt, int bits)
|
random_next(JSThreadData *data, int bits)
|
||||||
{
|
{
|
||||||
int64 nextseed, tmp;
|
uint64 nextseed = data->rngSeed * RNG_MULTIPLIER;
|
||||||
uint32 retval;
|
nextseed += RNG_ADDEND;
|
||||||
|
nextseed &= RNG_MASK;
|
||||||
JSLL_MUL(nextseed, rt->rngSeed, rt->rngMultiplier);
|
data->rngSeed = nextseed;
|
||||||
JSLL_ADD(nextseed, nextseed, rt->rngAddend);
|
return nextseed >> (48 - bits);
|
||||||
JSLL_AND(nextseed, nextseed, rt->rngMask);
|
|
||||||
rt->rngSeed = nextseed;
|
|
||||||
JSLL_USHR(tmp, nextseed, 48 - bits);
|
|
||||||
JSLL_L2I(retval, tmp);
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jsdouble
|
static inline jsdouble
|
||||||
js_random_nextDouble(JSRuntime *rt)
|
random_nextDouble(JSThreadData *data)
|
||||||
{
|
{
|
||||||
int64 tmp, tmp2;
|
return jsdouble((random_next(data, 26) << 27) + random_next(data, 27)) / RNG_DSCALE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
math_random(JSContext *cx, uintN argc, jsval *vp)
|
math_random(JSContext *cx, uintN argc, jsval *vp)
|
||||||
{
|
{
|
||||||
JSRuntime *rt;
|
jsdouble z = random_nextDouble(JS_THREAD_DATA(cx));
|
||||||
jsdouble z;
|
|
||||||
|
|
||||||
rt = cx->runtime;
|
|
||||||
JS_LOCK_RUNTIME(rt);
|
|
||||||
js_random_init(rt);
|
|
||||||
z = js_random_nextDouble(rt);
|
|
||||||
JS_UNLOCK_RUNTIME(rt);
|
|
||||||
return js_NewNumberInRootedValue(cx, z, vp);
|
return js_NewNumberInRootedValue(cx, z, vp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,13 +673,9 @@ math_pow_tn(jsdouble d, jsdouble p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static jsdouble FASTCALL
|
static jsdouble FASTCALL
|
||||||
math_random_tn(JSRuntime* rt)
|
math_random_tn(JSContext *cx)
|
||||||
{
|
{
|
||||||
JS_LOCK_RUNTIME(rt);
|
return random_nextDouble(JS_THREAD_DATA(cx));
|
||||||
js_random_init(rt);
|
|
||||||
jsdouble z = js_random_nextDouble(rt);
|
|
||||||
JS_UNLOCK_RUNTIME(rt);
|
|
||||||
return z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static jsdouble FASTCALL
|
static jsdouble FASTCALL
|
||||||
@ -752,7 +705,7 @@ JS_DEFINE_TRCINFO_1(math_min,
|
|||||||
JS_DEFINE_TRCINFO_1(math_pow,
|
JS_DEFINE_TRCINFO_1(math_pow,
|
||||||
(2, (static, DOUBLE, math_pow_tn, DOUBLE, DOUBLE, 1, 1)))
|
(2, (static, DOUBLE, math_pow_tn, DOUBLE, DOUBLE, 1, 1)))
|
||||||
JS_DEFINE_TRCINFO_1(math_random,
|
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,
|
JS_DEFINE_TRCINFO_1(math_round,
|
||||||
(1, (static, DOUBLE, math_round_tn, DOUBLE, 1, 1)))
|
(1, (static, DOUBLE, math_round_tn, DOUBLE, 1, 1)))
|
||||||
JS_DEFINE_TRCINFO_1(math_ceil,
|
JS_DEFINE_TRCINFO_1(math_ceil,
|
||||||
|
@ -51,10 +51,7 @@ extern JSObject *
|
|||||||
js_InitMathClass(JSContext *cx, JSObject *obj);
|
js_InitMathClass(JSContext *cx, JSObject *obj);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
js_random_init(JSRuntime *rt);
|
js_InitRandom(JSThreadData *data);
|
||||||
|
|
||||||
extern jsdouble
|
|
||||||
js_random_nextDouble(JSRuntime *rt);
|
|
||||||
|
|
||||||
JS_END_EXTERN_C
|
JS_END_EXTERN_C
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user