Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature suggestion] reverse-run and reverse-run-to #59

Open
sdsnatcher opened this issue Jun 5, 2017 · 3 comments
Open

[feature suggestion] reverse-run and reverse-run-to #59

sdsnatcher opened this issue Jun 5, 2017 · 3 comments

Comments

@sdsnatcher
Copy link

Currently, it's nice to have the step-back feature. But the debugger only allows you to step one instruction at a tine, and this can be very time consuming, specially if the machine has gone haywire and trashed the memory.

It would be nice to have a reverse-run feature. The machine would run the code backwards until a breakpoint/watchpoint/condition is triggered. The same goes for reverse-run-to: the machine would run many instructions until the specified address.

@bengalack
Copy link

step-back - I use it all the time. reverse-run-to would be VERY much appreciated. Numerous times have I had the need for this.

I have a bunch of asserts in my program, and when this occurs... backtracking is needed.

I vote for this!

@m9710797
Copy link
Contributor

I fully agree this would be a useful feature. The main reason why we didn't add it yet is because it's difficult to implement (in an efficient way).

More in detail:
OpenMSX can relatively efficiently go back to any point in the past. Under the hood this is implemented as take the most recent snapshot that is older than the requested moment in time. And from that emulate forwards till the requested moment in time (with granularity of one CPU instruction, so it could be a fraction of an instruction past the requested time). With "relatively efficient" I mean it usually completes in less than a second. Depending on how close to the last snapshot is to the destination. For the recent past we keep a snapshot every second (further in the past, we prune those snapshots). Though emulating forwards is only part of the cost. Often the dominating cost is restoring the last snapshot.

Stepping back a single instruction is already more complex because we don't know what the duration of that last instruction was. What the step-back function does is: take a large step backwards (using the above mechanism). This step has the length of the longest possible instruction. From there emulate single instructions forward, and remember the start time of these instructions. Repeat until we're back at the current instruction. We now know the time of the last instruction, and then we can again go back in time to that specific time (again using the above mechanism). With this implementation we have to go backwards in time two times, so it's about twice as expensive as the previous stuff (the emulate single-instructions forwards part is negligible). Usually a step-back operation completes in about a second (or less).

Implementing the requested features (run-backwards till a specific PC, or till a breakpoint/watchpoint triggers) adds another layer of complexity. We don't know how far back in time we'll have to go, and in this case we can't even make a (reasonable) upper-bound estimation. A naive implementation could call step-back in a loop until the desired condition is hit. But that would be unacceptably slow: order of magnitude one second per instruction. For any non-trivial distance this would seem like openMSX and/or the debugger hangs. I'm sure there are smarter ways to implement this: e.g. start from the last snapshot, emulate single-instructions forward until we're back in the present, while doing this remember the most recent moment in time what the stop-condition hit. And then go backwards again to that specific moment. If the condition never hit, retry from an earlier snapshot. This might work, but it still won't be very fast: emulating single instructions at a time is fine for a few hundred instructions. But if it are thousands instructions or more (like there may be since the last snapshot), this can also take a considerable amount of time (I mean much more than emulating these same instructions as a block).

I only just now thought of the "solution" in the previous paragraph. This will still be very slow (too slow?), but maybe not unacceptably slow? Another complication is the detect-the-stop-condition part. It's certainly technically possible to implement that, but it probably needs various extensions in the current code.

So to summarize:
I agree it would be a useful feature. Unfortunately it's not something easy to implement. And because of that it's not very high on my priority list. Also because there are manual workarounds possible (manually go back e.g. a second, and emulate forwards till the "stop-condition" is reached, more or less manually perform the above algorithm).
But is someone else is willing to try to implement this feature, then I can certainly help.

@bengalack
Copy link

Ok, thank you for elaborating on the matter. I was afraid things wouldn't be as easy to do, as it could seem. Maybe this issue can be revisited in the future in the case there are changes to the architecture that makes this more feasible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants