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 *,
|
funcTransition(const JSFunction *,
|
||||||
const JSScript *,
|
const JSScript *,
|
||||||
const JSContext *cx,
|
const JSContext *cx,
|
||||||
JSBool entering)
|
int entering)
|
||||||
{
|
{
|
||||||
if (entering) {
|
if (entering > 0) {
|
||||||
++depth;
|
++depth;
|
||||||
++enters;
|
++enters;
|
||||||
if (! JS_ON_TRACE(cx))
|
if (! JS_ON_TRACE(cx))
|
||||||
@ -32,7 +32,7 @@ funcTransition(const JSFunction *,
|
|||||||
static JSBool called2 = false;
|
static JSBool called2 = false;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
funcTransition2(const JSFunction *, const JSScript*, const JSContext*, JSBool)
|
funcTransition2(const JSFunction *, const JSScript*, const JSContext*, int)
|
||||||
{
|
{
|
||||||
called2 = true;
|
called2 = true;
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ static void
|
|||||||
funcTransitionOverlay(const JSFunction *fun,
|
funcTransitionOverlay(const JSFunction *fun,
|
||||||
const JSScript *script,
|
const JSScript *script,
|
||||||
const JSContext *cx,
|
const JSContext *cx,
|
||||||
JSBool entering)
|
int entering)
|
||||||
{
|
{
|
||||||
(*innerCallback)(fun, script, cx, entering);
|
(*innerCallback)(fun, script, cx, entering);
|
||||||
overlays++;
|
overlays++;
|
||||||
@ -66,7 +66,7 @@ BEGIN_TEST(testFuncCallback_bug507012)
|
|||||||
|
|
||||||
// Check whether the basic function tracking works
|
// Check whether the basic function tracking works
|
||||||
EXEC("f(1)");
|
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?
|
// Can we switch to a different callback?
|
||||||
enters = 777;
|
enters = 777;
|
||||||
@ -91,7 +91,7 @@ BEGIN_TEST(testFuncCallback_bug507012)
|
|||||||
EXEC("function g () { ++x; }");
|
EXEC("function g () { ++x; }");
|
||||||
interpreted = enters = leaves = depth = 0;
|
interpreted = enters = leaves = depth = 0;
|
||||||
EXEC("for (i = 0; i < 50; ++i) { g(); }");
|
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
|
// If this fails, it means that the code was interpreted rather
|
||||||
// than trace-JITted, and so is not testing what it's supposed to
|
// 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(enters == 1);
|
||||||
CHECK(leaves == 1);
|
CHECK(leaves == 1);
|
||||||
CHECK(depth == 0);
|
CHECK(depth == 0);
|
||||||
CHECK(overlays == 2); // 1 each for enter and exit
|
CHECK(overlays == enters + leaves);
|
||||||
interpreted = enters = leaves = depth = overlays = 0;
|
interpreted = enters = leaves = depth = overlays = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3307,8 +3307,17 @@ JS_ClearContextThread(JSContext *cx);
|
|||||||
typedef void (*JSFunctionCallback)(const JSFunction *fun,
|
typedef void (*JSFunctionCallback)(const JSFunction *fun,
|
||||||
const JSScript *scr,
|
const JSScript *scr,
|
||||||
const JSContext *cx,
|
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)
|
extern JS_PUBLIC_API(void)
|
||||||
JS_SetFunctionCallback(JSContext *cx, JSFunctionCallback fcb);
|
JS_SetFunctionCallback(JSContext *cx, JSFunctionCallback fcb);
|
||||||
|
|
||||||
|
@ -2176,7 +2176,7 @@ struct JSContext
|
|||||||
|
|
||||||
void doFunctionCallback(const JSFunction *fun,
|
void doFunctionCallback(const JSFunction *fun,
|
||||||
const JSScript *scr,
|
const JSScript *scr,
|
||||||
JSBool entering) const
|
int entering) const
|
||||||
{
|
{
|
||||||
if (functionCallback)
|
if (functionCallback)
|
||||||
functionCallback(fun, scr, this, entering);
|
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(vp[0].toObject().getFunctionPrivate() == evalfun);
|
||||||
JS_ASSERT(IsBuiltinEvalFunction(evalfun));
|
JS_ASSERT(IsBuiltinEvalFunction(evalfun));
|
||||||
|
|
||||||
AutoFunctionCallProbe callProbe(cx, evalfun);
|
|
||||||
|
|
||||||
JSStackFrame *caller = cx->fp();
|
JSStackFrame *caller = cx->fp();
|
||||||
JS_ASSERT(caller->isScriptFrame());
|
JS_ASSERT(caller->isScriptFrame());
|
||||||
|
AutoFunctionCallProbe callProbe(cx, evalfun, caller->script());
|
||||||
|
|
||||||
JSObject *scopeChain =
|
JSObject *scopeChain =
|
||||||
GetScopeChainFast(cx, caller, JSOP_EVAL, JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH);
|
GetScopeChainFast(cx, caller, JSOP_EVAL, JSOP_EVAL_LENGTH + JSOP_LINENO_LENGTH);
|
||||||
if (!scopeChain || !EvalKernel(cx, argc, vp, DIRECT_EVAL, caller, scopeChain))
|
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())
|
if (JS_UNLIKELY(hook != NULL) && !fp->isExecuteFrame())
|
||||||
fp->setHookData(hook(cx, fp, JS_TRUE, 0, cx->debugHooks->callHookData));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -4751,9 +4752,9 @@ BEGIN_CASE(JSOP_FUNCALL)
|
|||||||
DO_OP();
|
DO_OP();
|
||||||
}
|
}
|
||||||
|
|
||||||
Probes::enterJSFun(cx, newfun);
|
Probes::enterJSFun(cx, newfun, script);
|
||||||
JSBool ok = CallJSNative(cx, newfun->u.n.native, argc, vp);
|
JSBool ok = CallJSNative(cx, newfun->u.n.native, argc, vp);
|
||||||
Probes::exitJSFun(cx, newfun);
|
Probes::exitJSFun(cx, newfun, script);
|
||||||
regs.sp = vp + 1;
|
regs.sp = vp + 1;
|
||||||
if (!ok)
|
if (!ok)
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -592,7 +592,7 @@ InvokeSessionGuard::invoke(JSContext *cx) const
|
|||||||
JSBool ok;
|
JSBool ok;
|
||||||
{
|
{
|
||||||
AutoPreserveEnumerators preserve(cx);
|
AutoPreserveEnumerators preserve(cx);
|
||||||
Probes::enterJSFun(cx, fp->fun());
|
Probes::enterJSFun(cx, fp->fun(), script_);
|
||||||
#ifdef JS_METHODJIT
|
#ifdef JS_METHODJIT
|
||||||
AutoInterpPreparer prepareInterp(cx, script_);
|
AutoInterpPreparer prepareInterp(cx, script_);
|
||||||
ok = mjit::EnterMethodJIT(cx, fp, code_, stackLimit_);
|
ok = mjit::EnterMethodJIT(cx, fp, code_, stackLimit_);
|
||||||
@ -601,7 +601,7 @@ InvokeSessionGuard::invoke(JSContext *cx) const
|
|||||||
cx->regs->pc = script_->code;
|
cx->regs->pc = script_->code;
|
||||||
ok = Interpret(cx, cx->fp());
|
ok = Interpret(cx, cx->fp());
|
||||||
#endif
|
#endif
|
||||||
Probes::exitJSFun(cx, fp->fun());
|
Probes::exitJSFun(cx, fp->fun(), script_);
|
||||||
}
|
}
|
||||||
|
|
||||||
PutActivationObjects(cx, fp);
|
PutActivationObjects(cx, fp);
|
||||||
@ -706,7 +706,9 @@ ValuePropertyBearer(JSContext *cx, const Value &v, int spindex)
|
|||||||
static inline bool
|
static inline bool
|
||||||
ScriptEpilogue(JSContext *cx, JSStackFrame *fp, JSBool ok)
|
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;
|
JSInterpreterHook hook = cx->debugHooks->callHook;
|
||||||
if (hook && fp->hasHookData() && !fp->isExecuteFrame())
|
if (hook && fp->hasHookData() && !fp->isExecuteFrame())
|
||||||
hook(cx, fp, JS_FALSE, &ok, fp->hookData());
|
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.
|
* a number of usually unused lines of code would cause.
|
||||||
*/
|
*/
|
||||||
void
|
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));
|
FunctionName(cx, fun));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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));
|
FunctionName(cx, fun));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,16 +52,14 @@ class Probes {
|
|||||||
static int FunctionLineNumber(JSContext *cx, const JSFunction *fun);
|
static int FunctionLineNumber(JSContext *cx, const JSFunction *fun);
|
||||||
static const char *FunctionName(JSContext *cx, const JSFunction *fun);
|
static const char *FunctionName(JSContext *cx, const JSFunction *fun);
|
||||||
|
|
||||||
static void enterJSFunImpl(JSContext *cx, const JSFunction *fun);
|
static void enterJSFunImpl(JSContext *cx, JSFunction *fun, JSScript *script);
|
||||||
static void handleFunctionReturn(JSContext *cx, JSFunction *fun);
|
static void handleFunctionReturn(JSContext *cx, JSFunction *fun, JSScript *script);
|
||||||
static void finalizeObjectImpl(JSObject *obj);
|
static void finalizeObjectImpl(JSObject *obj);
|
||||||
public:
|
public:
|
||||||
/*
|
static bool callTrackingActive(JSContext *);
|
||||||
* 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 *, JSFunction *, JSScript *, int counter = 1);
|
||||||
*/
|
static void exitJSFun(JSContext *, JSFunction *, JSScript *, int counter = 0);
|
||||||
static void enterJSFun(JSContext *cx, JSFunction *fun, js::Value *lval = NULL);
|
|
||||||
static void exitJSFun(JSContext *cx, JSFunction *fun, js::Value *lval = NULL);
|
|
||||||
|
|
||||||
static void startExecution(JSContext *cx, JSScript *script);
|
static void startExecution(JSContext *cx, JSScript *script);
|
||||||
static void stopExecution(JSContext *cx, JSScript *script);
|
static void stopExecution(JSContext *cx, JSScript *script);
|
||||||
@ -113,31 +111,47 @@ class Probes {
|
|||||||
static JSBool CustomMark(int marker);
|
static JSBool CustomMark(int marker);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void
|
inline bool
|
||||||
Probes::enterJSFun(JSContext *cx, JSFunction *fun, js::Value *lval)
|
Probes::callTrackingActive(JSContext *cx)
|
||||||
{
|
{
|
||||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||||
if (!lval || IsFunctionObject(*lval)) {
|
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED() || JAVASCRIPT_FUNCTION_RETURN_ENABLED())
|
||||||
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
|
return true;
|
||||||
enterJSFunImpl(cx, fun);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_TRACE_JSCALLS
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
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
|
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||||
if (!lval || IsFunctionObject(*lval)) {
|
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
|
||||||
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
|
handleFunctionReturn(cx, fun, script);
|
||||||
handleFunctionReturn(cx, fun);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_TRACE_JSCALLS
|
#ifdef MOZ_TRACE_JSCALLS
|
||||||
cx->doFunctionCallback(fun, fun ? FUN_SCRIPT(fun) : NULL, false);
|
if (counter > 0)
|
||||||
|
counter = -counter;
|
||||||
|
cx->doFunctionCallback(fun, script, counter);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,11 +184,11 @@ Probes::startExecution(JSContext *cx, JSScript *script)
|
|||||||
{
|
{
|
||||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||||
if (JAVASCRIPT_EXECUTE_START_ENABLED())
|
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);
|
script->lineno);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_TRACE_JSCALLS
|
#ifdef MOZ_TRACE_JSCALLS
|
||||||
cx->doFunctionCallback(NULL, script, true);
|
cx->doFunctionCallback(NULL, script, 1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,11 +197,11 @@ Probes::stopExecution(JSContext *cx, JSScript *script)
|
|||||||
{
|
{
|
||||||
#ifdef INCLUDE_MOZILLA_DTRACE
|
#ifdef INCLUDE_MOZILLA_DTRACE
|
||||||
if (JAVASCRIPT_EXECUTE_DONE_ENABLED())
|
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);
|
script->lineno);
|
||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_TRACE_JSCALLS
|
#ifdef MOZ_TRACE_JSCALLS
|
||||||
cx->doFunctionCallback(NULL, script, false);
|
cx->doFunctionCallback(NULL, script, 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,19 +233,19 @@ inline JSBool Probes::CustomMark(int marker) { return JS_TRUE; }
|
|||||||
struct AutoFunctionCallProbe {
|
struct AutoFunctionCallProbe {
|
||||||
JSContext * const cx;
|
JSContext * const cx;
|
||||||
JSFunction *fun;
|
JSFunction *fun;
|
||||||
js::Value *lval;
|
JSScript *script;
|
||||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
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)
|
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
: cx(cx), fun(fun), lval(lval)
|
: cx(cx), fun(fun), script(script)
|
||||||
{
|
{
|
||||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
Probes::enterJSFun(cx, fun, lval);
|
Probes::enterJSFun(cx, fun, script);
|
||||||
}
|
}
|
||||||
|
|
||||||
~AutoFunctionCallProbe() {
|
~AutoFunctionCallProbe() {
|
||||||
Probes::exitJSFun(cx, fun, lval);
|
Probes::exitJSFun(cx, fun, script);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10236,22 +10236,20 @@ TraceRecorder::record_JSOP_LEAVEWITH()
|
|||||||
return ARECORD_STOP;
|
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
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_DEFINE_CALLINFO_3(static, BOOL, functionProbe, CONTEXT, FUNCTION, BOOL,
|
JS_DEFINE_CALLINFO_3(static, BOOL, functionProbe, CONTEXT, FUNCTION, INT32, 0, ACCSET_ALL)
|
||||||
0, ACCSET_STORE_ANY)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||||
TraceRecorder::record_JSOP_RETURN()
|
TraceRecorder::record_JSOP_RETURN()
|
||||||
@ -10264,13 +10262,11 @@ TraceRecorder::record_JSOP_RETURN()
|
|||||||
|
|
||||||
putActivationObjects();
|
putActivationObjects();
|
||||||
|
|
||||||
#ifdef MOZ_TRACE_JSCALLS
|
if (Probes::callTrackingActive(cx)) {
|
||||||
if (cx->functionCallback) {
|
|
||||||
LIns* args[] = { w.immi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
|
LIns* args[] = { w.immi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
|
||||||
LIns* call_ins = w.call(&functionProbe_ci, args);
|
LIns* call_ins = w.call(&functionProbe_ci, args);
|
||||||
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we inlined this function call, make the return value available to the caller code. */
|
/* If we inlined this function call, make the return value available to the caller code. */
|
||||||
Value& rval = stackval(-1);
|
Value& rval = stackval(-1);
|
||||||
@ -11389,8 +11385,7 @@ TraceRecorder::functionCall(uintN argc, JSOp mode)
|
|||||||
*/
|
*/
|
||||||
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &fval.toObject());
|
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, &fval.toObject());
|
||||||
|
|
||||||
#ifdef MOZ_TRACE_JSCALLS
|
if (Probes::callTrackingActive(cx)) {
|
||||||
if (cx->functionCallback) {
|
|
||||||
JSScript *script = FUN_SCRIPT(fun);
|
JSScript *script = FUN_SCRIPT(fun);
|
||||||
if (! script || ! script->isEmpty()) {
|
if (! script || ! script->isEmpty()) {
|
||||||
LIns* args[] = { w.immi(1), w.nameImmpNonGC(fun), cx_ins };
|
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);
|
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (FUN_INTERPRETED(fun))
|
if (FUN_INTERPRETED(fun))
|
||||||
return interpretedFunctionCall(fval, fun, argc, mode == JSOP_NEW);
|
return interpretedFunctionCall(fval, fun, argc, mode == JSOP_NEW);
|
||||||
@ -11420,13 +11414,11 @@ TraceRecorder::functionCall(uintN argc, JSOp mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RecordingStatus rs = callNative(argc, mode);
|
RecordingStatus rs = callNative(argc, mode);
|
||||||
#ifdef MOZ_TRACE_JSCALLS
|
if (Probes::callTrackingActive(cx)) {
|
||||||
if (cx->functionCallback) {
|
|
||||||
LIns* args[] = { w.immi(0), w.nameImmpNonGC(fun), cx_ins };
|
LIns* args[] = { w.immi(0), w.nameImmpNonGC(fun), cx_ins };
|
||||||
LIns* call_ins = w.call(&functionProbe_ci, args);
|
LIns* call_ins = w.call(&functionProbe_ci, args);
|
||||||
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return rs;
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15514,13 +15506,11 @@ TraceRecorder::record_JSOP_STOP()
|
|||||||
|
|
||||||
putActivationObjects();
|
putActivationObjects();
|
||||||
|
|
||||||
#ifdef MOZ_TRACE_JSCALLS
|
if (Probes::callTrackingActive(cx)) {
|
||||||
if (cx->functionCallback) {
|
|
||||||
LIns* args[] = { w.immi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
|
LIns* args[] = { w.immi(0), w.nameImmpNonGC(cx->fp()->fun()), cx_ins };
|
||||||
LIns* call_ins = w.call(&functionProbe_ci, args);
|
LIns* call_ins = w.call(&functionProbe_ci, args);
|
||||||
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
guard(false, w.eqi0(call_ins), MISMATCH_EXIT);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We know falling off the end of a constructor returns the new object that
|
* We know falling off the end of a constructor returns the new object that
|
||||||
|
@ -361,7 +361,7 @@ mjit::Compiler::generatePrologue()
|
|||||||
if (isConstructing)
|
if (isConstructing)
|
||||||
constructThis();
|
constructThis();
|
||||||
|
|
||||||
if (debugMode)
|
if (debugMode || Probes::callTrackingActive(cx))
|
||||||
stubCall(stubs::EnterScript);
|
stubCall(stubs::EnterScript);
|
||||||
|
|
||||||
return Compile_Okay;
|
return Compile_Okay;
|
||||||
@ -2199,7 +2199,7 @@ mjit::Compiler::emitReturn(FrameEntry *fe)
|
|||||||
/* Only the top of the stack can be returned. */
|
/* Only the top of the stack can be returned. */
|
||||||
JS_ASSERT_IF(fe, fe == frame.peek(-1));
|
JS_ASSERT_IF(fe, fe == frame.peek(-1));
|
||||||
|
|
||||||
if (debugMode) {
|
if (debugMode || Probes::callTrackingActive(cx)) {
|
||||||
prepareStubCall(Uses(0));
|
prepareStubCall(Uses(0));
|
||||||
stubCall(stubs::LeaveScript);
|
stubCall(stubs::LeaveScript);
|
||||||
}
|
}
|
||||||
|
@ -608,12 +608,15 @@ stubs::EnterScript(VMFrame &f)
|
|||||||
{
|
{
|
||||||
JSStackFrame *fp = f.fp();
|
JSStackFrame *fp = f.fp();
|
||||||
JSContext *cx = f.cx;
|
JSContext *cx = f.cx;
|
||||||
JSInterpreterHook hook = cx->debugHooks->callHook;
|
|
||||||
if (JS_UNLIKELY(hook != NULL) && !fp->isExecuteFrame()) {
|
if (fp->script()->debugMode) {
|
||||||
fp->setHookData(hook(cx, fp, JS_TRUE, 0, cx->debugHooks->callHookData));
|
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
|
void JS_FASTCALL
|
||||||
@ -621,14 +624,17 @@ stubs::LeaveScript(VMFrame &f)
|
|||||||
{
|
{
|
||||||
JSStackFrame *fp = f.fp();
|
JSStackFrame *fp = f.fp();
|
||||||
JSContext *cx = f.cx;
|
JSContext *cx = f.cx;
|
||||||
Probes::exitJSFun(cx, fp->maybeFun());
|
Probes::exitJSFun(cx, fp->maybeFun(), fp->maybeScript());
|
||||||
JSInterpreterHook hook = cx->debugHooks->callHook;
|
|
||||||
|
|
||||||
if (hook && fp->hasHookData() && !fp->isExecuteFrame()) {
|
if (fp->script()->debugMode) {
|
||||||
JSBool ok = JS_TRUE;
|
JSInterpreterHook hook = cx->debugHooks->callHook;
|
||||||
hook(cx, fp, JS_FALSE, &ok, fp->hookData());
|
|
||||||
if (!ok)
|
if (hook && fp->hasHookData() && !fp->isExecuteFrame()) {
|
||||||
THROW();
|
JSBool ok = JS_TRUE;
|
||||||
|
hook(cx, fp, JS_FALSE, &ok, fp->hookData());
|
||||||
|
if (!ok)
|
||||||
|
THROW();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user