Last Thursday, Nicolas (nbp) and I met with Nick Fitzgerald (fitzgen), Panos
Astithas (past), and Jim Blandy (jimb) of the devtools team.
Nick's our biggest fan on this effort and he'll be eagerly looking into
whatever we build. The immediate targets will *not* be advanced dynamic
analyses. The devtools team is interested in working on these things first:
* Code coverage.
* Program tracing --- literally just recording a log to show what methods
were called and whatever else happened. printf debugging without the
printfs.
We presented the two different implementation approaches:
* strace-like (described below)
* source-to-source transformation
Of course fitzgen et al were interested in how the two systems might work in
practice. Here's an example of how the strace-like approach might look, for
the program tracing use case.
// (devtools would run this code while a window is being set up,
before any
// script runs in it)
var dbg = new Debugger(theNewWindow); // NOTE: does not inhibit
optimizations
dbg.addLogListener({ // also does not inhibit
optimizations
enterFunction: function (event) { ... },
leaveFunction: function (event) { ... }
});
The devtools code here is specifically asking for two kinds of events to be
logged: enterFunction and leaveFunction. (Because we're not asking for
breakpoints etc., this does not cause the Debugger object to turn on full
ion-inhibiting debug mode.)
Events are *not* delivered synchronously. As JS code executes, a log is
written. Occasionally, the log is then parsed and records are delivered to
devtools code via the enterFunction and leaveFunction methods above. (This
batching should improve performance, by minimizing C++-to-JS-to-C++ and
cross-compartment calls.)
One nice thing about the strace-like approach is that we can offer a few
events
at first and add others later, making cost/benefit decisions
individually for
each event users request.
The proposed implementation technique underlying this is bytecode
instrumentation. One reason for this is that we already have tons of
practice
adding new opcodes to Ion, baseline, and the interpreter. We already
know how
to make them work the same in all modes and fast in Ion. Of course the
implementation technique could vary per event. If we choose to support
an event
that already has a natural choke-point in C++, we would not need bytecode
instrumentation to intercept that event. It is also true that bytecode
instrumentation has a few weaknesses--things like exception handling are not
done by executing bytecodes at all.
In any case, the corresponding source-to-source transformation is a major
effort. It might start out like this:
// (devtools would run this code while a window is being set up,
before any
// script runs in it)
var dbg = new Debugger(theNewWindow); // NOTE: does not turn on
full debug mode
dbg.onBeforeCompileSource = function (args, source) {
var ast = Reflect.parse(source);
... transform ast ...
var sourceMap = ...;
var modifiedSource = reserialize(ast);
return modifiedSource + encode(sourceMap);
};
My conclusion from this meeting was that source-to-source transformation
does
not address any of Nick's immediate use cases in a realistic way. Nobody
wants
to maintain hundreds of lines of tricky JS code munging ASTs in order to get
code coverage information. Nobody wants to maintain that code as new JS
language features are introduced.
Other use cases are (I think) better addressed by S2S, but that's beyond the
scope of this email which is about the one meeting.
-j
_______________________________________________
dev-tech-js-engine-internals mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals