Simon Marlow wrote:
Peter Hercek wrote:
Sure, but the plan to maintain an approximate debugging dynamic stack
depends on one thing:
The number of items (continuations) on the return stack from the
beginning of /case tick<n> of {_->e}/ to the moment when we can check
the count of items in the return stack inside /tick<n>/ is constant
and known for a given runtime version of ghc. Or variable but known
for each call individually. This is important to find out the number
of return addresses on the return stack just before the execution of
/case tick<n> of {_->e}/.
I don't fully understand what it is you mean. e.g. I don't know what
"from the beginning of /case tick<n> of {_->e}/" means.
Let me try to explain a couple of things that might (or might not!) help
clarify. We don't normally see
case tick<n> of { _ -> e }
because the byte-code generator turns this into
let
z = case tick<n> of { _ -> e }
in
z
the debugger paper explains why we do this. Anyway, the byte code for
the closure for z does this:
- if the breakpoint at <n> is enabled then stop,
- otherwise, evaluate e
i.e. it doesn't push any stack frames.
Does that help frame your question?
I reread the paper and together with this it actually answered my question.
I thought that tick<n> represents a call to the debugger. But it is only
a byte code which is checked by interpreter and if the debugging
location is enabled then the interpreter breaks.
Also I have found out that what I originally intended would not work
because the interpreter can beak only at the beginning of a BCO. But
maybe there are other almost as good solutions. I'm aiming at these
features:
* :next command with the meaning: Break at the next source span which
has the same or smaller number of addresses on the return stack and
which is not a subset of the current source span.
* :stepout command with the meaning: Break at the next source span which
has smaller number of addresses on the return stack.
* build dynamic stack (more or less entirely in GHCi so if it is not
used it should not slow down GHC code interpretation; well doing it in
GHCi would mean it would be painfully slow because of thread switches
but if it proves useful it can be moved to GHC)
* ... and maybe also something like the last one (or the last few)
frames of lexical stack for the current source span; this one may not be
even that interesting if options to filter trace log are fine enough;
the problem with trace log is anything which is executed in a loop (so
e.g. even some stupid lambda in a map cal)
I'm not aiming at full lexical stack. This is not a promise I'll
implement the above things. I would like just some more information:
* what would be a good way (if any) to implement a new kind of break
point: Break at any tick (source span) if number of addresses on the
return stack is less than given number. Actually the ability to count
number of return addresses (although useful) is not that important. It
is important to find out whether the current return stack has more,
less, or the same number of return adresses than it had in a given
moment in past. Any good paper / web page where I could find how the
return stack is actually implemented?
* any good paper / web page where I can find how GHC profiler derives
lexical call stack approximation?
Thanks,
Peter.
_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users