Thanks,
-- O.L.
What would you want to trace, exactly? Can you give a small script
and an example of the sort of output you'd want?
Mike
I'd just like to have a printout (properly indented) of every JS
function executed as a result of a user input, e.g., a click on the
page. With things like addEventListener adding functions to a page in
such a way that you can't retrieve them after the fact (no corresponding
getEventListener), scripts rewriting or augmenting the DOM at load time
etc it's really hard to figure out what really happens.
I cannot give "a small script": if this were my own code I wouldn't
need to trace it. I want to gain some insight into third-party web
sites with complicated JS on them.
-- O.L.
Well, you don't need to give a real world example to demonstrate what
you want done. Imagine writing a test case for the feature, to make
sure it did what you want.
Would this be a small script that is a good example?
function f() { }
function g() { f(); }
document.addEventListener("click", function () { f(); g(); });
anonymous
-> f
-> g
----> f
?
Mike
Unless it has been removed since FF4, this already exists as a compile-time option, MOZ_TRACE_JSCALLS, which allows an embedding to register a per-context "function callback". The callback is invoked whenever a function is entered or exited. My embedding uses this to implement call trace and profiling functionality.
I presume it's a compile-time option because of the necessary overhead, at least when interpreting, although when compiling the cost shouldn't have to be more than an easily-predicted if when the facility isn't being used.
--
Jens Ayton
Yes, that is what I meant, with full path info for named functions
and the actual definition for anonymous ones.
-- O.L.
I thought it might already exist, indeed. Is this what the tracing
flag of the Mozilla Javascript shell is about? See here:
https://developer.mozilla.org/en/introduction_to_the_javascript_shell
-- O.L.
It's still there. Put
ac_add_options --enable-trace-jscalls
in your mozconfig, then see
https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_SetFunctionCallback
You're correct about the reasoning for the compile-time option. It was
judged to be too much overhead for the interpreter. For the JITs, if it
is unused then it's only a quick check during compilation; the generated
JIT code doesn't change. If it *is* used, the JIT code is deoptimized a
fair amount. (But you'll still be JITted, unlike eg debug mode which
will disable the tracer entirely.)
Note that it doesn't have the magic interlocking that things like debug
mode have, so if you set a callback after something has already been
JITted, you won't immediately start seeing all calls. You'll see calls
from the interpreter, and calls for the subset of scripts that happen to
have been JITted, which will change over time (we sometimes throw out
and recompiled JIT code.) This is technically a bug, but given that it's
a compile-time option and most users will install a callback immediately
after context creation, it shouldn't matter too much.
In its current state, this is not all that useful for the Web or Firebug
Consoles, because of the compilation flag. I would guess that jsdbg2's
debug mode will be the way to implement that functionality in the
nearish future.
It's still there. Put
-- O.L.
In other tabs there are other "break on .." buttons that do different things.
Unfortunately something like a short setInterval() can really
interrupt you if what you want to do is catch a mouse click. Best way
to deal with that is anyone's guess.
> _______________________________________________
> dev-tech-js-engine mailing list
> dev-tech-...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-tech-js-engine
>
I've been following this thread with interest.
I've been developing a basic debugger for our application which embeds
Spidermonkey (I've just upgraded to Spidermonkey 1.8.5) and I've been
pondering if it would be possible to also create a profiler.
This looks like it fits the bill perfectly.
I just want to confirm my understanding of this. Can anyone confirm/
correct the following which is what I *think* is possible?
1. I can trace function entering/leaving by using
JS_SetFunctionCallback to register a hook but to do that I would have
to recompile Spidermonkey with MOZ_TRACE_JSCALLS defined.
2. If it is used performance will be hit but JIT is still active
3. If it is NOT used there there is no effect on performance (well
negligable anyway). The last thing I want to do is to slow down
scripts if the profiler is not being used.
4. This is not possible if the script is in debug mode (by calling
JS_SetRuntimeDebugMode and JS_SetDebugMode) as the tracer is disabled?
That's how I interpret the previous post. Is that correct?
If so is there any other way of doing it? If not, it doesn't matter.
I'm happy to have to run the 'profiler' separately from a 'debugger'.
I'm just curious.
Miles
Thanks but I find heavy use of the debugger mind-numbing. I would
much rather look at a nice printout of traces.
-- O.L.
Sorry, this mechanism is not accessible via JS. It cannot call out to JS
code because that would interfere with execution too much. (It would
force us to maintain consistent internal state, which would defeat the
purpose of the feature.) If you want something accessible from JS,
you'll currently need to use JSD, which will disable the tracing JIT and
have a small performance impact on the method JIT. (But getting a
callback for every function call is already going to have a fairly high
perf impact, even if your callback does very little.)
There is also the jsdbg2 API that just landed -
https://wiki.mozilla.org/Debugger
It will probably end up with similar characteristics as JSD, and I don't
think it's exposed quite yet. (See bug 679031.)
If by "function" you mean "Javascript function", then yes. It won't
track calls to native code. (Actually, what's currently there might get
a couple of them, but claim them to be the calling JS function. I can't
remember the current state.)
The easiest way to get MOZ_TRACE_JSCALLS defined is to configure with
--enable-trace-jscalls
> 2. If it is used performance will be hit but JIT is still active
Yes, though the implication that the JIT will be inactive using another
approach, namely JSD, is not entirely correct -- JSD disables the
tracing JIT, but only slightly slows down the method JIT.
> 3. If it is NOT used there there is no effect on performance (well
> negligable anyway). The last thing I want to do is to slow down
> scripts if the profiler is not being used.
I confess I haven't measured it, but I expected it to induce enough of a
slowdown that I hid it behind MOZ_TRACE_JSCALLS. If there were really no
impact, I would just have it available by default.
Still, I'd be surprised if it were more than a few percentage points.
> 4. This is not possible if the script is in debug mode (by calling
> JS_SetRuntimeDebugMode and JS_SetDebugMode) as the tracer is disabled?
> That's how I interpret the previous post. Is that correct?
> If so is there any other way of doing it? If not, it doesn't matter.
> I'm happy to have to run the 'profiler' separately from a 'debugger'.
> I'm just curious.
>
> Miles
>
If I am understanding correctly, then no, this is not correct. The
JS_SetFunctionCallback callback will still fire when in debug mode. Or
it's supposed to, at least. (There's been at least one bug in that.)
You are correct that the tracer will be disabled, but
JS_SetFunctionCallback hooks into the interpreter and both JITs separately.
I am working on a couple of other routes to get profiling for JS. One is
bug 642054, which is probably exactly what you want -- a profiler for
JS. But it's further out. I'm also exposing JIT information to various
external native profilers, so you can tell what JS function is executing
in their outputs -- oprofile, vtune, shark, callgrind, etc. Which isn't
quite what you want, since (1) it only gives the JS function name of the
youngest JS stack frame, not the whole JS stack, and (2) it ironically
gives better information for JITted code than interpreted code because
the interpreted code just shows up as JS_Execute or whatever.
But none of that's done yet. For now, I think you're going down the
right route.
Wrt. calling out to JS my wish was very modest: I just wanted a way to turn tracing on and off from JS.
-- O.L.
I assume you could write your tracing in C and then just expose an XPC
interface to JS to turn it on/off, right? If there are threading
concerns, you can mutex around setting that variable. Then the C side
when the variable changes you can register or unregister the callback.
d