mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 14:45:29 +00:00
bug=400902 r,a1.9=brendan Specialized GC arena for double values
This commit is contained in:
parent
dbd13fd08e
commit
663a089f9a
@ -85,7 +85,7 @@ MSG_DEF(JSMSG_INACTIVE, 2, 0, JSEXN_INTERNALERR, "nothing active
|
||||
MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, 3, JSEXN_TYPEERR, "{0} requires more than {1} argument{2}")
|
||||
MSG_DEF(JSMSG_BAD_CHAR, 4, 1, JSEXN_INTERNALERR, "invalid format character {0}")
|
||||
MSG_DEF(JSMSG_BAD_TYPE, 5, 1, JSEXN_TYPEERR, "unknown type {0}")
|
||||
MSG_DEF(JSMSG_CANT_LOCK, 6, 0, JSEXN_INTERNALERR, "can't lock memory")
|
||||
MSG_DEF(JSMSG_UNUSED6, 6, 0, JSEXN_NONE, "")
|
||||
MSG_DEF(JSMSG_CANT_UNLOCK, 7, 0, JSEXN_INTERNALERR, "can't unlock memory")
|
||||
MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 8, 3, JSEXN_TYPEERR, "{0}.prototype.{1} called on incompatible {2}")
|
||||
MSG_DEF(JSMSG_NO_CONSTRUCTOR, 9, 1, JSEXN_TYPEERR, "{0} has no constructor")
|
||||
|
@ -489,7 +489,7 @@ JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
|
||||
case JSTYPE_NUMBER:
|
||||
ok = js_ValueToNumber(cx, v, &d);
|
||||
if (ok) {
|
||||
dp = js_NewDouble(cx, d, 0);
|
||||
dp = js_NewDouble(cx, d);
|
||||
ok = (dp != NULL);
|
||||
if (ok)
|
||||
*vp = DOUBLE_TO_JSVAL(dp);
|
||||
@ -1768,7 +1768,7 @@ JS_PUBLIC_API(jsdouble *)
|
||||
JS_NewDouble(JSContext *cx, jsdouble d)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
return js_NewDouble(cx, d, 0);
|
||||
return js_NewDouble(cx, d);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
@ -1877,9 +1877,9 @@ JS_LockGCThing(JSContext *cx, void *thing)
|
||||
JSBool ok;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
ok = js_LockGCThing(cx, thing);
|
||||
ok = js_LockGCThingRT(cx->runtime, thing);
|
||||
if (!ok)
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_LOCK);
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -586,7 +586,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
|
||||
gen = ++table->generation;
|
||||
JS_UNLOCK(&state->lock, cx);
|
||||
|
||||
key = js_NewDouble(cx, d, 0);
|
||||
key = js_NewDouble(cx, d);
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
|
@ -187,6 +187,7 @@ struct JSRuntime {
|
||||
/* Garbage collector state, used by jsgc.c. */
|
||||
JSGCChunkInfo *gcChunkList;
|
||||
JSGCArenaList gcArenaList[GC_NUM_FREELISTS];
|
||||
JSGCDoubleArenaList gcDoubleArenaList;
|
||||
JSDHashTable gcRootsHash;
|
||||
JSDHashTable *gcLocksHash;
|
||||
jsrefcount gcKeepAtoms;
|
||||
@ -787,6 +788,9 @@ struct JSContext {
|
||||
/* Stack of thread-stack-allocated temporary GC roots. */
|
||||
JSTempValueRooter *tempValueRooters;
|
||||
|
||||
/* List of pre-allocated doubles. */
|
||||
JSGCDoubleCell *doubleFreeList;
|
||||
|
||||
/* Debug hooks associated with the current context. */
|
||||
JSDebugHooks *debugHooks;
|
||||
};
|
||||
|
@ -963,7 +963,7 @@ SetUTCTimePtr(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
|
||||
static JSBool
|
||||
SetUTCTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble t)
|
||||
{
|
||||
jsdouble *dp = js_NewDouble(cx, t, 0);
|
||||
jsdouble *dp = js_NewDouble(cx, t);
|
||||
if (!dp)
|
||||
return JS_FALSE;
|
||||
return SetUTCTimePtr(cx, obj, vp, dp);
|
||||
@ -993,7 +993,7 @@ GetAndCacheLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = LocalTime(result);
|
||||
|
||||
cached = js_NewDouble(cx, result, 0);
|
||||
cached = js_NewDouble(cx, result);
|
||||
if (!cached)
|
||||
return JS_FALSE;
|
||||
|
||||
@ -2019,7 +2019,7 @@ date_constructor(JSContext *cx, JSObject* obj)
|
||||
{
|
||||
jsdouble *date;
|
||||
|
||||
date = js_NewDouble(cx, 0.0, 0);
|
||||
date = js_NewDouble(cx, 0.0);
|
||||
if (!date)
|
||||
return NULL;
|
||||
|
||||
|
1109
js/src/jsgc.c
1109
js/src/jsgc.c
File diff suppressed because it is too large
Load Diff
@ -45,6 +45,7 @@
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsdhash.h"
|
||||
#include "jsbit.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
@ -202,8 +203,13 @@ struct JSGCThing {
|
||||
extern void *
|
||||
js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes);
|
||||
|
||||
extern JSBool
|
||||
js_LockGCThing(JSContext *cx, void *thing);
|
||||
/*
|
||||
* Return a pointer to a new GC-allocated and weakly rooted jsdouble number
|
||||
* or null when the allocation fails. The caller must initialize the returned
|
||||
* double.
|
||||
*/
|
||||
extern jsdouble *
|
||||
js_NewDoubleGCThing(JSContext *cx);
|
||||
|
||||
extern JSBool
|
||||
js_LockGCThingRT(JSRuntime *rt, void *thing);
|
||||
@ -303,6 +309,21 @@ struct JSGCArenaList {
|
||||
JSGCThing *freeList; /* list of free GC things */
|
||||
};
|
||||
|
||||
typedef union JSGCDoubleCell JSGCDoubleCell;
|
||||
|
||||
union JSGCDoubleCell {
|
||||
double number;
|
||||
JSGCDoubleCell *link;
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSGCDoubleCell) == sizeof(double));
|
||||
|
||||
typedef struct JSGCDoubleArenaList {
|
||||
JSGCArenaInfo *first; /* first allocated GC arena */
|
||||
uint8 *nextDoubleFlags; /* bitmask with flags to check for free
|
||||
things */
|
||||
} JSGCDoubleArenaList;
|
||||
|
||||
struct JSWeakRoots {
|
||||
/* Most recently created things by type, members of the GC's root set. */
|
||||
void *newborn[GCX_NTYPES];
|
||||
@ -324,28 +345,22 @@ JS_STATIC_ASSERT(JSVAL_NULL == 0);
|
||||
#ifdef JS_GCMETER
|
||||
|
||||
typedef struct JSGCArenaStats {
|
||||
uint32 narenas; /* number of arena in list */
|
||||
uint32 maxarenas; /* maximun number of allocated arenas */
|
||||
uint32 nthings; /* number of allocates JSGCThing */
|
||||
uint32 maxthings; /* maximum number number of allocates JSGCThing */
|
||||
uint32 totalnew; /* number of succeeded calls to js_NewGCThing */
|
||||
uint32 freelen; /* freeList lengths */
|
||||
uint32 recycle; /* number of things recycled through freeList */
|
||||
uint32 alloc; /* allocation attempts */
|
||||
uint32 localalloc; /* allocations from local lists */
|
||||
uint32 retry; /* allocation retries after running the GC */
|
||||
uint32 fail; /* allocation failures */
|
||||
uint32 nthings; /* live GC things */
|
||||
uint32 maxthings; /* maximum of live GC cells */
|
||||
double totalthings; /* live GC things the GC scanned so far */
|
||||
uint32 narenas; /* number of arena in list before the GC */
|
||||
uint32 newarenas; /* new arenas allocated before the last GC */
|
||||
uint32 livearenas; /* number of live arenas after the last GC */
|
||||
uint32 maxarenas; /* maximum of allocated arenas */
|
||||
uint32 totalarenas; /* total number of arenas with live things that
|
||||
GC scanned so far */
|
||||
uint32 totalfreelen; /* total number of things that GC put to free
|
||||
list so far */
|
||||
} JSGCArenaStats;
|
||||
|
||||
typedef struct JSGCStats {
|
||||
#ifdef JS_THREADSAFE
|
||||
uint32 localalloc; /* number of succeeded allocations from local lists */
|
||||
#endif
|
||||
uint32 alloc; /* number of allocation attempts */
|
||||
uint32 retry; /* allocation attempt retries after running the GC */
|
||||
uint32 retryhalt; /* allocation retries halted by the operation
|
||||
callback */
|
||||
uint32 fail; /* allocation failures */
|
||||
uint32 finalfail; /* finalizer calls allocator failures */
|
||||
uint32 lockborn; /* things born locked */
|
||||
uint32 lock; /* valid lock calls */
|
||||
@ -370,7 +385,8 @@ typedef struct JSGCStats {
|
||||
uint32 closelater; /* number of close hooks scheduled to run */
|
||||
uint32 maxcloselater; /* max number of close hooks scheduled to run */
|
||||
|
||||
JSGCArenaStats arenas[GC_NUM_FREELISTS];
|
||||
JSGCArenaStats arenaStats[GC_NUM_FREELISTS];
|
||||
JSGCArenaStats doubleArenaStats;
|
||||
} JSGCStats;
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
|
@ -548,21 +548,21 @@ js_InitRuntimeNumberState(JSContext *cx)
|
||||
u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
|
||||
u.s.lo = 0xffffffff;
|
||||
number_constants[NC_NaN].dval = NaN = u.d;
|
||||
rt->jsNaN = js_NewDouble(cx, NaN, GCF_LOCK);
|
||||
rt->jsNaN = js_NewDouble(cx, NaN);
|
||||
if (!rt->jsNaN)
|
||||
return JS_FALSE;
|
||||
|
||||
u.s.hi = JSDOUBLE_HI32_EXPMASK;
|
||||
u.s.lo = 0x00000000;
|
||||
number_constants[NC_POSITIVE_INFINITY].dval = u.d;
|
||||
rt->jsPositiveInfinity = js_NewDouble(cx, u.d, GCF_LOCK);
|
||||
rt->jsPositiveInfinity = js_NewDouble(cx, u.d);
|
||||
if (!rt->jsPositiveInfinity)
|
||||
return JS_FALSE;
|
||||
|
||||
u.s.hi = JSDOUBLE_HI32_SIGNBIT | JSDOUBLE_HI32_EXPMASK;
|
||||
u.s.lo = 0x00000000;
|
||||
number_constants[NC_NEGATIVE_INFINITY].dval = u.d;
|
||||
rt->jsNegativeInfinity = js_NewDouble(cx, u.d, GCF_LOCK);
|
||||
rt->jsNegativeInfinity = js_NewDouble(cx, u.d);
|
||||
if (!rt->jsNegativeInfinity)
|
||||
return JS_FALSE;
|
||||
|
||||
@ -581,6 +581,20 @@ js_InitRuntimeNumberState(JSContext *cx)
|
||||
return rt->thousandsSeparator && rt->decimalSeparator && rt->numGrouping;
|
||||
}
|
||||
|
||||
void
|
||||
js_TraceRuntimeNumberState(JSTracer *trc)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
|
||||
rt = trc->context->runtime;
|
||||
if (rt->jsNaN)
|
||||
JS_CALL_DOUBLE_TRACER(trc, rt->jsNaN, "NaN");
|
||||
if (rt->jsPositiveInfinity)
|
||||
JS_CALL_DOUBLE_TRACER(trc, rt->jsPositiveInfinity, "+Infinity");
|
||||
if (rt->jsNegativeInfinity)
|
||||
JS_CALL_DOUBLE_TRACER(trc, rt->jsNegativeInfinity, "-Infinity");
|
||||
}
|
||||
|
||||
void
|
||||
js_FinishRuntimeNumberState(JSContext *cx)
|
||||
{
|
||||
@ -637,31 +651,26 @@ js_InitNumberClass(JSContext *cx, JSObject *obj)
|
||||
}
|
||||
|
||||
jsdouble *
|
||||
js_NewDouble(JSContext *cx, jsdouble d, uintN gcflag)
|
||||
js_NewDouble(JSContext *cx, jsdouble d)
|
||||
{
|
||||
jsdouble *dp;
|
||||
|
||||
dp = (jsdouble *) js_NewGCThing(cx, gcflag | GCX_DOUBLE, sizeof(jsdouble));
|
||||
dp = js_NewDoubleGCThing(cx);
|
||||
if (!dp)
|
||||
return NULL;
|
||||
*dp = d;
|
||||
return dp;
|
||||
}
|
||||
|
||||
void
|
||||
js_FinalizeDouble(JSContext *cx, jsdouble *dp)
|
||||
{
|
||||
*dp = NaN;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
|
||||
{
|
||||
jsdouble *dp;
|
||||
|
||||
dp = js_NewDouble(cx, d, 0);
|
||||
dp = js_NewDoubleGCThing(cx);
|
||||
if (!dp)
|
||||
return JS_FALSE;
|
||||
*dp = d;
|
||||
*rval = DOUBLE_TO_JSVAL(dp);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
@ -146,6 +146,9 @@ typedef union jsdpun {
|
||||
extern JSBool
|
||||
js_InitRuntimeNumberState(JSContext *cx);
|
||||
|
||||
extern void
|
||||
js_TraceRuntimeNumberState(JSTracer *trc);
|
||||
|
||||
extern void
|
||||
js_FinishRuntimeNumberState(JSContext *cx);
|
||||
|
||||
@ -167,10 +170,7 @@ extern const char js_parseInt_str[];
|
||||
|
||||
/* GC-allocate a new JS number. */
|
||||
extern jsdouble *
|
||||
js_NewDouble(JSContext *cx, jsdouble d, uintN gcflag);
|
||||
|
||||
extern void
|
||||
js_FinalizeDouble(JSContext *cx, jsdouble *dp);
|
||||
js_NewDouble(JSContext *cx, jsdouble d);
|
||||
|
||||
extern JSBool
|
||||
js_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval);
|
||||
|
Loading…
Reference in New Issue
Block a user