Closed Bug 1465289 Opened 6 years ago Closed 6 years ago

Web Replay: Record/replay debugger

Categories

(Core Graveyard :: Web Replay, enhancement)

enhancement
Not set
normal

Tracking

(firefox62 wontfix, firefox63 fixed)

RESOLVED FIXED
mozilla63
Tracking Status
firefox62 --- wontfix
firefox63 --- fixed

People

(Reporter: bhackett1024, Assigned: bhackett1024)

References

Details

Attachments

(1 file, 3 obsolete files)

This bug includes patches for adding the replay debugger and associated logic.  Debuggers created in middleman processes by devtools server code have a replay debugger which they use for getting information about a recording/replaying child process and for controlling its execution.  Likewise, the child process is able to respond to queries from the replay debugger in the middleman, and is able to play forward or backward to the last point where a breakpoint was hit.
Most changes to the debugger itself are just forwarding property accesses / calls to methods in the replay debugger.  Other changes include refactoring handling of script related methods so they don't need an actual JSScript*, and adding a few new methods on the debugger which devtools server code will need when dealing with a replay debugger.
Assignee: nobody → bhackett1024
Attachment #8981711 - Flags: review?(jimb)
Attached patch Part 2 - Add replay debugger. (obsolete) — Splinter Review
The replay debugger fetches information from a recording/replaying process by sending JSON requests and getting JSON responses.  Within the recording/replaying process additional logic is needed so that the process can keep track of what it is doing as it scans forward or backward for breakpoint hits (which requires rewinding, often multiple times, and needs state that persists across these rewinds).
Attachment #8981712 - Flags: review?(jimb)
The replay debugger identifies points of execution within a recording as a pair of a progress count and a script location or other place where a breakpoint can be set.  The idea is that the debugger has a progress counter that advances at predictable points, mainly when entering a script or hitting a LOOPENTRY opcode, and needs to have the same value regardless of what JIT compilations have been performed.
Attachment #8981713 - Flags: review?(jdemooij)
What are the printfs for? If it's necessary it would be nice if we could abstract that somewhere with a comment explaining what's going on.
Flags: needinfo?(bhackett1024)
(In reply to Jan de Mooij [:jandem] from comment #4)
> What are the printfs for? If it's necessary it would be nice if we could
> abstract that somewhere with a comment explaining what's going on.

I used the printfs for debugging count variances between different compiler options, but it's probably better to remove them.
Flags: needinfo?(bhackett1024)
Comment on attachment 8981713 [details] [diff] [review]
Part 3 - Keep track of JS execution progress made when there is a replay debugger.

Review of attachment 8981713 [details] [diff] [review]:
-----------------------------------------------------------------

Sorry for the delay. The idea makes sense to me. You need something similar for Wasm baseline/Ion right?

::: js/src/jit/BaselineBailouts.cpp
@@ +1032,5 @@
>          }
>          op = JSOp(*pc);
> +        if (skippedLoopEntry && ReplayDebugger::trackProgress(script)) {
> +            if (const char* str = ReplayDebugger::progressString("SkippedLoopEntry", script, skippedLoopEntry))
> +                fprintf(stderr, "%s", str);

Please remove the printfs here and elsewhere.

@@ +1234,5 @@
>                  opReturnAddr = baselineScript->prologueEntryAddr();
>                  JitSpew(JitSpew_BaselineBailouts, "      Resuming into prologue.");
>  
> +                // The comment above is wrong and there are times when we end
> +                // up here even though the script has started executing. Undo

We should just fix the comment or the code.

::: js/src/jit/IonBuilder.cpp
@@ +1675,5 @@
>          if (!succ->addPredecessor(alloc(), current))
>              return abort(AbortReason::Alloc);
>      }
>  
> +    if (ins->brokenLoopEntry()) {

This needs a comment.

@@ +2503,5 @@
>      if (!graph().removeSuccessorBlocks(header))
>          return abort(AbortReason::Alloc);
>      graph().removeBlockFromList(header);
>  
> +    // Find the LOOPENTRY pc for this loop.

Hm I remember running into this JSOP_LOOPENTRY issue with the WIP patch for Ion optimization levels. I'll try to split that off and post a patch for that, so you don't need to do this here.

::: js/src/jit/shared/CodeGenerator-shared.cpp
@@ +128,5 @@
>  
> +    if (ReplayDebugger::trackProgress(gen->info().script())) {
> +        if (const char* str = ReplayDebugger::progressString("Prologue", gen->info().script()))
> +            masm.printf(str);
> +        masm.inc64(AbsoluteAddress(&ReplayDebugger::gProgressCounter));

We don't support workers (yet)? Wondering about races.

::: js/src/vm/Stack.cpp
@@ +223,5 @@
>              lexicalEnv = &cx->global()->lexicalEnvironment();
>              varObjRoot = cx->global();
>          }
> +        if (!CheckGlobalDeclarationConflicts(cx, script, lexicalEnv, varObjRoot)) {
> +            // Treat this as a script entry, for consistency with Ion.

After this we call probes::EnterScript. What about moving the EnterScript call before the CheckGlobalDeclarationConflicts call, would that fix this?
Attachment #8981713 - Flags: review?(jdemooij)
Depends on: 1467496
Thanks for the feedback, I'll update the patch based on the one in bug 1467496.

(In reply to Jan de Mooij [:jandem] from comment #6)
> Comment on attachment 8981713 [details] [diff] [review]
> Part 3 - Keep track of JS execution progress made when there is a replay
> debugger.
> 
> Review of attachment 8981713 [details] [diff] [review]:
> -----------------------------------------------------------------
> 
> Sorry for the delay. The idea makes sense to me. You need something similar
> for Wasm baseline/Ion right?

Eventually, yeah, but I don't think we support wasm yet (the signal handler it uses is disabled, though I don't know what repercussions that has in terms of what works or not).

> ::: js/src/jit/shared/CodeGenerator-shared.cpp
> @@ +128,5 @@
> >  
> > +    if (ReplayDebugger::trackProgress(gen->info().script())) {
> > +        if (const char* str = ReplayDebugger::progressString("Prologue", gen->info().script()))
> > +            masm.printf(str);
> > +        masm.inc64(AbsoluteAddress(&ReplayDebugger::gProgressCounter));
> 
> We don't support workers (yet)? Wondering about races.

We can record/replay tabs that use workers, but they can't be debugged yet.  ReplayDebugger::trackProcess returns true only for scripts associated with the main thread's runtime.
Comment on attachment 8981711 [details] [diff] [review]
Part 1 - Debugger changes for interfacing with replay debugger.

So, after working on web console integration (bug 1448607 part 40) I have some new thoughts about this.  I think that modifying the Debugger C++ object to add functionality for replaying is the wrong approach.  Instead, I'd like to make the replay debugger self hosted, to as great a degree as possible.

The middleman process can create a JS object which mimics the interface of the C++ Debugger, and performs queries by sending JSON requests to the recording/replaying process and receiving JSON responses.  In the recording/replaying process these JSON requests are handled by JS code which manages a Debugger to inspect the state of things.  The only changes to the Debugger should be additions to support this inspection.

Note that this strategy is basically the same as what we do now, except most things are happening in JS rather than C++.  This should make everything a lot tidier and the replay-specific changes separated from existing logic, and will be better for future work as we expand the interface between the middleman and recording/replaying processes (e.g. for web console integration).
Attachment #8981711 - Flags: review?(jimb)
Comment on attachment 8981712 [details] [diff] [review]
Part 2 - Add replay debugger.

Many parts of this patch need rewriting per the new approach outlined above.
Attachment #8981712 - Flags: review?(jimb)
Comment on attachment 8985707 [details] [diff] [review]
Part 3 - Keep track of JS execution progress made when there is a replay debugger.

Review of attachment 8985707 [details] [diff] [review]:
-----------------------------------------------------------------

Sorry for the delay. r=me with comment below addressed.

::: js/src/jit/MIR.h
@@ +8374,5 @@
>  // Check whether we need to fire the interrupt handler.
>  class MInterruptCheck : public MNullaryInstruction
>  {
> +    CompilerScript script_;
> +    jsbytecode* pc_;

At least the pc_ field isn't used anymore AFAICT. I think instead of script/pc all we need now is a |bool recordReplayTrackProgress_ = false;| or something with a method to set it to |true|.
Attachment #8985707 - Flags: review?(jdemooij) → review+
Comment on attachment 8981711 [details] [diff] [review]
Part 1 - Debugger changes for interfacing with replay debugger.

Bug 1470795 has the new version of the replay debugger.
Attachment #8981711 - Attachment is obsolete: true
Attachment #8981712 - Attachment is obsolete: true
Component: General → Web Replay
(In reply to Brian Hackett (:bhackett) from comment #9)
> Comment on attachment 8981711 [details] [diff] [review]
> Part 1 - Debugger changes for interfacing with replay debugger.
> 
> So, after working on web console integration (bug 1448607 part 40) I have
> some new thoughts about this.  I think that modifying the Debugger C++
> object to add functionality for replaying is the wrong approach.  Instead,
> I'd like to make the replay debugger self hosted, to as great a degree as
> possible.
> 
> The middleman process can create a JS object which mimics the interface of
> the C++ Debugger, and performs queries by sending JSON requests to the
> recording/replaying process and receiving JSON responses.  In the
> recording/replaying process these JSON requests are handled by JS code which
> manages a Debugger to inspect the state of things.  The only changes to the
> Debugger should be additions to support this inspection.
> 
> Note that this strategy is basically the same as what we do now, except most
> things are happening in JS rather than C++.  This should make everything a
> lot tidier and the replay-specific changes separated from existing logic,
> and will be better for future work as we expand the interface between the
> middleman and recording/replaying processes (e.g. for web console
> integration).

Yeah, I like the sound of this a lot.
Pushed by bhackett@mozilla.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/a3f53213595e
Part 3 - Keep track of JS execution progress made when there is a replay debugger, r=jandem.
https://hg.mozilla.org/mozilla-central/rev/a3f53213595e
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla63
Product: Core → Core Graveyard
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: