diff --git a/mozilla/js/src/js.c b/mozilla/js/src/js.c index d1dd954034e..54cc05d8867 100644 --- a/mozilla/js/src/js.c +++ b/mozilla/js/src/js.c @@ -706,10 +706,6 @@ Quit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) return JS_FALSE; } -#ifdef GC_MARK_DEBUG -extern JS_FRIEND_DATA(FILE *) js_DumpGCHeap; -#endif - static JSBool GC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { diff --git a/mozilla/js/src/jsarray.c b/mozilla/js/src/jsarray.c index 5c632ddc1a0..338cdaadb87 100644 --- a/mozilla/js/src/jsarray.c +++ b/mozilla/js/src/jsarray.c @@ -164,24 +164,28 @@ ValueIsLength(JSContext *cx, jsval v, jsuint *lengthp) JSBool js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp) { + JSTempValueRooter tvr; jsid id; + JSBool ok; jsint i; - jsval v; + JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr); id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); - if (!OBJ_GET_PROPERTY(cx, obj, id, &v)) - return JS_FALSE; - - /* Short-circuit, because js_ValueToECMAUint32 fails when - * called during init time. - */ - if (JSVAL_IS_INT(v)) { - i = JSVAL_TO_INT(v); - /* jsuint cast does ToUint32. */ - *lengthp = (jsuint)i; - return JS_TRUE; + ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value); + if (ok) { + /* + * Short-circuit, because js_ValueToECMAUint32 fails when called + * during init time. + */ + if (JSVAL_IS_INT(tvr.u.value)) { + i = JSVAL_TO_INT(tvr.u.value); + *lengthp = (jsuint)i; /* jsuint cast does ToUint32 */ + } else { + ok = js_ValueToECMAUint32(cx, tvr.u.value, (uint32 *)lengthp); + } } - return js_ValueToECMAUint32(cx, v, (uint32 *)lengthp); + JS_POP_TEMP_ROOT(cx, &tvr); + return ok; } static JSBool @@ -345,17 +349,19 @@ JSBool js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp) { JSErrorReporter older; + JSTempValueRooter tvr; jsid id; JSBool ok; - jsval v; older = JS_SetErrorReporter(cx, NULL); + JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr); id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); - ok = OBJ_GET_PROPERTY(cx, obj, id, &v); + ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value); JS_SetErrorReporter(cx, older); - if (!ok) - return JS_FALSE; - return ValueIsLength(cx, v, lengthp); + if (ok) + ok = ValueIsLength(cx, tvr.u.value, lengthp); + JS_POP_TEMP_ROOT(cx, &tvr); + return ok; } JSBool @@ -491,7 +497,8 @@ array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op, const jschar *sepstr; JSString *str; JSHashEntry *he; - JSObject *obj2; + JSTempValueRooter tvr; + JSAtom *atom; int stackDummy; if (!JS_CHECK_STACK_SIZE(cx, stackDummy)) { @@ -592,14 +599,14 @@ array_join_sub(JSContext *cx, JSObject *obj, enum ArrayToStringOp op, str = cx->runtime->emptyString; } else { if (op == TO_LOCALE_STRING) { - if (!js_ValueToObject(cx, v, &obj2) || - !js_TryMethod(cx, obj2, - cx->runtime->atomState.toLocaleStringAtom, - 0, NULL, &v)) { - str = NULL; - } else { - str = js_ValueToString(cx, v); - } + atom = cx->runtime->atomState.toLocaleStringAtom; + JS_PUSH_TEMP_ROOT_OBJECT(cx, NULL, &tvr); + ok = js_ValueToObject(cx, v, &tvr.u.object) && + js_TryMethod(cx, tvr.u.object, atom, 0, NULL, &v); + JS_POP_TEMP_ROOT(cx, &tvr); + if (!ok) + goto done; + str = js_ValueToString(cx, v); } else if (op == TO_STRING) { str = js_ValueToString(cx, v); } else { @@ -967,15 +974,15 @@ sort_compare(void *arg, const void *a, const void *b, int *result) } } else { jsdouble cmp; - jsval rval, argv[2]; + jsval argv[2]; argv[0] = av; argv[1] = bv; ok = js_InternalCall(cx, OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(fval)), - fval, 2, argv, &rval); + fval, 2, argv, ca->localroot); if (ok) { - ok = js_ValueToNumber(cx, rval, &cmp); + ok = js_ValueToNumber(cx, *ca->localroot, &cmp); /* Clamp cmp to -1, 0, 1. */ if (ok) { diff --git a/mozilla/js/src/jscntxt.h b/mozilla/js/src/jscntxt.h index c5f0902a490..ce6b4753eda 100644 --- a/mozilla/js/src/jscntxt.h +++ b/mozilla/js/src/jscntxt.h @@ -475,14 +475,27 @@ typedef struct JSTempValueRooter JSTempValueRooter; typedef void (* JS_DLL_CALLBACK JSTempValueMarker)(JSContext *cx, JSTempValueRooter *tvr); +typedef union JSTempValueUnion { + jsval value; + JSObject *object; + JSTempValueMarker marker; + jsval *array; +} JSTempValueUnion; + +/* + * The following allows to reinterpret JSTempValueUnion.object as jsval using + * the tagging property of a generic jsval described below. + */ +JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(jsval)); +JS_STATIC_ASSERT(sizeof(JSTempValueUnion) == sizeof(JSObject *)); + /* * Context-linked stack of temporary GC roots. * - * If count is -1, then u.value contains the single value to root. If count is - * -2, then u.marker holds a mark hook that is executed to mark the values. - * Otherwise u.array points to a stack-allocated vector of jsvals. Note that - * the vector may have length 0 or 1 for full generality, so we need -1 to - * discriminate the union. + * If count is -1, then u.value contains the single value to root. + * If count is -2, then u.marker holds a mark hook that is executed to mark + * the values. + * If count >= 0, then u.array points to a stack-allocated vector of jsvals. * * To root a single GC-thing pointer, which need not be tagged and stored as a * jsval, use JS_PUSH_SINGLE_TEMP_ROOT. The (jsval)(val) cast works because a @@ -498,16 +511,11 @@ typedef void * internal API (see further below) instead. */ struct JSTempValueRooter { - JSTempValueRooter *down; - jsint count; - union { - jsval value; - jsval *array; - JSTempValueMarker marker; - } u; + JSTempValueRooter *down; + ptrdiff_t count; + JSTempValueUnion u; }; - #define JS_PUSH_TEMP_ROOT_COMMON(cx,tvr) \ JS_BEGIN_MACRO \ JS_ASSERT((cx)->tempValueRooters != (tvr)); \ @@ -525,7 +533,8 @@ struct JSTempValueRooter { #define JS_PUSH_TEMP_ROOT(cx,cnt,arr,tvr) \ JS_BEGIN_MACRO \ JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ - (tvr)->count = (cnt); \ + JS_ASSERT((ptrdiff_t)(cnt) >= 0); \ + (tvr)->count = (ptrdiff_t)(cnt); \ (tvr)->u.array = (arr); \ JS_END_MACRO @@ -536,6 +545,13 @@ struct JSTempValueRooter { (tvr)->u.marker = (marker_); \ JS_END_MACRO +#define JS_PUSH_TEMP_ROOT_OBJECT(cx,obj,tvr) \ + JS_BEGIN_MACRO \ + JS_PUSH_TEMP_ROOT_COMMON(cx, tvr); \ + (tvr)->count = -3; \ + (tvr)->u.object = (obj); \ + JS_END_MACRO + #define JS_POP_TEMP_ROOT(cx,tvr) \ JS_BEGIN_MACRO \ JS_ASSERT((cx)->tempValueRooters == (tvr)); \ diff --git a/mozilla/js/src/jsgc.c b/mozilla/js/src/jsgc.c index 83a2fb5c33c..e478852395c 100644 --- a/mozilla/js/src/jsgc.c +++ b/mozilla/js/src/jsgc.c @@ -2816,6 +2816,7 @@ restart: } else if (tvr->count == -2) { tvr->u.marker(cx, tvr); } else { + JS_ASSERT(tvr->count >= 0); GC_MARK_JSVALS(cx, tvr->count, tvr->u.array, "tvr->u.array"); } } diff --git a/mozilla/js/src/jsgc.h b/mozilla/js/src/jsgc.h index 0d0c120c559..e53253e9fd9 100644 --- a/mozilla/js/src/jsgc.h +++ b/mozilla/js/src/jsgc.h @@ -228,6 +228,9 @@ js_MarkGCThing(JSContext *cx, void *thing); extern void js_MarkNamedGCThing(JSContext *cx, void *thing, const char *name); +extern JS_FRIEND_DATA(FILE *) js_DumpGCHeap; +JS_EXTERN_DATA(void *) js_LiveThingToFind; + #else # define GC_MARK(cx, thing, name) js_MarkGCThing(cx, thing) diff --git a/mozilla/js/src/jsstr.c b/mozilla/js/src/jsstr.c index 4cf256b7b02..950053dc037 100644 --- a/mozilla/js/src/jsstr.c +++ b/mozilla/js/src/jsstr.c @@ -2698,6 +2698,9 @@ js_ValueToString(JSContext *cx, jsval v) JS_FRIEND_API(JSString *) js_ValueToSource(JSContext *cx, jsval v) { + JSTempValueRooter tvr; + JSString *str; + if (JSVAL_IS_STRING(v)) return js_QuoteString(cx, JSVAL_TO_STRING(v), '"'); if (JSVAL_IS_PRIMITIVE(v)) { @@ -2708,14 +2711,19 @@ js_ValueToSource(JSContext *cx, jsval v) return js_NewStringCopyN(cx, js_negzero_ucNstr, 2, 0); } - } else { - if (!js_TryMethod(cx, JSVAL_TO_OBJECT(v), - cx->runtime->atomState.toSourceAtom, - 0, NULL, &v)) { - return NULL; - } + return js_ValueToString(cx, v); } - return js_ValueToString(cx, v); + + JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr); + if (!js_TryMethod(cx, JSVAL_TO_OBJECT(v), + cx->runtime->atomState.toSourceAtom, + 0, NULL, &tvr.u.value)) { + str = NULL; + } else { + str = js_ValueToString(cx, tvr.u.value); + } + JS_POP_TEMP_ROOT(cx, &tvr); + return str; } JSHashNumber