b=403345; dtrace probes get wrong function name, filename, and line number info when native methods are involved; r=brendan

This commit is contained in:
Vladimir Vukicevic 2009-06-17 13:50:03 -07:00
Родитель 3dc9dd5693
Коммит 220c1376a3
3 изменённых файлов: 88 добавлений и 116 удалений

Просмотреть файл

@ -51,34 +51,41 @@
static char dempty[] = "<null>";
char *
jsdtrace_funcclass_name(JSFunction *fun)
static char *
jsdtrace_fun_classname(JSFunction *fun)
{
return (!FUN_INTERPRETED(fun) &&
return (fun &&
!FUN_INTERPRETED(fun) &&
!(fun->flags & JSFUN_TRACEABLE) &&
FUN_CLASP(fun))
? (char *)FUN_CLASP(fun)->name
: dempty;
}
char *
static char *
jsdtrace_filename(JSStackFrame *fp)
{
while (fp && fp->script == NULL)
fp = fp->down;
return (fp && fp->script && fp->script->filename)
? (char *)fp->script->filename
: dempty;
}
int
jsdtrace_linenumber(JSContext *cx, JSStackFrame *fp)
static int
jsdtrace_fun_linenumber(JSContext *cx, JSFunction *fun)
{
while (fp && fp->script == NULL)
fp = fp->down;
return (fp && fp->regs)
? (int) js_PCToLineNumber(cx, fp->script, fp->regs->pc)
: -1;
if (fun && FUN_INTERPRETED(fun))
return (int) JS_GetScriptBaseLineNumber(cx, FUN_SCRIPT(fun));
return 0;
}
int
jsdtrace_frame_linenumber(JSContext *cx, JSStackFrame *fp)
{
if (fp && fp->regs)
return (int) js_FramePCToLineNumber(cx, fp);
return 0;
}
/*
@ -101,7 +108,7 @@ jsdtrace_linenumber(JSContext *cx, JSStackFrame *fp)
* This is used by the function-args and function-rval probes, which also
* provide raw (unmasked) jsvals should type info be useful from D scripts.
*/
void *
static void *
jsdtrace_jsvaltovoid(JSContext *cx, jsval argval)
{
JSType type = TYPEOF(cx, argval);
@ -128,68 +135,23 @@ jsdtrace_jsvaltovoid(JSContext *cx, jsval argval)
/* NOTREACHED */
}
char *
jsdtrace_function_name(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
static char *
jsdtrace_fun_name(JSContext *cx, JSFunction *fun)
{
JSAtom *atom;
JSFrameRegs *regs;
JSScript *script;
jsbytecode *pc;
char *name;
if (!fun)
return dempty;
atom = fun->atom;
if (!atom) {
if (fp->fun != fun || !fp->down)
return dempty;
regs = fp->down->regs;
if (!regs)
return dempty;
/*
* An anonymous function called from an active script or interpreted
* function: try to fetch the variable or property name by which the
* anonymous function was invoked.
* TODO: maybe do more work here to figure out the name of the property
* or variable that held the anonymous function that we're calling, if anyone
* cares; an easy workaround is to just give your anonymous functions names.
*/
pc = regs->pc;
script = fp->down->script;
switch ((JSOp) *pc) {
case JSOP_CALL:
case JSOP_EVAL:
JS_ASSERT(fp->argv == regs->sp - (int)GET_ARGC(pc));
/*
* FIXME bug 422864: update this code to use the pc stack from the
* decompiler.
*/
break;
default: ;
}
switch ((JSOp) *pc) {
case JSOP_CALLNAME:
case JSOP_CALLPROP:
case JSOP_NAME:
case JSOP_SETNAME:
case JSOP_GETPROP:
case JSOP_SETPROP:
GET_ATOM_FROM_BYTECODE(script, pc, 0, atom);
break;
case JSOP_CALLELEM:
case JSOP_GETELEM:
case JSOP_SETELEM:
case JSOP_CALLGVAR:
case JSOP_GETGVAR:
case JSOP_SETGVAR:
case JSOP_CALLARG:
case JSOP_CALLLOCAL:
/* FIXME: try to recover a name from these ops. */
/* FALL THROUGH */
default:
return dempty;
}
return dempty;
}
name = (char *)js_GetStringBytes(cx, ATOM_TO_STRING(atom));
@ -208,8 +170,8 @@ jsdtrace_function_entry(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
{
JAVASCRIPT_FUNCTION_ENTRY(
jsdtrace_filename(fp),
jsdtrace_funcclass_name(fun),
jsdtrace_function_name(cx, fp, fun)
jsdtrace_fun_classname(fun),
jsdtrace_fun_name(cx, fun)
);
}
@ -219,39 +181,40 @@ jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
{
JAVASCRIPT_FUNCTION_INFO(
jsdtrace_filename(fp),
jsdtrace_funcclass_name(fun),
jsdtrace_function_name(cx, fp, fun),
fp->script->lineno,
jsdtrace_fun_classname(fun),
jsdtrace_fun_name(cx, fun),
jsdtrace_fun_linenumber(cx, fun),
jsdtrace_filename(dfp),
jsdtrace_linenumber(cx, dfp)
jsdtrace_frame_linenumber(cx, dfp)
);
}
void
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsuint argc, jsval *argv)
{
JAVASCRIPT_FUNCTION_ARGS(
jsdtrace_filename(fp),
jsdtrace_funcclass_name(fun),
jsdtrace_function_name(cx, fp, fun),
fp->argc, (void *)fp->argv,
(fp->argc > 0) ? jsdtrace_jsvaltovoid(cx, fp->argv[0]) : 0,
(fp->argc > 1) ? jsdtrace_jsvaltovoid(cx, fp->argv[1]) : 0,
(fp->argc > 2) ? jsdtrace_jsvaltovoid(cx, fp->argv[2]) : 0,
(fp->argc > 3) ? jsdtrace_jsvaltovoid(cx, fp->argv[3]) : 0,
(fp->argc > 4) ? jsdtrace_jsvaltovoid(cx, fp->argv[4]) : 0
jsdtrace_fun_classname(fun),
jsdtrace_fun_name(cx, fun),
argc, (void *)argv,
(argc > 0) ? jsdtrace_jsvaltovoid(cx, argv[0]) : 0,
(argc > 1) ? jsdtrace_jsvaltovoid(cx, argv[1]) : 0,
(argc > 2) ? jsdtrace_jsvaltovoid(cx, argv[2]) : 0,
(argc > 3) ? jsdtrace_jsvaltovoid(cx, argv[3]) : 0,
(argc > 4) ? jsdtrace_jsvaltovoid(cx, argv[4]) : 0
);
}
void
jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsval *rval)
{
JAVASCRIPT_FUNCTION_RVAL(
jsdtrace_filename(fp),
jsdtrace_funcclass_name(fun),
jsdtrace_function_name(cx, fp, fun),
jsdtrace_linenumber(cx, fp), (void *)fp->rval,
jsdtrace_jsvaltovoid(cx, fp->rval)
jsdtrace_fun_classname(fun),
jsdtrace_fun_name(cx, fun),
jsdtrace_fun_linenumber(cx, fun),
(void *)rval,
jsdtrace_jsvaltovoid(cx, *rval)
);
}
@ -260,8 +223,8 @@ jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
{
JAVASCRIPT_FUNCTION_RETURN(
jsdtrace_filename(fp),
jsdtrace_funcclass_name(fun),
jsdtrace_function_name(cx, fp, fun)
jsdtrace_fun_classname(fun),
jsdtrace_fun_name(cx, fun)
);
}
@ -284,7 +247,7 @@ jsdtrace_object_create(JSContext *cx, JSClass *clasp, JSObject *obj)
jsdtrace_filename(cx->fp),
(char *)clasp->name,
(uintptr_t)obj,
jsdtrace_linenumber(cx, cx->fp)
jsdtrace_frame_linenumber(cx, cx->fp)
);
}

Просмотреть файл

@ -50,10 +50,10 @@ jsdtrace_function_info(JSContext *cx, JSStackFrame *fp, JSStackFrame *dfp,
JSFunction *fun);
extern void
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
jsdtrace_function_args(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsuint argc, jsval *argv);
extern void
jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun);
jsdtrace_function_rval(JSContext *cx, JSStackFrame *fp, JSFunction *fun, jsval *rval);
extern void
jsdtrace_function_return(JSContext *cx, JSStackFrame *fp, JSFunction *fun);

Просмотреть файл

@ -1367,6 +1367,16 @@ have_fun:
if (hook)
hookData = hook(cx, &frame, JS_TRUE, 0, cx->debugHooks->callHookData);
#ifdef INCLUDE_MOZILLA_DTRACE
/* DTrace function entry, non-inlines */
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
jsdtrace_function_entry(cx, &frame, fun);
if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
jsdtrace_function_info(cx, &frame, frame.down, fun);
if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
jsdtrace_function_args(cx, &frame, fun, frame.argc, frame.argv);
#endif
/* Call the function, either a native method or an interpreted script. */
if (native) {
#ifdef DEBUG_NOT_THROWING
@ -1388,6 +1398,14 @@ have_fun:
ok = js_Interpret(cx);
}
#ifdef INCLUDE_MOZILLA_DTRACE
/* DTrace function return, non-inlines */
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
jsdtrace_function_rval(cx, &frame, fun, &frame.rval);
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
jsdtrace_function_return(cx, &frame, fun);
#endif
out:
if (hookData) {
hook = cx->debugHooks->callHook;
@ -3264,7 +3282,7 @@ js_Interpret(JSContext *cx)
#ifdef INCLUDE_MOZILLA_DTRACE
/* DTrace function return, inlines */
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
jsdtrace_function_rval(cx, fp, fp->fun);
jsdtrace_function_rval(cx, fp, fp->fun, &fp->rval);
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
jsdtrace_function_return(cx, fp, fp->fun);
#endif
@ -5143,7 +5161,7 @@ js_Interpret(JSContext *cx)
if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
jsdtrace_function_info(cx, fp, fp->down, fun);
if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
jsdtrace_function_args(cx, fp, fun);
jsdtrace_function_args(cx, fp, fun, fp->argc, fp->argv);
#endif
/* Load first op and dispatch it (safe since JSOP_STOP). */
@ -5158,19 +5176,19 @@ js_Interpret(JSContext *cx)
goto error;
}
if (fun->flags & JSFUN_FAST_NATIVE) {
#ifdef INCLUDE_MOZILLA_DTRACE
/* DTrace function entry, non-inlines */
if (VALUE_IS_FUNCTION(cx, lval)) {
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
jsdtrace_function_entry(cx, fp, fun);
if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
jsdtrace_function_info(cx, fp, fp, fun);
if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
jsdtrace_function_args(cx, fp, fun);
}
/* DTrace function entry, non-inlines */
if (VALUE_IS_FUNCTION(cx, lval)) {
if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
jsdtrace_function_entry(cx, NULL, fun);
if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
jsdtrace_function_info(cx, NULL, fp, fun);
if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
jsdtrace_function_args(cx, fp, fun, argc, vp+2);
}
#endif
if (fun->flags & JSFUN_FAST_NATIVE) {
JS_ASSERT(fun->u.n.extra == 0);
JS_ASSERT(JSVAL_IS_OBJECT(vp[1]) ||
PRIMITIVE_THIS_TEST(fun, vp[1]));
@ -5178,9 +5196,9 @@ js_Interpret(JSContext *cx)
#ifdef INCLUDE_MOZILLA_DTRACE
if (VALUE_IS_FUNCTION(cx, lval)) {
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
jsdtrace_function_rval(cx, fp, fun);
jsdtrace_function_rval(cx, NULL, fun, vp);
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
jsdtrace_function_return(cx, fp, fun);
jsdtrace_function_return(cx, NULL, fun);
}
#endif
regs.sp = vp + 1;
@ -5207,15 +5225,6 @@ js_Interpret(JSContext *cx)
}
ok = js_Invoke(cx, argc, vp, 0);
#ifdef INCLUDE_MOZILLA_DTRACE
/* DTrace function return, non-inlines */
if (VALUE_IS_FUNCTION(cx, lval)) {
if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
jsdtrace_function_rval(cx, fp, fun);
if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
jsdtrace_function_return(cx, fp, fun);
}
#endif
regs.sp = vp + 1;
CHECK_INTERRUPT_HANDLER();
if (!ok)