This diff updates the debugger to be able to debug async functions again, after the most excellent optimizations introduced in D946914. Minor updates to be able to identify an async func outside of the emitter, and minor adjustments to get breakpoints on async function names working again. Async stacks were fine, the test just needed to be updated. Stepping over await/yield used to decode the instruction stream around OpContSuspend to determine where execution would continue, but that was annoying and brittle. I recently gave c_Continuation the ability to predict its next execution offset, so I enhanced that a bit and switched to using that, so the debugger no longer cares about the codegen around OpContSuspend and doesn't care about anything around OpCreateAsync. This fixes stepping over suspends within a continuation. To get across the first await, we now notice a OpCreateAsync, step over that operation, then grab the c_Continuation off the top of the operand stack and ask it where the heck it's going.
Reviewed By: @hermanventer
Differential Revision: D965577
The debugger's API mode added a lot of extra complexity to the debugger client for minimal value. It also had a bunch of bugs, and unnecessarily tied alternate debugger clients to the command line client implementation. Deleting it.
Differential Revision: D912729
Request Start has no activation record on the stack, but Next is quite valid and should still work. Modified to tollerate the lack of act rec.
Differential Revision: D908499
A real breakpoint makes entries in the breakpoint filter for all offsets at the given line. Various flow control commands will also use the breakpoint filter to add and remove temporary "internal breakpoints" required during the flow operation. Ensure that we never remove a breakpoint filter entry if there was already one there due to a breakpoint (or really any other reason).
Updates continuations to allow yielding of a key-value
pair from a generator. Adds bytecode instructions (PackContK,
ContKey) for using the new feature, and adds IR instructions
(ContUpdateIdx, ContIncKey) to help get it down to the metal
(in particular, ContIncKey attempts to keep the current use-cases
as fast as possible).
PackCont opcode is always followed by ContExit so let's join them into ContSuspend. ContResume counterpart may come later (replacing ContNext/Send/Raise/Enter).
Because stronger types are better types, and this will make
future refactoring easier. I considered trying to purge the Opcode
type from the codebase too but that would be a much bigger project.
Small stepping, which is stepping over sub-expressions (kinda), worked but was a little goofy. The mode was set on the client, passed over with control flow commands, placed on the execution context, then retrieved from there and used by those same flow commands. Removed the execution context part of it, since it was useless, and factored grabbing the offsets into the flow cmds where they belong instead of doing it all the time.
The run cmd also had some notion of small stepping, but you'll note it was never sent over the wire. Nuked that, since it never mattered anyway.
Add reasonable behavior for stepping within continuations (generators). Stepping over a yield now does what one would expect. When the generator is driven from a C++ extension like ASIO, the next logical execution point is after the yield statement, and that's where we'll stop now. When driven from PHP, say in a loop calling send(), the next execution point is in fact the call site of send(), so we go there. Stepping off the end of the generator function, goes to the caller of send(), or the caller of the C++ extension. Stepping _out_ of a generator driven by a C++ extension ensures that we go to the caller and not back into the generator again. The logic for both cases is exactly the same. The difference comes from the fact that we don't actually debug C++ extensions.
This also fixes a long-standing problem where breakpoints would interfere with control flow cmds on the same source line. This caused funny behavior, like taking multiple steps to get off of a breakpoint.