Platform/JSDebugv2: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
(Undo revision 219588 by Jimb (Talk))
Line 21: Line 21:
Since the interface is both is network-transparent and independent of the implementation's machine architecture, this means it can be used for debugging JavaScript running on (say) mobile devices, assuming an appropriate connection can be set up.
Since the interface is both is network-transparent and independent of the implementation's machine architecture, this means it can be used for debugging JavaScript running on (say) mobile devices, assuming an appropriate connection can be set up.


= Internal Debugging Model =
= Debugging Models =
 
The <tt>js::dbg2</tt> debugging interface operates at the JavaScript level,
not at the C++ or machine level. It assumes that the JavaScript
implementation itself is healthy and responsive; the JavaScript program
being executed may have gone wrong, but the implementation's internal state
is not corrupt. Bugs in the JavaScript implementation may cause the
debugger to fail; bugs in the JavaScript program must not.
 
Whenever a program's execution is paused, the C++ call stack looks like
this (younger frames appear above older frames):
 
{| border="1"
| debugger machinery frames
|-
| interpreter/JITted frames for debuggee
|}
 
In this case, the "debugger machinery" is responsible for reporting the
state of the JavaScript debuggee and interacting with the debugger's user
interface until the program is continued. When control continues, the
"debugger machinery" frame simply returns, and the "interpreter frames for
debuggee" resume execution. If the user decides to stop executing the
debuggee, the "debugger machinery" frame throws an appropriate, uncatchable
exception, allowing the interpreter to clean up its state in an orderly
way.
 
If the user asks the debugger to evaluate an expression that requires
evaluating JavaScript code (like <tt>e.x()</tt>), then the C++ stack looks
like this:
 
{| border="1"
| interpreter/JITted frames for expression given to debugger
|-
| debugger machinery frames
|-
| interpreter/JITted frames for debuggee
|}
 
If evaluation of the expression throws an exception or hits a breakpoint,
then the result is a matter of user interface. Either we abandon evaluation
of the expression, and C++ control returns to the original machinery frames:
 
{| border="1"
| debugger machinery frames
|-
| interpreter/JITted frames for debuggee
|}
 
Or we treat the event as something to be investigated, just as if it had
occurred in the debuggee's normal course of execution:
 
{| border="1"
| nested debugger machinery frames
|-
| interpreter/JITted frames for expression given to debugger
|-
| debugger machinery frames
|-
| interpreter/JITted frames for debuggee
|}
 
Again, the debugger machinery is <em>not</em> written to tolerate corrupt
interpreter data structures or incomplete execution states; it relies on
correct cooperation from the interpreter.
 
When the debuggee is running on a device with a limited user interface
(say, a mobile phone or tablet computer), it can be extremely valuable to
have the debugger's user interface running on a workstation or laptop. In
this case, the C++ call stack looks like this:
 
 
 
 
In all these scenarios it is essential that the debugger machinery be
properly insulated from the debuggee.
 
 
not
assume that the interpreted code's state is well-formed (global variables
may be monkey-patched or wiped out; control may be stuck in an infinite
loop; etc.),
 
= Usage Models =
 
 
 
There are several different ways that debugger and debuggee can

Revision as of 21:49, 29 April 2010

js::dbg2: JavaScript Debugging Interface, v2

We'd like to improve the Mozilla platform's debugging facilities, for a number of reasons:

  • Beyond debuggers, we want to encourage the creation of other sorts of monitoring and manipulation tools for web code; "watching programs run" is a broad charge. Think DTrace and SystemTap.
  • Our JavaScript implementation is changing rapidly; we need to do better than falling back to the bytecode interpreter whenever the debugger is enabled.
  • We need to be able to monitor and debug worker threads.
  • We need to be able to monitor and debug JavaScript running on embedded devices.
  • Now that SpiderMonkey is C++, an interface designed in that language can be more expressive and less error-prone than a C interface.

Long-term goals

  • The interface must operate at the source language level, and not expose details of the implementation technique: it should behave the same way regardless of whether the debuggee is being executed by a bytecode interpreter (SpiderMonkey classic), a just-in-time compiler (TraceMonkey), or a whole-method JIT (Jägermonkey). If the implementation compiles to native code, the debugging interface should be independent of the underlying processor architecture. The interface should be sufficiently high-level to allow debugging of (say) JITted code without requiring the implementation to pretend that is still a bytecode interpreter.
  • The interface must support cross-thread debugging: if the client uses the interfaces provided for this purpose, it should be able to debug JavaScript code running in another thread.
  • The interface must be cross-runtime: it should allow full inspection of JavaScript values, including objects, without creating direct inter-runtime object references or otherwise violating the rules for working with multiple runtimes.
  • The interface must be network-transparent: using the appropriate interfaces, a client should be able to inspect the state of a JavaScript program running on another machine.

Since the interface is both is network-transparent and independent of the implementation's machine architecture, this means it can be used for debugging JavaScript running on (say) mobile devices, assuming an appropriate connection can be set up.

Debugging Models