mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 400902: using a specialized GC arena for doubles. r,a=brendan a1.9b3=mtschrep
This commit is contained in:
parent
453fae2df2
commit
ea03e8c6f0
@ -331,16 +331,19 @@ JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
|
||||
break;
|
||||
case 'i':
|
||||
case 'j':
|
||||
if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp))
|
||||
*sp = js_NewWeakNumberValue(cx, (jsdouble) va_arg(ap, int32));
|
||||
if (*sp == JSVAL_NULL)
|
||||
goto bad;
|
||||
break;
|
||||
case 'u':
|
||||
if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp))
|
||||
*sp = js_NewWeakNumberValue(cx, (jsdouble) va_arg(ap, uint32));
|
||||
if (*sp == JSVAL_NULL)
|
||||
goto bad;
|
||||
break;
|
||||
case 'd':
|
||||
case 'I':
|
||||
if (!js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp))
|
||||
*sp = js_NewUnrootedDoubleValue(cx, va_arg(ap, jsdouble));
|
||||
if (*sp == JSVAL_NULL || !js_WeaklyRootDouble(cx, *sp))
|
||||
goto bad;
|
||||
break;
|
||||
case 's':
|
||||
@ -462,7 +465,7 @@ JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
|
||||
JSBool ok;
|
||||
JSObject *obj;
|
||||
JSString *str;
|
||||
jsdouble d, *dp;
|
||||
jsdouble d;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
switch (type) {
|
||||
@ -489,10 +492,8 @@ 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);
|
||||
ok = (dp != NULL);
|
||||
if (ok)
|
||||
*vp = DOUBLE_TO_JSVAL(dp);
|
||||
*vp = js_NewUnrootedDoubleValue(cx, d);
|
||||
ok = *vp != JSVAL_NULL && js_WeaklyRootDouble(cx, *vp);
|
||||
}
|
||||
break;
|
||||
case JSTYPE_BOOLEAN:
|
||||
@ -1766,21 +1767,23 @@ JS_PUBLIC_API(jsdouble *)
|
||||
JS_NewDouble(JSContext *cx, jsdouble d)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
return js_NewDouble(cx, d, 0);
|
||||
return js_NewWeaklyRootedDouble(cx, d);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
|
||||
JS_NewDoubleValue(JSContext *cx, jsdouble d, jsval *vp)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
return js_NewDoubleValue(cx, d, rval);
|
||||
*vp = js_NewUnrootedDoubleValue(cx, d);
|
||||
return *vp != JSVAL_NULL && js_WeaklyRootDouble(cx, *vp);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
|
||||
JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *vp)
|
||||
{
|
||||
CHECK_REQUEST(cx);
|
||||
return js_NewNumberValue(cx, d, rval);
|
||||
*vp = js_NewWeakNumberValue(cx, d);
|
||||
return vp != JSVAL_NULL;
|
||||
}
|
||||
|
||||
#undef JS_AddRoot
|
||||
@ -3051,23 +3054,21 @@ JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, JSClass *clasp,
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_DefineConstDoubles(JSContext *cx, JSObject *obj, JSConstDoubleSpec *cds)
|
||||
{
|
||||
JSBool ok;
|
||||
jsval value;
|
||||
uintN flags;
|
||||
|
||||
CHECK_REQUEST(cx);
|
||||
for (ok = JS_TRUE; cds->name; cds++) {
|
||||
ok = js_NewNumberValue(cx, cds->dval, &value);
|
||||
if (!ok)
|
||||
break;
|
||||
for (; cds->name; cds++) {
|
||||
value = js_NewWeakNumberValue(cx, cds->dval);
|
||||
if (value == JSVAL_NULL)
|
||||
return JS_FALSE;
|
||||
flags = cds->flags;
|
||||
if (!flags)
|
||||
flags = JSPROP_READONLY | JSPROP_PERMANENT;
|
||||
ok = DefineProperty(cx, obj, cds->name, value, NULL, NULL, flags, 0, 0);
|
||||
if (!ok)
|
||||
break;
|
||||
if (!DefineProperty(cx, obj, cds->name, value, NULL, NULL, flags, 0, 0))
|
||||
return JS_FALSE;
|
||||
}
|
||||
return ok;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
@ -187,6 +187,9 @@ js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* vp must be a root.
|
||||
*/
|
||||
static JSBool
|
||||
IndexToValue(JSContext *cx, jsuint index, jsval *vp)
|
||||
{
|
||||
@ -194,7 +197,8 @@ IndexToValue(JSContext *cx, jsuint index, jsval *vp)
|
||||
*vp = INT_TO_JSVAL(index);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return js_NewDoubleValue(cx, (jsdouble)index, vp);
|
||||
*vp = js_NewUnrootedDoubleValue(cx, (jsdouble)index);
|
||||
return *vp != JSVAL_NULL;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
@ -334,13 +338,16 @@ SetOrDeleteArrayElement(JSContext *cx, JSObject *obj, jsuint index,
|
||||
JSBool
|
||||
js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length)
|
||||
{
|
||||
jsval v;
|
||||
jsid id;
|
||||
JSTempValueRooter tvr;
|
||||
JSBool ok;
|
||||
|
||||
if (!IndexToValue(cx, length, &v))
|
||||
return JS_FALSE;
|
||||
id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
|
||||
return OBJ_SET_PROPERTY(cx, obj, id, &v);
|
||||
JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
|
||||
ok = IndexToValue(cx, length, &tvr.u.value) &&
|
||||
OBJ_SET_PROPERTY(cx, obj, id, &tvr.u.value);
|
||||
JS_POP_TEMP_ROOT(cx, &tvr);
|
||||
return ok;
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -774,12 +781,13 @@ InitArrayElements(JSContext *cx, JSObject *obj, jsuint start, jsuint end,
|
||||
static JSBool
|
||||
InitArrayObject(JSContext *cx, JSObject *obj, jsuint length, jsval *vector)
|
||||
{
|
||||
jsval v;
|
||||
jsval *vp;
|
||||
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ArrayClass);
|
||||
if (!IndexToValue(cx, length, &v))
|
||||
|
||||
vp = STOBJ_FIXED_SLOT_PTR(obj, JSSLOT_ARRAY_LENGTH);
|
||||
if (!IndexToValue(cx, length, vp))
|
||||
return JS_FALSE;
|
||||
STOBJ_SET_SLOT(obj, JSSLOT_ARRAY_LENGTH, v);
|
||||
return !vector || InitArrayElements(cx, obj, 0, length, vector);
|
||||
}
|
||||
|
||||
|
@ -586,7 +586,7 @@ js_AtomizeDouble(JSContext *cx, jsdouble d)
|
||||
gen = ++state->tablegen;
|
||||
JS_UNLOCK(&state->lock, cx);
|
||||
|
||||
key = js_NewDouble(cx, d, 0);
|
||||
key = js_NewWeaklyRootedDouble(cx, d);
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
|
@ -50,12 +50,12 @@ JS_BEGIN_EXTERN_C
|
||||
typedef JSUword jsbitmap_t; /* NSPR name, a la Unix system types */
|
||||
typedef jsbitmap_t jsbitmap; /* JS-style scalar typedef name */
|
||||
|
||||
#define JS_TEST_BIT(_map,_bit) \
|
||||
((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] & (1L << ((_bit) & (JS_BITS_PER_WORD-1))))
|
||||
#define JS_SET_BIT(_map,_bit) \
|
||||
((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] |= (1L << ((_bit) & (JS_BITS_PER_WORD-1))))
|
||||
#define JS_CLEAR_BIT(_map,_bit) \
|
||||
((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &= ~(1L << ((_bit) & (JS_BITS_PER_WORD-1))))
|
||||
#define JS_TEST_BIT(map,bit) ((map)[(bit) >> JS_BITS_PER_WORD_LOG2] & \
|
||||
((jsbitmap)1 << ((bit)&(JS_BITS_PER_WORD-1))))
|
||||
#define JS_SET_BIT(map,bit) ((map)[(bit) >> JS_BITS_PER_WORD_LOG2] |= \
|
||||
((jsbitmap)1 << ((bit)&(JS_BITS_PER_WORD-1))))
|
||||
#define JS_CLEAR_BIT(map,bit) ((map)[(bit) >> JS_BITS_PER_WORD_LOG2] &= \
|
||||
~((jsbitmap)1 << ((bit)&(JS_BITS_PER_WORD-1))))
|
||||
|
||||
/*
|
||||
** Compute the log of the least power of 2 greater than or equal to n
|
||||
|
@ -183,6 +183,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;
|
||||
@ -765,6 +766,8 @@ struct JSContext {
|
||||
/* Stack of thread-stack-allocated temporary GC roots. */
|
||||
JSTempValueRooter *tempValueRooters;
|
||||
|
||||
JSGCDoubleCell *doubleFreeList;
|
||||
|
||||
/* Debug hooks associated with the current context. */
|
||||
JSDebugHooks *debugHooks;
|
||||
};
|
||||
|
@ -915,7 +915,8 @@ date_now(JSContext *cx, uintN argc, jsval *vp)
|
||||
JSLL_DIV(ms, us, us2ms);
|
||||
JSLL_L2D(msec_time, ms);
|
||||
|
||||
return js_NewDoubleValue(cx, msec_time, vp);
|
||||
*vp = js_NewUnrootedDoubleValue(cx, msec_time);
|
||||
return *vp != JSVAL_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -963,7 +964,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_NewWeaklyRootedDouble(cx, t);
|
||||
if (!dp)
|
||||
return JS_FALSE;
|
||||
return SetUTCTimePtr(cx, obj, vp, dp);
|
||||
@ -993,7 +994,7 @@ GetLocalTime(JSContext *cx, JSObject *obj, jsval *vp, jsdouble *dp)
|
||||
if (JSDOUBLE_IS_FINITE(result))
|
||||
result = LocalTime(result);
|
||||
|
||||
cached = js_NewDouble(cx, result, 0);
|
||||
cached = js_NewWeaklyRootedDouble(cx, result);
|
||||
if (!cached)
|
||||
return JS_FALSE;
|
||||
|
||||
@ -1543,7 +1544,8 @@ date_setYear(JSContext *cx, uintN argc, jsval *vp)
|
||||
if (!JSDOUBLE_IS_FINITE(year)) {
|
||||
if (!SetUTCTimePtr(cx, obj, NULL, cx->runtime->jsNaN))
|
||||
return JS_FALSE;
|
||||
return js_NewNumberValue(cx, *cx->runtime->jsNaN, vp);
|
||||
*vp = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
year = js_DoubleToInteger(year);
|
||||
@ -2019,7 +2021,7 @@ date_constructor(JSContext *cx, JSObject* obj)
|
||||
{
|
||||
jsdouble *date;
|
||||
|
||||
date = js_NewDouble(cx, 0.0, 0);
|
||||
date = js_NewWeaklyRootedDouble(cx, 0.0);
|
||||
if (!date)
|
||||
return NULL;
|
||||
|
||||
|
1031
js/src/jsgc.c
1031
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
|
||||
@ -182,6 +183,22 @@ struct JSGCThing {
|
||||
extern void *
|
||||
js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes);
|
||||
|
||||
/*
|
||||
* GC-allocate a new jsdouble number. Returns JSVAL_NULL when the allocation
|
||||
* fails. Otherwise the caller must root the result immediately after the
|
||||
* the call.
|
||||
*/
|
||||
extern jsval
|
||||
js_NewUnrootedDoubleValue(JSContext *cx, jsdouble d);
|
||||
|
||||
/*
|
||||
* Copy double jsval to the weak root for doubles. This is the function to
|
||||
* call after invoking js_NewUnrootedDoubleValue to provide at least weak
|
||||
* rooting of the new double value.
|
||||
*/
|
||||
extern JSBool
|
||||
js_WeaklyRootDouble(JSContext *cx, jsval v);
|
||||
|
||||
extern JSBool
|
||||
js_LockGCThing(JSContext *cx, void *thing);
|
||||
|
||||
@ -283,6 +300,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];
|
||||
@ -304,28 +336,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 */
|
||||
@ -350,7 +376,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)
|
||||
|
@ -127,7 +127,8 @@
|
||||
v_ = INT_TO_JSVAL(i_); \
|
||||
} else { \
|
||||
SAVE_SP_AND_PC(fp); \
|
||||
ok = js_NewDoubleValue(cx, d, &v_); \
|
||||
v_ = js_NewUnrootedDoubleValue(cx, d); \
|
||||
ok = v_ != JSVAL_NULL; \
|
||||
if (!ok) \
|
||||
goto out; \
|
||||
} \
|
||||
@ -142,7 +143,8 @@
|
||||
v_ = INT_TO_JSVAL(i); \
|
||||
} else { \
|
||||
SAVE_SP_AND_PC(fp); \
|
||||
ok = js_NewDoubleValue(cx, (jsdouble)(i), &v_); \
|
||||
v_ = js_NewUnrootedDoubleValue(cx, d); \
|
||||
ok = v_ != JSVAL_NULL; \
|
||||
if (!ok) \
|
||||
goto out; \
|
||||
} \
|
||||
@ -157,7 +159,8 @@
|
||||
v_ = INT_TO_JSVAL(u); \
|
||||
} else { \
|
||||
SAVE_SP_AND_PC(fp); \
|
||||
ok = js_NewDoubleValue(cx, (jsdouble)(u), &v_); \
|
||||
v_ = js_NewUnrootedDoubleValue(cx, d); \
|
||||
ok = v_ != JSVAL_NULL; \
|
||||
if (!ok) \
|
||||
goto out; \
|
||||
} \
|
||||
@ -3152,7 +3155,8 @@ interrupt:
|
||||
#else
|
||||
d = -d;
|
||||
#endif
|
||||
ok = js_NewNumberValue(cx, d, &rval);
|
||||
rval = js_NewUnrootedDoubleValue(cx, d);
|
||||
ok = rval != JSVAL_NULL;
|
||||
if (!ok)
|
||||
goto out;
|
||||
}
|
||||
@ -3166,7 +3170,8 @@ interrupt:
|
||||
ok = js_ValueToNumber(cx, rval, &d);
|
||||
if (!ok)
|
||||
goto out;
|
||||
ok = js_NewNumberValue(cx, d, &rval);
|
||||
rval = js_NewUnrootedDoubleValue(cx, d);
|
||||
ok = rval != JSVAL_NULL;
|
||||
if (!ok)
|
||||
goto out;
|
||||
sp[-1] = rval;
|
||||
@ -3320,18 +3325,20 @@ interrupt:
|
||||
if (cs->format & JOF_POST) { \
|
||||
rtmp = rval; \
|
||||
if (!JSVAL_IS_NUMBER(rtmp)) { \
|
||||
ok = js_NewNumberValue(cx, d, &rtmp); \
|
||||
rtmp = js_NewWeakNumberValue(cx, d); \
|
||||
ok = (rtmp != JSVAL_NULL); \
|
||||
if (!ok) \
|
||||
goto out; \
|
||||
} \
|
||||
*vp = rtmp; \
|
||||
(cs->format & JOF_INC) ? d++ : d--; \
|
||||
ok = js_NewNumberValue(cx, d, &rval); \
|
||||
rval = js_NewWeakNumberValue(cx, d); \
|
||||
} else { \
|
||||
(cs->format & JOF_INC) ? ++d : --d; \
|
||||
ok = js_NewNumberValue(cx, d, &rval); \
|
||||
rval = js_NewWeakNumberValue(cx, d); \
|
||||
rtmp = rval; \
|
||||
} \
|
||||
ok = (rval != JSVAL_NULL); \
|
||||
if (!ok) \
|
||||
goto out; \
|
||||
JS_END_MACRO
|
||||
|
@ -165,7 +165,8 @@ math_atan2(JSContext *cx, uintN argc, jsval *vp)
|
||||
z = fd_copysign(M_PI / 4, x);
|
||||
if (y < 0)
|
||||
z *= 3;
|
||||
return js_NewDoubleValue(cx, z, vp);
|
||||
*vp = js_NewUnrootedDoubleValue(cx, z);
|
||||
return *vp != JSVAL_NULL;
|
||||
}
|
||||
#endif
|
||||
z = fd_atan2(x, y);
|
||||
|
101
js/src/jsnum.c
101
js/src/jsnum.c
@ -167,7 +167,6 @@ static JSBool
|
||||
Number(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
jsdouble d;
|
||||
jsval v;
|
||||
|
||||
if (argc != 0) {
|
||||
if (!js_ValueToNumber(cx, argv[0], &d))
|
||||
@ -175,14 +174,10 @@ Number(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
} else {
|
||||
d = 0.0;
|
||||
}
|
||||
if (!js_NewNumberValue(cx, d, &v))
|
||||
return JS_FALSE;
|
||||
if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
|
||||
*rval = v;
|
||||
return JS_TRUE;
|
||||
}
|
||||
OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, v);
|
||||
return JS_TRUE;
|
||||
return js_NewNumberValue(cx, d,
|
||||
!(cx->fp->flags & JSFRAME_CONSTRUCTING)
|
||||
? rval
|
||||
: STOBJ_FIXED_SLOT_PTR(obj, JSSLOT_PRIVATE));
|
||||
}
|
||||
|
||||
#if JS_HAS_TOSOURCE
|
||||
@ -538,6 +533,7 @@ js_InitRuntimeNumberState(JSContext *cx)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
jsdpun u;
|
||||
jsval v;
|
||||
struct lconv *locale;
|
||||
|
||||
rt = cx->runtime;
|
||||
@ -548,23 +544,26 @@ 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);
|
||||
if (!rt->jsNaN)
|
||||
v = js_NewUnrootedDoubleValue(cx, NaN);
|
||||
if (v == JSVAL_NULL)
|
||||
return JS_FALSE;
|
||||
rt->jsNaN = JSVAL_TO_DOUBLE(v);
|
||||
|
||||
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);
|
||||
if (!rt->jsPositiveInfinity)
|
||||
v = js_NewUnrootedDoubleValue(cx, u.d);
|
||||
if (v == JSVAL_NULL)
|
||||
return JS_FALSE;
|
||||
rt->jsPositiveInfinity = JSVAL_TO_DOUBLE(v);
|
||||
|
||||
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);
|
||||
if (!rt->jsNegativeInfinity)
|
||||
v = js_NewUnrootedDoubleValue(cx, u.d);
|
||||
if (v == JSVAL_NULL)
|
||||
return JS_FALSE;
|
||||
rt->jsNegativeInfinity = JSVAL_TO_DOUBLE(v);
|
||||
|
||||
u.s.hi = 0;
|
||||
u.s.lo = 1;
|
||||
@ -581,15 +580,25 @@ 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)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime;
|
||||
|
||||
js_UnlockGCThingRT(rt, rt->jsNaN);
|
||||
js_UnlockGCThingRT(rt, rt->jsNegativeInfinity);
|
||||
js_UnlockGCThingRT(rt, rt->jsPositiveInfinity);
|
||||
|
||||
rt->jsNaN = NULL;
|
||||
rt->jsNegativeInfinity = NULL;
|
||||
rt->jsPositiveInfinity = NULL;
|
||||
@ -637,47 +646,41 @@ js_InitNumberClass(JSContext *cx, JSObject *obj)
|
||||
}
|
||||
|
||||
jsdouble *
|
||||
js_NewDouble(JSContext *cx, jsdouble d, uintN gcflag)
|
||||
js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d)
|
||||
{
|
||||
jsdouble *dp;
|
||||
jsval v;
|
||||
|
||||
dp = (jsdouble *) js_NewGCThing(cx, gcflag | GCX_DOUBLE, sizeof(jsdouble));
|
||||
if (!dp)
|
||||
v = js_NewUnrootedDoubleValue(cx, d);
|
||||
if (v == JSVAL_NULL || !js_WeaklyRootDouble(cx, v))
|
||||
return NULL;
|
||||
*dp = d;
|
||||
return dp;
|
||||
}
|
||||
|
||||
void
|
||||
js_FinalizeDouble(JSContext *cx, jsdouble *dp)
|
||||
{
|
||||
*dp = NaN;
|
||||
return JSVAL_TO_DOUBLE(v);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
|
||||
{
|
||||
jsdouble *dp;
|
||||
|
||||
dp = js_NewDouble(cx, d, 0);
|
||||
if (!dp)
|
||||
return JS_FALSE;
|
||||
*rval = DOUBLE_TO_JSVAL(dp);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
|
||||
js_NewNumberValue(JSContext *cx, jsdouble d, jsval *vp)
|
||||
{
|
||||
jsint i;
|
||||
|
||||
if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i)) {
|
||||
*rval = INT_TO_JSVAL(i);
|
||||
} else {
|
||||
if (!js_NewDoubleValue(cx, d, rval))
|
||||
return JS_FALSE;
|
||||
*vp = INT_TO_JSVAL(i);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
*vp = js_NewUnrootedDoubleValue(cx, d);
|
||||
return *vp != JSVAL_VOID;
|
||||
}
|
||||
|
||||
jsval
|
||||
js_NewWeakNumberValue(JSContext *cx, jsdouble d)
|
||||
{
|
||||
jsint i;
|
||||
jsval v;
|
||||
|
||||
if (JSDOUBLE_IS_INT(d, i) && INT_FITS_IN_JSVAL(i))
|
||||
return INT_TO_JSVAL(i);
|
||||
v = js_NewUnrootedDoubleValue(cx, d);
|
||||
if (v != JSVAL_NULL && !js_WeaklyRootDouble(cx, v))
|
||||
v = JSVAL_NULL;
|
||||
return v;
|
||||
}
|
||||
|
||||
char *
|
||||
|
@ -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);
|
||||
|
||||
@ -165,18 +168,29 @@ extern const char js_isFinite_str[];
|
||||
extern const char js_parseFloat_str[];
|
||||
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);
|
||||
|
||||
extern JSBool
|
||||
js_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval);
|
||||
/*
|
||||
* Create a new double value corresponding to d. The result is weakly rooted.
|
||||
*/
|
||||
extern jsdouble *
|
||||
js_NewWeaklyRootedDouble(JSContext *cx, jsdouble d);
|
||||
|
||||
/*
|
||||
* Set *vp to int or double value corresponding to d.
|
||||
*
|
||||
* vp must be a root.
|
||||
*/
|
||||
extern JSBool
|
||||
js_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval);
|
||||
js_NewNumberValue(JSContext *cx, jsdouble d, jsval *vp);
|
||||
|
||||
/*
|
||||
* If d is int, return it as jsval. Otherwise allocate a new double, weakly
|
||||
* root and return it as jsval. Returns JSVAL_NULL when the allocation fails.
|
||||
*/
|
||||
extern jsval
|
||||
js_NewWeakNumberValue(JSContext *cx, jsdouble d);
|
||||
|
||||
/* Convert a number to a GC'ed string. */
|
||||
extern JSString *
|
||||
|
@ -142,6 +142,9 @@ struct JSObject {
|
||||
#define STOBJ_NSLOTS(obj) \
|
||||
((obj)->dslots ? (uint32)(obj)->dslots[-1] : (uint32)JS_INITIAL_NSLOTS)
|
||||
|
||||
#define STOBJ_FIXED_SLOT_PTR(obj, slot) \
|
||||
(JS_ASSERT((slot) < JS_INITIAL_NSLOTS), &(obj)->fslots[(slot)])
|
||||
|
||||
#define STOBJ_GET_SLOT(obj,slot) \
|
||||
((slot) < JS_INITIAL_NSLOTS \
|
||||
? (obj)->fslots[(slot)] \
|
||||
|
@ -4319,7 +4319,7 @@ js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex)
|
||||
{
|
||||
jsval v;
|
||||
|
||||
return js_NewNumberValue(cx, lastIndex, &v) &&
|
||||
JS_SetReservedSlot(cx, obj, 0, v);
|
||||
v = js_NewWeakNumberValue(cx, lastIndex);
|
||||
return v != JSVAL_NULL && JS_SetReservedSlot(cx, obj, 0, v);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user