failure implementing :next command in ghci

Simon Marlow marlowsd at
Tue Apr 21 04:28:09 EDT 2009

2009/4/20 Peter Hercek <phercek at>:
> Simon Marlow wrote:
>> Peter Hercek wrote:
>>> The proposed meaning for :next
>>> Lets mark dynamic stack size at a breakpoint (at which we issue :next) as
>>> breakStackSize and its selected expression as breakSpan. Then :next would
>>> single step till any of these is true:
>>> 1) current dynamic stack size is smaller than breakStackSize
>>> 2) current dynamic stack size is equal to breakStackSize and the current
>>> selected expression is not a subset of breakSpan
>> So what happens if the stack shrinks and then grows again between two
>> breakpoints?  Presumably :next wouldn't notice.
> Yes, if there is no breakpoint in between I would not notice. I did not
> expect this can happen though. I thought that to add a frame on the stack
> this must be done within an expression (which is going to be forced) and the
> expression should be a breakpoint location. If it is so negligible that it
> does not have a breakpoint location associated then even the things it is
> calling should be negligible.
> Where is an error in this?

You can't assume that there are breakpoints everywhere.  Compiled code
doesn't have breakpoints, for example.  Even in interpreted code,
there is compiler-generated code that doesn't have breakpoints in it,
and after transformations breakpoints may have moved around.

>> I think you'd be better off implementing this with a special stack frame,
>> so that you can guarantee to notice when the current "context" has been
>> exited.
> This would be robust but I do not have knowledge to do it yet. If I
> understand you correctly this means that before executing a BCO which we are
> going to break at, we must prepare for a possible :next. So regardless
> whether :next is going to be issued by the user or not we would add a frame
> which represents a return to a function which:
> a) if user issued :next it enables all breakpoints so that we stop at the
> next breakpoint
> b) if user did not issue a break it would not do anything (just return)

Yes, exactly.  Although we have to worry about stack growth: we don't
want the addition of a new stack frame to change constant stack-usage
into linear stack-usage, so perhaps we would have to avoid pushing
these frames directly on top of each other.

> We could decide not to insert the frame when we are only tracing. But if I
> would want to track a simulated dynamic stack I would need to insert this
> stack frame at the start of each breakpoint (when dynamic stack tracing
> would be on). Does not sound that good.
>>> I hope the above would make good sense but I do not really know since
>>> maybe rts does some funny things with stack sometimes. If you think the
>>> proposed behavior is garbage let me know why so that I do not waste more
>>> time with this :)
>> Yes the RTS does do "funny thing" with the stack sometimes.  The stack can
>> shrink as a result of adjacent update frames being coalesced ("stack
>> squeezing").
> OK, so it looks like either switching off the squeezing (if shrinking and
> growing stack between breakpoints/ticks is not such an issue), or inserting
> a stack frame.
> Does the "stack squeezing" happen during garbage collection?

It can happen any time, so yes.


More information about the Glasgow-haskell-users mailing list