In the block closure version, which uses stack frames for method contexts, I doubt the tailSend: bytecode would be any faster because, although your saving a return, you have to copy the receiver and args down. The regular send: just leaves the receiver and args where they are and starts the new context right from there.
The biggest drawback of tailSend:, I think, is losing the calling context when looking in the debugger. It would just add to the confusion when trying to figure out a bug.
The only benefit would be to save stack space. But (unless your in an infinite loop) it is rare that the stack uses too much space, usually it other data structures taking up too much space. And if your stack is taking up most of the space, usually you can rewrite your algorithm to use iteration instead of recursion without loosing much clarity.
But I guess there are some algorithms where the tail recursive version is nicer. So I would vote for adding the tailSend: bytecode but requiring another language construct that invokes it, so you are aware of it (in the debugger). I would not automatically convert all "send: + returnTop" to "tailSend:"
Cheers, Anthony
On Fri, 1 Feb 2002, Anthony Hannan wrote:
In the block closure version, which uses stack frames for method contexts, I doubt the tailSend: bytecode would be any faster
It might be marginally faster through caching issues from using less stack space. (Probably marginal, but it should be benchmarked.)
The biggest drawback of tailSend:, I think, is losing the calling context when looking in the debugger. It would just add to the confusion when trying to figure out a bug.
Agreed.
But I guess there are some algorithms where the tail recursive version is nicer. So I would vote for adding the tailSend: bytecode but requiring another language construct that invokes it, so you are aware of it (in the debugger). I would not automatically convert all "send: + returnTop" to "tailSend:"
I want it to make it easier to write those algorithms. We've got closures, with closures and tailcall come useful uses of continuations.
Debuggability is one of squeak's strengths. Wholesale replacement, other than as an experimental test/benchmark, would be a bad idea.
BTW, what about tailcall out of a block?
foo: ^[^self bar]
Is that a different bytecode?
And thanks...
Scott
squeak-dev@lists.squeakfoundation.org