Bug 680428 - onEnterFrame does not work with tracejit. r=dvander.

--HG--
rename : js/src/jit-test/tests/debug/onEnterFrame-05.js => js/src/jit-test/tests/debug/onEnterFrame-04.js
This commit is contained in:
Jason Orendorff 2011-08-23 14:42:17 -05:00
parent f3aa16a31d
commit 44cd5a6f2c
7 changed files with 103 additions and 29 deletions

View File

@ -0,0 +1,17 @@
// We detect and stop the runaway recursion caused by making onEnterFrame a wrapper of a debuggee function.
var g = newGlobal('new-compartment');
g.n = 0;
g.eval("function f(frame) { n++; return 42; }");
print('ok');
var dbg = Debugger(g);
dbg.onEnterFrame = g.f;
// Since enterFrame cannot throw, the InternalError is reported and execution proceeds.
var x = g.f();
assertEq(x, 42);
assertEq(g.n > 20, true);
// When an error is reported, the shell usually exits with a nonzero exit
// code. If we get here, the test passed, so override that behavior.
quit(0);

View File

@ -1,17 +1,15 @@
// We detect and stop the runaway recursion caused by making onEnterFrame a wrapper of a debuggee function.
// The tracejit does not prevent onEnterFrame from being called.
var g = newGlobal('new-compartment');
g.n = 0;
g.eval("function f(frame) { n++; return 42; }");
print('ok');
g.eval("function f() { return 1; }\n");
var N = g.N = RUNLOOP + 2;
g.eval("function h() {\n" +
" for (var i = 0; i < N; i += f()) {}\n" +
"}");
g.h(); // record loop
var dbg = Debugger(g);
dbg.onEnterFrame = g.f;
// Since enterFrame cannot throw, the InternalError is reported and execution proceeds.
var x = g.f();
assertEq(x, 42);
assertEq(g.n > 20, true);
// When an error is reported, the shell usually exits with a nonzero exit
// code. If we get here, the test passed, so override that behavior.
quit(0);
var log = '';
dbg.onEnterFrame = function (frame) { log += frame.callee.name; };
g.h();
assertEq(log, 'h' + Array(N + 1).join('f'));

View File

@ -0,0 +1,19 @@
// The tracejit does not prevent onEnterFrame from being called after entering
// a debuggee compartment from a non-debuggee compartment.
var g1 = newGlobal('new-compartment');
var g2 = newGlobal('new-compartment');
var dbg = Debugger(g1, g2);
dbg.removeDebuggee(g2); // turn off debug mode in g2
g1.eval("function f() { return 1; }\n");
var N = g1.N = RUNLOOP + 2;
g1.eval("function h() {\n" +
" for (var i = 0; i < N; i += f()) {}\n" +
"}");
g1.h(); // record loop
var log = '';
dbg.onEnterFrame = function (frame) { log += frame.callee.name; };
g1.h();
assertEq(log, 'h' + Array(N + 1).join('f'));

View File

@ -570,7 +570,7 @@ js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp)
Maybe<AutoLockGC> lockIf;
if (unlocked)
lockIf.construct(rt);
cx = js_ContextFromLinkField(cx ? cx->link.next : rt->contextList.next);
cx = JSContext::fromLinkField(cx ? cx->link.next : rt->contextList.next);
if (&cx->link == &rt->contextList)
cx = NULL;
*iterp = cx;
@ -1387,9 +1387,9 @@ JSContext::resetCompartment()
}
compartment = scopeobj->compartment();
if (isExceptionPending())
wrapPendingException();
updateJITEnabled();
return;
error:
@ -1580,6 +1580,8 @@ JSContext::updateJITEnabled()
#ifdef JS_TRACER
traceJitEnabled = ((runOptions & JSOPTION_JIT) &&
!IsJITBrokenHere() &&
compartment &&
!compartment->debugMode() &&
(debugHooks == &js_NullDebugHooks ||
(debugHooks == &runtime->globalDebugHooks &&
!runtime->debuggerInhibitsJIT())));

View File

@ -1144,9 +1144,6 @@ struct JSContext
without the corresponding
JS_EndRequest. */
JSCList threadLinks; /* JSThread contextList linkage */
#define CX_FROM_THREAD_LINKS(tl) \
((JSContext *)((char *)(tl) - offsetof(JSContext, threadLinks)))
#endif
/* Stack of thread-stack-allocated GC roots. */
@ -1325,6 +1322,18 @@ struct JSContext
*/
bool runningWithTrustedPrincipals() const;
static inline JSContext *fromLinkField(JSCList *link) {
JS_ASSERT(link);
return reinterpret_cast<JSContext *>(uintptr_t(link) - offsetof(JSContext, link));
}
#ifdef JS_THREADSAFE
static inline JSContext *fromThreadLinks(JSCList *link) {
JS_ASSERT(link);
return reinterpret_cast<JSContext *>(uintptr_t(link) - offsetof(JSContext, threadLinks));
}
#endif
private:
/*
* The allocation code calls the function to indicate either OOM failure
@ -2137,6 +2146,36 @@ class ThreadDataIter
#endif /* !JS_THREADSAFE */
/*
* Enumerate all contexts in a runtime that are in the same thread as a given
* context.
*/
class ThreadContextRange {
JSCList *begin;
JSCList *end;
public:
explicit ThreadContextRange(JSContext *cx) {
#ifdef JS_THREADSAFE
end = &cx->thread()->contextList;
#else
end = &cx->runtime->contextList;
#endif
begin = end->next;
}
bool empty() const { return begin == end; }
void popFront() { JS_ASSERT(!empty()); begin = begin->next; }
JSContext *front() const {
#ifdef JS_THREADSAFE
return JSContext::fromThreadLinks(begin);
#else
return JSContext::fromLinkField(begin);
#endif
}
};
} /* namespace js */
/*
@ -2149,13 +2188,6 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize);
extern void
js_DestroyContext(JSContext *cx, JSDestroyContextMode mode);
static JS_INLINE JSContext *
js_ContextFromLinkField(JSCList *link)
{
JS_ASSERT(link);
return reinterpret_cast<JSContext *>(uintptr_t(link) - offsetof(JSContext, link));
}
/*
* If unlocked, acquire and release rt->gcLock around *iterp update; otherwise
* the caller must be holding rt->gcLock.

View File

@ -667,7 +667,7 @@ JSCompartment::setDebugModeFromC(JSContext *cx, bool b)
debugModeBits = (debugModeBits & ~uintN(DebugFromC)) | (b ? DebugFromC : 0);
JS_ASSERT(debugMode() == enabledAfter);
if (enabledBefore != enabledAfter && !onStack)
if (enabledBefore != enabledAfter)
updateForDebugMode(cx);
return true;
}
@ -675,6 +675,12 @@ JSCompartment::setDebugModeFromC(JSContext *cx, bool b)
void
JSCompartment::updateForDebugMode(JSContext *cx)
{
for (ThreadContextRange r(cx); !r.empty(); r.popFront()) {
JSContext *cx = r.front();
if (cx->compartment == this)
cx->updateJITEnabled();
}
#ifdef JS_METHODJIT
bool enabled = debugMode();

View File

@ -289,11 +289,11 @@ JITInhibitingHookChange(JSRuntime *rt, bool wasInhibited)
if (wasInhibited) {
if (!rt->debuggerInhibitsJIT()) {
for (JSCList *cl = rt->contextList.next; cl != &rt->contextList; cl = cl->next)
js_ContextFromLinkField(cl)->updateJITEnabled();
JSContext::fromLinkField(cl)->updateJITEnabled();
}
} else if (rt->debuggerInhibitsJIT()) {
for (JSCList *cl = rt->contextList.next; cl != &rt->contextList; cl = cl->next)
js_ContextFromLinkField(cl)->traceJitEnabled = false;
JSContext::fromLinkField(cl)->traceJitEnabled = false;
}
}
#endif