mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
Bug 605330 - extend jscalls (bug 507012) tracking to cover JM and fix some mismatched calls, r=dvander, a=NPODB
--HG-- extra : rebase_source : 77f64a8ee2c88cbb00ac5671ba2532f71551f28b
This commit is contained in:
parent
c27fce5107
commit
7cdb5fabc2
@ -16,9 +16,9 @@ static void
|
||||
funcTransition(const JSFunction *,
|
||||
const JSScript *,
|
||||
const JSContext *cx,
|
||||
JSBool entering)
|
||||
int entering)
|
||||
{
|
||||
if (entering) {
|
||||
if (entering > 0) {
|
||||
++depth;
|
||||
++enters;
|
||||
if (! JS_ON_TRACE(cx))
|
||||
@ -32,7 +32,7 @@ funcTransition(const JSFunction *,
|
||||
static JSBool called2 = false;
|
||||
|
||||
static void
|
||||
funcTransition2(const JSFunction *, const JSScript*, const JSContext*, JSBool)
|
||||
funcTransition2(const JSFunction *, const JSScript*, const JSContext*, int)
|
||||
{
|
||||
called2 = true;
|
||||
}
|
||||
@ -43,7 +43,7 @@ static void
|
||||
funcTransitionOverlay(const JSFunction *fun,
|
||||
const JSScript *script,
|
||||
const JSContext *cx,
|
||||
JSBool entering)
|
||||
int entering)
|
||||
{
|
||||
(*innerCallback)(fun, script, cx, entering);
|
||||
overlays++;
|
||||
@ -66,7 +66,7 @@ BEGIN_TEST(testFuncCallback_bug507012)
|
||||
|
||||
// Check whether the basic function tracking works
|
||||
EXEC("f(1)");
|
||||
CHECK(enters == 2 && leaves == 2 && depth == 0);
|
||||
CHECK(enters == 1+1 && leaves == 1+1 && depth == 0);
|
||||
|
||||
// Can we switch to a different callback?
|
||||
enters = 777;
|
||||
@ -91,7 +91,7 @@ BEGIN_TEST(testFuncCallback_bug507012)
|
||||
EXEC("function g () { ++x; }");
|
||||
interpreted = enters = leaves = depth = 0;
|
||||
EXEC("for (i = 0; i < 50; ++i) { g(); }");
|
||||
CHECK(enters == 50+1 && leaves == 50+1 && depth == 0);
|
||||
CHECK(enters == 1+50 && leaves == 1+50 && depth == 0);
|
||||
|
||||
// If this fails, it means that the code was interpreted rather
|
||||
// than trace-JITted, and so is not testing what it's supposed to
|
||||
@ -114,7 +114,7 @@ BEGIN_TEST(testFuncCallback_bug507012)
|
||||
CHECK(enters == 1);
|
||||
CHECK(leaves == 1);
|
||||
CHECK(depth == 0);
|
||||
CHECK(overlays == 2); // 1 each for enter and exit
|
||||
CHECK(overlays == enters + leaves);
|
||||
interpreted = enters = leaves = depth = overlays = 0;
|
||||
#endif
|
||||
|
||||
|
@ -3307,8 +3307,17 @@ JS_ClearContextThread(JSContext *cx);
|
||||
typedef void (*JSFunctionCallback)(const JSFunction *fun,
|
||||
const JSScript *scr,
|
||||
const JSContext *cx,
|
||||
JSBool entering);
|
||||
int entering);
|
||||
|
||||
/*
|
||||
* The callback is expected to be quick and noninvasive. It should not
|
||||
* trigger interrupts, turn on debugging, or produce uncaught JS
|
||||
* exceptions. The state of the stack and registers in the context
|
||||
* cannot be relied upon, since this callback may be invoked directly
|
||||
* from either JIT. The 'entering' field means we are entering a
|
||||
* function if it is positive, leaving a function if it is zero or
|
||||
* negative.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetFunctionCallback(JSContext *cx, JSFunctionCallback fcb);
|
||||
|
||||
|
@ -2176,7 +2176,7 @@ struct JSContext
|
||||
|
||||
void doFunctionCallback(const JSFunction *fun,
|
||||
const JSScript *scr,
|
||||
JSBool entering) const
|
||||
int entering) const
|
||||
{
|
||||
if (functionCallback)
|
||||
functionCallback(fun, scr, this, entering);
|
||||
|
@ -1347,10 +1347,10 @@ DirectEval(JSContext *cx, JSFunction *evalfun, uint32 argc, Value *vp)
|
||||
JS_ASSERT(vp[0].toObject().getFunctionPrivate() == evalfun);
|
||||
JS_ASSERT(IsBuiltinEvalFunction(evalfun));
|
||||
|
||||
AutoFunctionCallProbe callProbe(cx, evalfun);
|
||||
|
||||
JSStackFrame *caller = cx->fp();
|
||||
JS_ASSERT(caller->isScriptFrame());
|
||||
AutoFunctionCallProbe callProbe(cx, evalfun, caller->script());
|
||||
|
||||
JSObject *scopeChain =
|
||||
GetScopeChainFast(cx, caller, JSOP_EVAL, JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH);
|
||||
if (!scopeChain || !EvalKernel(cx, argc, vp, DIRECT_EVAL, caller, scopeChain))
|
||||
@ -2214,7 +2214,8 @@ ScriptPrologue(JSContext *cx, JSStackFrame *fp)
|
||||
if (JS_UNLIKELY(hook != NULL) && !fp->isExecuteFrame())
|
||||
fp->setHookData(hook(cx, fp, JS_TRUE, 0, cx->debugHooks->callHookData));
|
||||
|
||||
Probes::enterJSFun(cx, fp->maybeFun());
|
||||
if (!fp->isExecuteFrame())
|
||||
Probes::enterJSFun(cx, fp->maybeFun(), fp->maybeScript());
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -4751,9 +4752,9 @@ BEGIN_CASE(JSOP_FUNCALL)
|
||||
DO_OP();
|
||||
}
|
||||
|
||||
Probes::enterJSFun(cx, newfun);
|
||||
Probes::enterJSFun(cx, newfun, script);
|
||||
JSBool ok = CallJSNative(cx, newfun->u.n.native, argc, vp);
|
||||
Probes::exitJSFun(cx, newfun);
|
||||
Probes::exitJSFun(cx, newfun, script);
|
||||
regs.sp = vp + 1;
|
||||
if (!ok)
|
||||
goto error;
|
||||
|
@ -592,7 +592,7 @@ InvokeSessionGuard::invoke(JSContext *cx) const
|
||||
JSBool ok;
|
||||
{
|
||||
AutoPreserveEnumerators preserve(cx);
|
||||
Probes::enterJSFun(cx, fp->fun());
|
||||
Probes::enterJSFun(cx, fp->fun(), script_);
|
||||
#ifdef JS_METHODJIT
|
||||
AutoInterpPreparer prepareInterp(cx, script_);
|
||||
ok = mjit::EnterMethodJIT(cx, fp, code_, stackLimit_);
|
||||
@ -601,7 +601,7 @@ InvokeSessionGuard::invoke(JSContext *cx) const
|
||||
cx->regs->pc = script_->code;
|
||||
ok = Interpret(cx, cx->fp());
|
||||
#endif
|
||||
Probes::exitJSFun(cx, fp->fun());
|
||||
Probes::exitJSFun(cx, fp->fun(), script_);
|
||||
}
|
||||
|
||||
PutActivationObjects(cx, fp);
|
||||
@ -706,7 +706,9 @@ ValuePropertyBearer(JSContext *cx, const Value &v, int spindex)
|
||||
static inline bool
|
||||
ScriptEpilogue(JSContext *cx, JSStackFrame *fp, JSBool ok)
|
||||
{
|
||||
Probes::exitJSFun(cx, fp->maybeFun());
|
||||
if (!fp->isExecuteFrame())
|
||||
Probes::exitJSFun(cx, fp->maybeFun(), fp->maybeScript());
|
||||
|
||||
JSInterpreterHook hook = cx->debugHooks->callHook;
|
||||
if (hook && fp->hasHookData() && !fp->isExecuteFrame())
|
||||
hook(cx, fp, JS_FALSE, &ok, fp->hookData());
|
||||
|
@ -152,16 +152,16 @@ Probes::FunctionName(JSContext *cx, const JSFunction *fun)
|
||||
* a number of usually unused lines of code would cause.
|
||||
*/
|
||||
void
|
||||
Probes::enterJSFunImpl(JSContext *cx, const JSFunction *fun)
|
||||
Probes::enterJSFunImpl(JSContext *cx, JSFunction *fun, JSScript *script)
|
||||
{
|
||||
JAVASCRIPT_FUNCTION_ENTRY(ScriptFilename(FUN_SCRIPT(fun)), FunctionClassname(fun),
|
||||
JAVASCRIPT_FUNCTION_ENTRY(ScriptFilename(script), FunctionClassname(fun),
|
||||
FunctionName(cx, fun));
|
||||
}
|
||||
|
||||
void
|
||||
Probes::handleFunctionReturn(JSContext *cx, JSFunction *fun)
|
||||
Probes::handleFunctionReturn(JSContext *cx, JSFunction *fun, JSScript *script)
|
||||
{
|
||||
JAVASCRIPT_FUNCTION_RETURN(ScriptFilename(FUN_SCRIPT(fun)), FunctionClassname(fun),
|
||||
JAVASCRIPT_FUNCTION_RETURN(ScriptFilename(script), FunctionClassname(fun),
|
||||
FunctionName(cx, fun));
|
||||
}
|
||||
|
||||
|
@ -52,16 +52,14 @@ class Probes {
|
||||
static int FunctionLineNumber(JSContext *cx, const JSFunction *fun);
|
||||
static const char *FunctionName(JSContext *cx, const JSFunction *fun);
|
||||
|
||||
static void enterJSFunImpl(JSContext *cx, const JSFunction *fun);
|
||||
static void handleFunctionReturn(JSContext *cx, JSFunction *fun);
|
||||
static void enterJSFunImpl(JSContext *cx, JSFunction *fun, JSScript *script);
|
||||
static void handleFunctionReturn(JSContext *cx, JSFunction *fun, JSScript *script);
|
||||
static void finalizeObjectImpl(JSObject *obj);
|
||||
public:
|
||||
/*
|
||||
* If |lval| is provided to the enter/exit methods, it is tested to see if
|
||||
* it is a function as a predicate to the dtrace event emission.
|
||||
*/
|
||||
static void enterJSFun(JSContext *cx, JSFunction *fun, js::Value *lval = NULL);
|
||||
static void exitJSFun(JSContext *cx, JSFunction *fun, js::Value *lval = NULL);
|
||||
static bool callTrackingActive(JSContext *);
|
||||
|
||||
static void enterJSFun(JSContext *, JSFunction *, JSScript *, int counter = 1);
|
||||
static void exitJSFun(JSContext *, JSFunction *, JSScript *, int counter = 0);
|
||||
|
||||
static void startExecution(JSContext *cx, JSScript *script);
|
||||
static void stopExecution(JSContext *cx, JSScript *script);
|
||||
@ -113,31 +111,47 @@ class Probes {
|
||||
static JSBool CustomMark(int marker);
|
||||
};
|
||||
|
||||
inline void
|
||||
Probes::enterJSFun(JSContext *cx, JSFunction *fun, js::Value *lval)
|
||||
inline bool
|
||||
Probes::callTrackingActive(JSContext *cx)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (!lval || IsFunctionObject(*lval)) {
|
||||
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
|
||||
enterJSFunImpl(cx, fun);
|
||||
}
|
||||
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED() || JAVASCRIPT_FUNCTION_RETURN_ENABLED())
|
||||
return true;
|
||||
#endif
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
cx->doFunctionCallback(fun, fun ? FUN_SCRIPT(fun) : NULL, true);
|
||||
if (cx->functionCallback)
|
||||
return true;
|
||||
#endif
|
||||
#ifdef MOZ_ETW
|
||||
if (ProfilingActive && MCGEN_ENABLE_CHECK(MozillaSpiderMonkey_Context, EvtFunctionEntry))
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void
|
||||
Probes::enterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
|
||||
enterJSFunImpl(cx, fun, script);
|
||||
#endif
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
cx->doFunctionCallback(fun, script, counter);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void
|
||||
Probes::exitJSFun(JSContext *cx, JSFunction *fun, js::Value *lval)
|
||||
Probes::exitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (!lval || IsFunctionObject(*lval)) {
|
||||
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
|
||||
handleFunctionReturn(cx, fun);
|
||||
}
|
||||
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
|
||||
handleFunctionReturn(cx, fun, script);
|
||||
#endif
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
cx->doFunctionCallback(fun, fun ? FUN_SCRIPT(fun) : NULL, false);
|
||||
if (counter > 0)
|
||||
counter = -counter;
|
||||
cx->doFunctionCallback(fun, script, counter);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -170,11 +184,11 @@ Probes::startExecution(JSContext *cx, JSScript *script)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_EXECUTE_START_ENABLED())
|
||||
JAVASCRIPT_EXECUTE_START(script->filename ? (char *)script->filename : nullName,
|
||||
JAVASCRIPT_EXECUTE_START((script->filename ? (char *)script->filename : nullName),
|
||||
script->lineno);
|
||||
#endif
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
cx->doFunctionCallback(NULL, script, true);
|
||||
cx->doFunctionCallback(NULL, script, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -183,11 +197,11 @@ Probes::stopExecution(JSContext *cx, JSScript *script)
|
||||
{
|
||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||
if (JAVASCRIPT_EXECUTE_DONE_ENABLED())
|
||||
JAVASCRIPT_EXECUTE_DONE(script->filename ? (char *)script->filename : nullName,
|
||||
JAVASCRIPT_EXECUTE_DONE((script->filename ? (char *)script->filename : nullName),
|
||||
script->lineno);
|
||||
#endif
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
cx->doFunctionCallback(NULL, script, false);
|
||||
cx->doFunctionCallback(NULL, script, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -219,19 +233,19 @@ inline JSBool Probes::CustomMark(int marker) { return JS_TRUE; }
|
||||
struct AutoFunctionCallProbe {
|
||||
JSContext * const cx;
|
||||
JSFunction *fun;
|
||||
js::Value *lval;
|
||||
JSScript *script;
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
AutoFunctionCallProbe(JSContext *cx, JSFunction *fun, js::Value *lval = NULL
|
||||
AutoFunctionCallProbe(JSContext *cx, JSFunction *fun, JSScript *script
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: cx(cx), fun(fun), lval(lval)
|
||||
: cx(cx), fun(fun), script(script)
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
Probes::enterJSFun(cx, fun, lval);
|
||||
Probes::enterJSFun(cx, fun, script);
|
||||
}
|
||||
|
||||
~AutoFunctionCallProbe() {
|
||||
Probes::exitJSFun(cx, fun, lval);
|
||||
Probes::exitJSFun(cx, fun, script);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -10236,22 +10236,20 @@ TraceRecorder::record_JSOP_LEAVEWITH()
|
||||
return ARECORD_STOP;
|
||||
}
|
||||
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
// Usually, cx->doFunctionCallback() is invoked via DTrace::enterJSFun
|
||||
// and friends, but the DTrace:: probes use fp and therefore would
|
||||
// need to break out of tracing. So we define a functionProbe()
|
||||
// callback to be called by generated code when a Javascript function
|
||||
// is entered or exited.
|
||||
static JSBool JS_FASTCALL
|
||||
functionProbe(JSContext *cx, JSFunction *fun, JSBool enter)
|
||||
functionProbe(JSContext *cx, JSFunction *fun, int enter)
|
||||
{
|
||||
cx->doFunctionCallback(fun, FUN_SCRIPT(fun), enter);
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
JSScript *script = fun ? FUN_SCRIPT(fun) : NULL;
|
||||
if (enter > 0)
|
||||
Probes::enterJSFun(cx, fun, script, enter);
|
||||
else
|
||||
Probes::exitJSFun(cx, fun, script, enter);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_DEFINE_CALLINFO_3(static, BOOL, functionProbe, CONTEXT, FUNCTION, BOOL,
|
||||
0, ACCSET_STORE_ANY)
|
||||
#endif
|
||||
JS_DEFINE_CALLINFO_3(static, BOOL, functionProbe, CONTEXT, FUNCTION, INT32, 0, ACCSET_ALL)
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::record_JSOP_RETURN()
|
||||
@ -10264,13 +10262,11 @@ TraceRecorder::record_JSOP_RETURN()
|
||||
|
||||
putActivationObjects();
|
||||
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
if (cx->functionCallback) {
|
||||
if (Probes::callTrackingActive(cx)) {
|
||||
LIns* args[] = { w.immi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
|
||||
LIns* call_ins = w.call(&functionProbe_ci, args);
|
||||
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If we inlined this function call, make the return value available to the caller code. */
|
||||
Value& rval = stackval(-1);
|
||||
@ -11389,8 +11385,7 @@ TraceRecorder::functionCall(uintN argc, JSOp mode)
|
||||
*/
|
||||
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &fval.toObject());
|
||||
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
if (cx->functionCallback) {
|
||||
if (Probes::callTrackingActive(cx)) {
|
||||
JSScript *script = FUN_SCRIPT(fun);
|
||||
if (! script || ! script->isEmpty()) {
|
||||
LIns* args[] = { w.immi(1), w.nameImmpNonGC(fun), cx_ins };
|
||||
@ -11398,7 +11393,6 @@ TraceRecorder::functionCall(uintN argc, JSOp mode)
|
||||
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (FUN_INTERPRETED(fun))
|
||||
return interpretedFunctionCall(fval, fun, argc, mode == JSOP_NEW);
|
||||
@ -11420,13 +11414,11 @@ TraceRecorder::functionCall(uintN argc, JSOp mode)
|
||||
}
|
||||
|
||||
RecordingStatus rs = callNative(argc, mode);
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
if (cx->functionCallback) {
|
||||
if (Probes::callTrackingActive(cx)) {
|
||||
LIns* args[] = { w.immi(0), w.nameImmpNonGC(fun), cx_ins };
|
||||
LIns* call_ins = w.call(&functionProbe_ci, args);
|
||||
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
||||
}
|
||||
#endif
|
||||
return rs;
|
||||
}
|
||||
|
||||
@ -15514,13 +15506,11 @@ TraceRecorder::record_JSOP_STOP()
|
||||
|
||||
putActivationObjects();
|
||||
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
if (cx->functionCallback) {
|
||||
if (Probes::callTrackingActive(cx)) {
|
||||
LIns* args[] = { w.immi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
|
||||
LIns* call_ins = w.call(&functionProbe_ci, args);
|
||||
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We know falling off the end of a constructor returns the new object that
|
||||
|
@ -361,7 +361,7 @@ mjit::Compiler::generatePrologue()
|
||||
if (isConstructing)
|
||||
constructThis();
|
||||
|
||||
if (debugMode)
|
||||
if (debugMode || Probes::callTrackingActive(cx))
|
||||
stubCall(stubs::EnterScript);
|
||||
|
||||
return Compile_Okay;
|
||||
@ -2199,7 +2199,7 @@ mjit::Compiler::emitReturn(FrameEntry *fe)
|
||||
/* Only the top of the stack can be returned. */
|
||||
JS_ASSERT_IF(fe, fe == frame.peek(-1));
|
||||
|
||||
if (debugMode) {
|
||||
if (debugMode || Probes::callTrackingActive(cx)) {
|
||||
prepareStubCall(Uses(0));
|
||||
stubCall(stubs::LeaveScript);
|
||||
}
|
||||
|
@ -608,12 +608,15 @@ stubs::EnterScript(VMFrame &f)
|
||||
{
|
||||
JSStackFrame *fp = f.fp();
|
||||
JSContext *cx = f.cx;
|
||||
JSInterpreterHook hook = cx->debugHooks->callHook;
|
||||
if (JS_UNLIKELY(hook != NULL) && !fp->isExecuteFrame()) {
|
||||
fp->setHookData(hook(cx, fp, JS_TRUE, 0, cx->debugHooks->callHookData));
|
||||
|
||||
if (fp->script()->debugMode) {
|
||||
JSInterpreterHook hook = cx->debugHooks->callHook;
|
||||
if (JS_UNLIKELY(hook != NULL) && !fp->isExecuteFrame()) {
|
||||
fp->setHookData(hook(cx, fp, JS_TRUE, 0, cx->debugHooks->callHookData));
|
||||
}
|
||||
}
|
||||
|
||||
Probes::enterJSFun(cx, fp->maybeFun());
|
||||
Probes::enterJSFun(cx, fp->maybeFun(), fp->script());
|
||||
}
|
||||
|
||||
void JS_FASTCALL
|
||||
@ -621,14 +624,17 @@ stubs::LeaveScript(VMFrame &f)
|
||||
{
|
||||
JSStackFrame *fp = f.fp();
|
||||
JSContext *cx = f.cx;
|
||||
Probes::exitJSFun(cx, fp->maybeFun());
|
||||
JSInterpreterHook hook = cx->debugHooks->callHook;
|
||||
Probes::exitJSFun(cx, fp->maybeFun(), fp->maybeScript());
|
||||
|
||||
if (hook && fp->hasHookData() && !fp->isExecuteFrame()) {
|
||||
JSBool ok = JS_TRUE;
|
||||
hook(cx, fp, JS_FALSE, &ok, fp->hookData());
|
||||
if (!ok)
|
||||
THROW();
|
||||
if (fp->script()->debugMode) {
|
||||
JSInterpreterHook hook = cx->debugHooks->callHook;
|
||||
|
||||
if (hook && fp->hasHookData() && !fp->isExecuteFrame()) {
|
||||
JSBool ok = JS_TRUE;
|
||||
hook(cx, fp, JS_FALSE, &ok, fp->hookData());
|
||||
if (!ok)
|
||||
THROW();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user