[otp] Duplicate Erlang's non-tail-call-with-no-stack-frame optimization #6

eriksoe opened this Issue Feb 21, 2010 · 5 comments

2 participants


The optimization in question makes certain non-tail recursions be rewritten so that they run in fixed stack space.
At present, io_lib:write_binary_body/2 sometimes dies because of Erjang lacking this feature.
Another example is lists:flatten applied to a sufficiently deeply nested list.


The rule seems to be as follows:
Several stack frames with the same return address appear as one entry in the stack traces.
This does not, of course, mean that any optimization is actually going on; just that get_stacktrace() doesn't report the raw trace.
However, the problem with Javastack overflows remains an issue.

Trifork member

Bugger, we need to figure out how to do this. lists:map needs it; and I don't understand how to do this at runtime.

{function, map, 2, 337}.

I still think the optimization is not really there (except that when the stack trace is generated, identical return addresses are conflated).
The real trick is heap allocation of stack frames - or, nearly equivalent, lazy stack unpacking by kilim.
You get stack overflow errors? Then now you know why I've been rambling about this lazy vs. eager difference :-)

Trifork member

Yep, exactly. I am seeing stack overflows. I agree that we need to encode this by allocating stack frames on the heap somehow; but I don't think we should involve Kilim in the matter; had Kilim been a proper continuation-style encoder, it would have made sense. A function which is self-recursive-sans-tail-call needs to have a separate self-call stack. Ugly blugly.

Trifork member

Found out what goes on. It's the {trim,1,1} insn that just "trims" the size of the current activation record. So the call is really normal-recursive, but that BEAM insn just lowers to cost because it makes it possible to reduce the stack size.

Perhaps we can find a way to re-code the special case of a non-tail, but recursive call that is followed by a cons, i.e. ... encode

  • {trim,N,N}
  • call (self)
  • put_list (i.e. a cons)
  • return

Into something tail-recursive with a reverse on the end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment