bug=400902 r,a1.9=brendan Specialized GC arena for double values

This commit is contained in:
igor@mir2.org 2008-02-26 13:01:42 -08:00
parent dbd13fd08e
commit 663a089f9a
9 changed files with 869 additions and 359 deletions

View File

@ -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")

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
};

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -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;
}

View File

@ -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);