Bug 623297 - To decide JS_ON_TRACE, check the thread, not the compartment (r=gal)

This commit is contained in:
Bill McCloskey 2011-01-24 10:36:28 -08:00
parent e1c6e82e7f
commit 34bbf897a3
4 changed files with 75 additions and 20 deletions

View File

@ -0,0 +1,14 @@
gczeal(2);
function foo() {
return /foo/;
}
function test() {
var obj = {};
for (var i = 0; i < 50; i++) {
obj["_" + i] = "J";
}
}
test();

View File

@ -815,17 +815,6 @@ private:
} /* namespace js */
/*
* N.B. JS_ON_TRACE(cx) is true if JIT code is on the stack in the current
* thread, regardless of whether cx is the context in which that trace is
* executing. cx must be a context on the current thread.
*/
#ifdef JS_TRACER
# define JS_ON_TRACE(cx) (cx->compartment && JS_TRACE_MONITOR(cx).ontrace())
#else
# define JS_ON_TRACE(cx) false
#endif
#ifdef DEBUG
# define FUNCTION_KIND_METER_LIST(_) \
_(allfun), _(heavy), _(nofreeupvar), _(onlyfreevar), \
@ -859,6 +848,18 @@ struct JSThreadData {
unsigned requestDepth;
#endif
#ifdef JS_TRACER
/*
* During trace execution (or during trace recording or
* profiling), this field points to the compartment doing the
* execution on this thread. At other times, it is NULL. If a
* thread tries to execute/record/profile one trace while another
* is still running, the initial one will abort. Therefore, we
* only need to track one tracerCompartment at a time.
*/
JSCompartment *tracerCompartment;
#endif
/*
* If non-zero, we were been asked to call the operation callback as soon
* as possible. If the thread has an active request, this contributes

View File

@ -412,9 +412,34 @@ struct JS_FRIEND_API(JSCompartment) {
}
};
#define JS_TRACE_MONITOR(cx) (cx->compartment->traceMonitor)
#define JS_SCRIPTS_TO_GC(cx) (cx->compartment->scriptsToGC)
#ifdef JS_TRACER
static inline js::TraceMonitor &
JS_TRACE_MONITOR(JSContext *cx)
{
JSCompartment *c = JS_THREAD_DATA(cx)->tracerCompartment;
if (c == NULL)
c = cx->compartment;
return c->traceMonitor;
}
#endif
/*
* N.B. JS_ON_TRACE(cx) is true if JIT code is on the stack in the current
* thread, regardless of whether cx is the context in which that trace is
* executing. cx must be a context on the current thread.
*/
static inline bool
JS_ON_TRACE(JSContext *cx)
{
#ifdef JS_TRACER
if (cx->compartment || JS_THREAD_DATA(cx)->tracerCompartment)
return JS_TRACE_MONITOR(cx).ontrace();
#endif
return false;
}
namespace js {
static inline MathCache *
GetMathCache(JSContext *cx)

View File

@ -2311,6 +2311,8 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag
JS_ASSERT(globalObj->hasOwnShape());
JS_ASSERT(cx->regs->pc == (jsbytecode*)fragment->ip);
JS_THREAD_DATA(cx)->tracerCompartment = cx->compartment;
#ifdef DEBUG
lirbuf->printer = new (tempAlloc()) LInsPrinter(tempAlloc(), TM_NUM_USED_ACCS);
#endif
@ -2460,6 +2462,8 @@ TraceRecorder::~TraceRecorder()
/* Should already have been adjusted by callers before calling delete. */
JS_ASSERT(traceMonitor->recorder != this);
JS_THREAD_DATA(cx)->tracerCompartment = NULL;
if (trashSelf)
TrashTree(fragment->root);
@ -6322,9 +6326,6 @@ public:
JS_REQUIRES_STACK TreeFragment*
TraceRecorder::findNestedCompatiblePeer(TreeFragment* f)
{
TraceMonitor* tm;
tm = &JS_TRACE_MONITOR(cx);
unsigned int ngslots = tree->globalSlots->length();
for (; f != NULL; f = f->peer) {
@ -6489,6 +6490,8 @@ TracerState::TracerState(JSContext* cx, TraceMonitor* tm, TreeFragment* f,
prev = tm->tracerState;
tm->tracerState = this;
JS_THREAD_DATA(cx)->tracerCompartment = cx->compartment;
JS_ASSERT(eos == stackBase + MAX_NATIVE_STACK_SLOTS);
JS_ASSERT(sp < eos);
@ -6517,6 +6520,8 @@ TracerState::~TracerState()
TraceMonitor *tm = &JS_TRACE_MONITOR(cx);
tm->tracerState = prev;
tm->tracecx = NULL;
JS_THREAD_DATA(cx)->tracerCompartment = NULL;
}
/* Call |f|, return the exit taken. */
@ -16902,6 +16907,14 @@ LookupLoopProfile(JSContext *cx, jsbytecode *pc)
return NULL;
}
static void
StopProfiling(JSContext *cx)
{
TraceMonitor* tm = &JS_TRACE_MONITOR(cx);
tm->profile = NULL;
JS_THREAD_DATA(cx)->tracerCompartment = NULL;
}
JS_REQUIRES_STACK TracePointAction
MonitorTracePoint(JSContext *cx, uintN& inlineCallCount, bool* blacklist,
void** traceData, uintN *traceEpoch, uint32 *loopCounter, uint32 hits)
@ -16945,6 +16958,8 @@ MonitorTracePoint(JSContext *cx, uintN& inlineCallCount, bool* blacklist,
tm->profile = prof;
JS_THREAD_DATA(cx)->tracerCompartment = cx->compartment;
if (!Interpret(cx, cx->fp(), inlineCallCount, JSINTERP_PROFILE))
return TPA_Error;
@ -16979,7 +16994,7 @@ LoopProfile::profileOperation(JSContext* cx, JSOp op)
TraceMonitor* tm = &JS_TRACE_MONITOR(cx);
if (profiled) {
tm->profile = NULL;
StopProfiling(cx);
return ProfComplete;
}
@ -16991,7 +17006,7 @@ LoopProfile::profileOperation(JSContext* cx, JSOp op)
debug_only_printf(LC_TMProfiler, "Profiling complete (loop exit) at line %u\n",
js_FramePCToLineNumber(cx, cx->fp()));
tm->profile->decide(cx);
tm->profile = NULL;
StopProfiling(cx);
return ProfComplete;
}
@ -17005,7 +17020,7 @@ LoopProfile::profileOperation(JSContext* cx, JSOp op)
if (loopStackDepth == PROFILE_MAX_INNER_LOOPS) {
debug_only_print0(LC_TMProfiler, "Profiling complete (maxnest)\n");
tm->profile->decide(cx);
tm->profile = NULL;
StopProfiling(cx);
return ProfComplete;
}
@ -17089,7 +17104,7 @@ LoopProfile::profileOperation(JSContext* cx, JSOp op)
if (numAllOps >= MAX_PROFILE_OPS) {
debug_only_print0(LC_TMProfiler, "Profiling complete (maxops)\n");
tm->profile->decide(cx);
tm->profile = NULL;
StopProfiling(cx);
return ProfComplete;
}
@ -17351,7 +17366,7 @@ AbortProfiling(JSContext *cx)
tm->profile->profiled = true;
tm->profile->traceOK = false;
tm->profile->execOK = false;
tm->profile = NULL;
StopProfiling(cx);
}
#else /* JS_METHODJIT */