Skip to content


Subversion checkout URL

You can clone with
Download ZIP


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

eriksoe opened this Issue · 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.


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 :-)


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.


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
Something went wrong with that request. Please try again.