Bug 476177 - TM: cx->stackPool must not be accessed on trace. r=brendan.

--HG--
extra : rebase_source : 746d61b54aa38cbe18fe31bce4efcbbad4629678
This commit is contained in:
Jason Orendorff 2009-01-30 17:40:05 -06:00
parent 8c35f95c27
commit 37f2985bdf
20 changed files with 92 additions and 60 deletions

View File

@ -79,14 +79,11 @@
#include "jsscope.h"
#include "jsscript.h"
#include "jsstr.h"
#include "jstracer.h"
#include "jsdbgapi.h"
#include "prmjtime.h"
#include "jsstaticcheck.h"
#if !defined JS_THREADSAFE && defined JS_TRACER
#include "jstracer.h"
#endif
#if JS_HAS_FILE_OBJECT
#include "jsfile.h"
#endif
@ -323,6 +320,7 @@ JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
continue;
argc++;
}
js_LeaveTrace(cx);
sp = js_AllocStack(cx, argc, markp);
if (!sp)
return NULL;
@ -419,6 +417,7 @@ JS_PUBLIC_API(void)
JS_PopArguments(JSContext *cx, void *mark)
{
CHECK_REQUEST(cx);
JS_ASSERT_NOT_ON_TRACE(cx);
js_FreeStack(cx, mark);
}
@ -2067,6 +2066,7 @@ JS_TraceRuntime(JSTracer *trc)
{
JSBool allAtoms = trc->context->runtime->gcKeepAtoms != 0;
js_LeaveTrace(trc->context);
js_TraceRuntime(trc, allAtoms);
}
@ -2483,6 +2483,8 @@ JS_IsGCMarkingTracer(JSTracer *trc)
JS_PUBLIC_API(void)
JS_GC(JSContext *cx)
{
js_LeaveTrace(cx);
/* Don't nuke active arenas if executing or compiling. */
if (cx->stackPool.current == &cx->stackPool.first)
JS_FinishArenaPool(&cx->stackPool);
@ -5446,8 +5448,7 @@ JS_SaveFrameChain(JSContext *cx)
JS_PUBLIC_API(void)
JS_RestoreFrameChain(JSContext *cx, JSStackFrame *fp)
{
JS_ASSERT(!JS_ON_TRACE(cx));
VOUCH_DOES_NOT_REQUIRE_STACK();
JS_ASSERT_NOT_ON_TRACE(cx);
JS_ASSERT(!cx->fp);
if (!fp)
return;

View File

@ -1620,7 +1620,7 @@ typedef struct MSortArgs {
} MSortArgs;
/* Helper function for js_MergeSort. */
static JSBool
static JS_REQUIRES_STACK JSBool
MergeArrays(MSortArgs *msa, void *src, void *dest, size_t run1, size_t run2)
{
void *arg, *a, *b, *c;
@ -1681,7 +1681,7 @@ MergeArrays(MSortArgs *msa, void *src, void *dest, size_t run1, size_t run2)
* This sort is stable, i.e. sequence of equal elements is preserved.
* See also bug #224128.
*/
JSBool
JS_REQUIRES_STACK JSBool
js_MergeSort(void *src, size_t nel, size_t elsize,
JSComparator cmp, void *arg, void *tmp)
{
@ -1767,7 +1767,7 @@ typedef struct CompareArgs {
jsval *elemroot; /* stack needed for js_Invoke */
} CompareArgs;
static JSBool
static JS_REQUIRES_STACK JSBool
sort_compare(void *arg, const void *a, const void *b, int *result)
{
jsval av = *(const jsval *)a, bv = *(const jsval *)b;
@ -1835,7 +1835,7 @@ sort_compare_strings(void *arg, const void *a, const void *b, int *result)
*/
JS_STATIC_ASSERT(JSVAL_NULL == 0);
static JSBool
static JS_REQUIRES_STACK JSBool
array_sort(JSContext *cx, uintN argc, jsval *vp)
{
jsval *argv, fval, *vec, *mergesort_tmp, v;
@ -2746,7 +2746,7 @@ typedef enum ArrayExtraMode {
#define REDUCE_MODE(mode) ((mode) == REDUCE || (mode) == REDUCE_RIGHT)
static JSBool
static JS_REQUIRES_STACK JSBool
array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp)
{
JSObject *obj;
@ -2930,43 +2930,43 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, jsval *vp)
return ok;
}
static JSBool
static JS_REQUIRES_STACK JSBool
array_forEach(JSContext *cx, uintN argc, jsval *vp)
{
return array_extra(cx, FOREACH, argc, vp);
}
static JSBool
static JS_REQUIRES_STACK JSBool
array_map(JSContext *cx, uintN argc, jsval *vp)
{
return array_extra(cx, MAP, argc, vp);
}
static JSBool
static JS_REQUIRES_STACK JSBool
array_reduce(JSContext *cx, uintN argc, jsval *vp)
{
return array_extra(cx, REDUCE, argc, vp);
}
static JSBool
static JS_REQUIRES_STACK JSBool
array_reduceRight(JSContext *cx, uintN argc, jsval *vp)
{
return array_extra(cx, REDUCE_RIGHT, argc, vp);
}
static JSBool
static JS_REQUIRES_STACK JSBool
array_filter(JSContext *cx, uintN argc, jsval *vp)
{
return array_extra(cx, FILTER, argc, vp);
}
static JSBool
static JS_REQUIRES_STACK JSBool
array_some(JSContext *cx, uintN argc, jsval *vp)
{
return array_extra(cx, SOME, argc, vp);
}
static JSBool
static JS_REQUIRES_STACK JSBool
array_every(JSContext *cx, uintN argc, jsval *vp)
{
return array_extra(cx, EVERY, argc, vp);

View File

@ -122,7 +122,7 @@ typedef JSBool (*JSComparator)(void *arg, const void *a, const void *b,
* comparator function cmp returns an error inside a comparison, so remember
* to check the return value of this function.
*/
extern JSBool
extern JS_REQUIRES_STACK JSBool
js_MergeSort(void *vec, size_t nel, size_t elsize, JSComparator cmp,
void *arg, void *tmp);

View File

@ -64,6 +64,7 @@
#include "jsscan.h"
#include "jsscope.h"
#include "jsscript.h"
#include "jsstaticcheck.h"
#include "jsstr.h"
#include "jstracer.h"
@ -294,6 +295,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
* done by js_DestroyContext).
*/
cx->version = JSVERSION_DEFAULT;
VOUCH_DOES_NOT_REQUIRE_STACK();
JS_INIT_ARENA_POOL(&cx->stackPool, "stack", stackChunkSize, sizeof(jsval),
&cx->scriptStackQuota);
@ -507,6 +509,7 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
/* Free the stuff hanging off of cx. */
js_FreeRegExpStatics(cx);
VOUCH_DOES_NOT_REQUIRE_STACK();
JS_FinishArenaPool(&cx->stackPool);
JS_FinishArenaPool(&cx->tempPool);

View File

@ -889,6 +889,7 @@ struct JSContext {
JSRuntime *runtime;
/* Stack arena pool and frame pointer register. */
JS_REQUIRES_STACK
JSArenaPool stackPool;
JS_REQUIRES_STACK

View File

@ -674,7 +674,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return JS_TRUE;
}
JSBool
JS_REQUIRES_STACK JSBool
js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{

View File

@ -120,10 +120,10 @@ extern JSPropertyOp
js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
const JSScopeProperty *sprop);
extern JSBool
extern JS_REQUIRES_STACK JSBool
js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
extern JSBool
extern JS_REQUIRES_STACK JSBool
js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);

View File

@ -1587,7 +1587,7 @@ fun_toSource(JSContext *cx, uintN argc, jsval *vp)
}
#endif
JSBool
JS_REQUIRES_STACK JSBool
js_fun_call(JSContext *cx, uintN argc, jsval *vp)
{
JSObject *obj;
@ -1646,7 +1646,7 @@ js_fun_call(JSContext *cx, uintN argc, jsval *vp)
return ok;
}
JSBool
JS_REQUIRES_STACK JSBool
js_fun_apply(JSContext *cx, uintN argc, jsval *vp)
{
JSObject *obj, *aobj;
@ -1737,7 +1737,7 @@ out:
}
#ifdef NARCISSUS
static JSBool
static JS_REQUIRES_STACK JSBool
fun_applyConstructor(JSContext *cx, uintN argc, jsval *vp)
{
JSObject *aobj;

View File

@ -284,10 +284,10 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, struct JSArenaPool *pool);
extern void
js_FreezeLocalNames(JSContext *cx, JSFunction *fun);
extern JSBool
extern JS_REQUIRES_STACK JSBool
js_fun_apply(JSContext *cx, uintN argc, jsval *vp);
extern JSBool
extern JS_REQUIRES_STACK JSBool
js_fun_call(JSContext *cx, uintN argc, jsval *vp);

View File

@ -74,6 +74,7 @@
#include "jsparse.h"
#include "jsscope.h"
#include "jsscript.h"
#include "jsstaticcheck.h"
#include "jsstr.h"
#include "jstracer.h"
@ -2957,7 +2958,7 @@ TraceWeakRoots(JSTracer *trc, JSWeakRoots *wr)
js_CallValueTracerIfGCThing(trc, wr->lastInternalResult);
}
JS_FRIEND_API(void)
JS_REQUIRES_STACK JS_FRIEND_API(void)
js_TraceContext(JSTracer *trc, JSContext *acx)
{
JSStackFrame *fp, *nextChain;
@ -3109,7 +3110,7 @@ js_TraceTraceMonitor(JSTracer *trc, JSTraceMonitor *tm)
}
}
void
JS_REQUIRES_STACK void
js_TraceRuntime(JSTracer *trc, JSBool allAtoms)
{
JSRuntime *rt = trc->context->runtime;
@ -3456,6 +3457,7 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
#ifdef JS_TRACER
if (JS_ON_TRACE(cx))
goto out;
VOUCH_HAVE_STACK();
#endif
/* Reset malloc counter. */
@ -3778,7 +3780,8 @@ out:
* We want to restart GC if js_GC was called recursively or if any of the
* finalizers called js_RemoveRoot or js_UnlockGCThingRT.
*/
if (rt->gcLevel > 1 || rt->gcPoke) {
if (!JS_ON_TRACE(cx) && (rt->gcLevel > 1 || rt->gcPoke)) {
VOUCH_HAVE_STACK();
rt->gcLevel = 1;
rt->gcPoke = JS_FALSE;
JS_UNLOCK_GC(rt);

View File

@ -254,10 +254,10 @@ js_CallValueTracerIfGCThing(JSTracer *trc, jsval v);
extern void
js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp);
extern void
extern JS_REQUIRES_STACK void
js_TraceRuntime(JSTracer *trc, JSBool allAtoms);
extern JS_FRIEND_API(void)
extern JS_REQUIRES_STACK JS_FRIEND_API(void)
js_TraceContext(JSTracer *trc, JSContext *acx);
/*

View File

@ -533,7 +533,7 @@ js_EnablePropertyCache(JSContext *cx)
* Check if the current arena has enough space to fit nslots after sp and, if
* so, reserve the necessary space.
*/
static JSBool
static JS_REQUIRES_STACK JSBool
AllocateAfterSP(JSContext *cx, jsval *sp, uintN nslots)
{
uintN surplus;
@ -558,7 +558,7 @@ AllocateAfterSP(JSContext *cx, jsval *sp, uintN nslots)
return JS_TRUE;
}
JS_STATIC_INTERPRET jsval *
JS_STATIC_INTERPRET JS_REQUIRES_STACK jsval *
js_AllocRawStack(JSContext *cx, uintN nslots, void **markp)
{
jsval *sp;
@ -583,13 +583,13 @@ js_AllocRawStack(JSContext *cx, uintN nslots, void **markp)
return sp;
}
JS_STATIC_INTERPRET void
JS_STATIC_INTERPRET JS_REQUIRES_STACK void
js_FreeRawStack(JSContext *cx, void *mark)
{
JS_ARENA_RELEASE(&cx->stackPool, mark);
}
JS_FRIEND_API(jsval *)
JS_REQUIRES_STACK JS_FRIEND_API(jsval *)
js_AllocStack(JSContext *cx, uintN nslots, void **markp)
{
jsval *sp;
@ -635,7 +635,7 @@ js_AllocStack(JSContext *cx, uintN nslots, void **markp)
return sp;
}
JS_FRIEND_API(void)
JS_REQUIRES_STACK JS_FRIEND_API(void)
js_FreeStack(JSContext *cx, void *mark)
{
JSStackHeader *sh;
@ -988,7 +988,7 @@ js_OnUnknownMethod(JSContext *cx, jsval *vp)
return ok;
}
static JSBool
static JS_REQUIRES_STACK JSBool
NoSuchMethod(JSContext *cx, uintN argc, jsval *vp, uint32 flags)
{
jsval *invokevp;
@ -1049,7 +1049,7 @@ const uint16 js_PrimitiveTestFlags[] = {
* required arguments, allocate declared local variables, and pop everything
* when done. Then push the return value.
*/
JS_FRIEND_API(JSBool)
JS_REQUIRES_STACK JS_FRIEND_API(JSBool)
js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags)
{
void *mark;
@ -1265,7 +1265,7 @@ have_fun:
/* Default return value for a constructor is the new object. */
frame.rval = (flags & JSINVOKE_CONSTRUCT) ? vp[1] : JSVAL_VOID;
frame.down = js_GetTopStackFrame(cx);
frame.down = cx->fp;
frame.annotation = NULL;
frame.scopeChain = NULL; /* set below for real, after cx->fp is set */
frame.regs = NULL;
@ -1372,7 +1372,7 @@ bad:
goto out2;
}
JSBool
JS_REQUIRES_STACK JSBool
js_InternalInvoke(JSContext *cx, JSObject *obj, jsval fval, uintN flags,
uintN argc, jsval *argv, jsval *rval)
{
@ -1418,6 +1418,8 @@ js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval,
{
JSSecurityCallbacks *callbacks;
js_LeaveTrace(cx);
/*
* js_InternalInvoke could result in another try to get or set the same id
* again, see bug 355497.
@ -1731,7 +1733,7 @@ js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval)
return lval == rval;
}
JSBool
JS_REQUIRES_STACK JSBool
js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp)
{
JSFunction *fun, *fun2;

View File

@ -368,10 +368,10 @@ js_EnablePropertyCache(JSContext *cx);
/*
* Interpreter stack arena-pool alloc and free functions.
*/
extern JS_FRIEND_API(jsval *)
extern JS_REQUIRES_STACK JS_FRIEND_API(jsval *)
js_AllocStack(JSContext *cx, uintN nslots, void **markp);
extern JS_FRIEND_API(void)
extern JS_REQUIRES_STACK JS_FRIEND_API(void)
js_FreeStack(JSContext *cx, void *mark);
/*
@ -422,7 +422,7 @@ extern const uint16 js_PrimitiveTestFlags[];
* so the caller should not use that space for values that must be preserved
* across the call.
*/
extern JS_FRIEND_API(JSBool)
extern JS_REQUIRES_STACK JS_FRIEND_API(JSBool)
js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags);
/*
@ -468,7 +468,7 @@ extern JSBool
js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
JSStackFrame *down, uintN flags, jsval *result);
extern JSBool
extern JS_REQUIRES_STACK JSBool
js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp);
extern JS_REQUIRES_STACK JSBool
@ -507,10 +507,10 @@ js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval);
#else
# define JS_STATIC_INTERPRET
extern jsval *
extern JS_REQUIRES_STACK jsval *
js_AllocRawStack(JSContext *cx, uintN nslots, void **markp);
extern void
extern JS_REQUIRES_STACK void
js_FreeRawStack(JSContext *cx, void *mark);
/*

View File

@ -64,6 +64,8 @@
#include "jsscan.h"
#include "jsscope.h"
#include "jsscript.h"
#include "jsstaticcheck.h"
#include "jstracer.h"
#if JS_HAS_XML_SUPPORT
#include "jsxml.h"
@ -75,7 +77,7 @@
#if JS_HAS_GENERATORS
static JSBool
static JS_REQUIRES_STACK JSBool
CloseGenerator(JSContext *cx, JSObject *genobj);
#endif
@ -407,6 +409,7 @@ js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp)
if (!InitNativeIterator(cx, iterobj, obj, flags))
goto bad;
} else {
js_LeaveTrace(cx);
arg = BOOLEAN_TO_JSVAL((flags & JSITER_FOREACH) == 0);
if (!js_InternalInvoke(cx, obj, *vp, JSINVOKE_ITERATOR, 1, &arg,
vp)) {
@ -449,6 +452,7 @@ js_CloseIterator(JSContext *cx, jsval v)
}
#if JS_HAS_GENERATORS
else if (clasp == &js_GeneratorClass) {
JS_ASSERT_NOT_ON_TRACE(cx);
if (!CloseGenerator(cx, obj))
return JS_FALSE;
}
@ -814,7 +818,7 @@ typedef enum JSGeneratorOp {
* Start newborn or restart yielding generator and perform the requested
* operation inside its frame.
*/
static JSBool
static JS_REQUIRES_STACK JSBool
SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
JSGenerator *gen, jsval arg)
{
@ -904,7 +908,7 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
return JS_FALSE;
}
static JSBool
static JS_REQUIRES_STACK JSBool
CloseGenerator(JSContext *cx, JSObject *obj)
{
JSGenerator *gen;
@ -932,6 +936,8 @@ generator_op(JSContext *cx, JSGeneratorOp op, jsval *vp, uintN argc)
JSGenerator *gen;
jsval arg;
js_LeaveTrace(cx);
obj = JS_THIS_OBJECT(cx, vp);
if (!JS_InstanceOf(cx, obj, &js_GeneratorClass, vp + 2))
return JS_FALSE;
@ -976,6 +982,8 @@ generator_op(JSContext *cx, JSGeneratorOp op, jsval *vp, uintN argc)
}
}
js_LeaveTrace(cx);
arg = ((op == JSGENOP_SEND || op == JSGENOP_THROW) && argc != 0)
? vp[2]
: JSVAL_VOID;

View File

@ -69,9 +69,10 @@
#include "jsparse.h"
#include "jsscope.h"
#include "jsscript.h"
#include "jsstr.h"
#include "jsdbgapi.h" /* whether or not JS_HAS_OBJ_WATCHPOINT */
#include "jsstaticcheck.h"
#include "jsstr.h"
#include "jstracer.h"
#include "jsdbgapi.h" /* whether or not JS_HAS_OBJ_WATCHPOINT */
#if JS_HAS_GENERATORS
#include "jsiter.h"
@ -3983,7 +3984,7 @@ js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
return JS_FALSE;
if (entryp) {
JS_ASSERT_NOT_EXECUTING_TRACE(cx);
JS_ASSERT_NOT_ON_TRACE(cx);
js_FillPropertyCache(cx, obj, shape, 0, protoIndex, obj2, sprop, entryp);
}
JS_UNLOCK_OBJ(cx, obj2);
@ -4189,7 +4190,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
return JS_FALSE;
if (entryp) {
JS_ASSERT_NOT_EXECUTING_TRACE(cx);
JS_ASSERT_NOT_ON_TRACE(cx);
if (!(attrs & JSPROP_SHARED))
js_FillPropertyCache(cx, obj, shape, 0, 0, obj, sprop, entryp);
else
@ -5130,8 +5131,9 @@ js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
JS_ClearPendingException(cx);
JS_SetErrorReporter(cx, older);
return JSVAL_IS_PRIMITIVE(fval) ||
js_InternalCall(cx, obj, fval, argc, argv, rval);
if (JSVAL_IS_PRIMITIVE(fval))
return JS_TRUE;
return js_InternalCall(cx, obj, fval, argc, argv, rval);
}
#if JS_HAS_XDR

View File

@ -4110,6 +4110,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
tmp = (TableEntry *)
JS_malloc(cx, (size_t)j * sizeof *table);
if (tmp) {
VOUCH_DOES_NOT_REQUIRE_STACK();
ok = js_MergeSort(table, (size_t)j, sizeof(TableEntry),
CompareOffsets, NULL, tmp);
JS_free(cx, tmp);

View File

@ -53,7 +53,7 @@ inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {
inline JS_FORCES_STACK void VOUCH_DOES_NOT_REQUIRE_STACK() {}
inline JS_FORCES_STACK void
JS_ASSERT_NOT_EXECUTING_TRACE(JSContext *cx)
JS_ASSERT_NOT_ON_TRACE(JSContext *cx)
{
JS_ASSERT(!JS_ON_TRACE(cx));
}
@ -62,7 +62,8 @@ JS_ASSERT_NOT_EXECUTING_TRACE(JSContext *cx)
#define MUST_FLOW_THROUGH(label) ((void) 0)
#define MUST_FLOW_LABEL(label)
#define VOUCH_DOES_NOT_REQUIRE_STACK() ((void) 0)
#define JS_ASSERT_NOT_EXECUTING_TRACE(cx) JS_ASSERT(!JS_ON_TRACE(cx))
#define JS_ASSERT_NOT_ON_TRACE(cx) JS_ASSERT(!JS_ON_TRACE(cx))
#endif
#define VOUCH_HAVE_STACK VOUCH_DOES_NOT_REQUIRE_STACK
#endif /* jsstaticcheck_h___ */

View File

@ -70,6 +70,7 @@
#include "jsopcode.h"
#include "jsregexp.h"
#include "jsscope.h"
#include "jsstaticcheck.h"
#include "jsstr.h"
#include "jsbit.h"
@ -1580,6 +1581,8 @@ find_replen(JSContext *cx, ReplaceData *rdata, size_t *sizep)
void *mark;
JSBool ok;
JS_ASSERT_NOT_ON_TRACE(cx);
/*
* Save the regExpStatics from the current regexp, since they may be
* clobbered by a RegExp usage in the lambda function. Note that all

View File

@ -2953,7 +2953,7 @@ nanojit::Fragment::onDestroy()
delete (TreeInfo *)vmprivate;
}
bool
static JS_REQUIRES_STACK bool
js_DeleteRecorder(JSContext* cx)
{
JSTraceMonitor* tm = &JS_TRACE_MONITOR(cx);

View File

@ -600,4 +600,11 @@ js_GetBuiltinFunction(JSContext *cx, uintN index);
#endif /* !JS_TRACER */
static JS_INLINE JS_FORCES_STACK void
js_LeaveTrace(JSContext *cx)
{
if (JS_ON_TRACE(cx))
js_GetTopStackFrame(cx);
}
#endif /* jstracer_h___ */