ES6 Tail Recursion Optimisation Stack Overflow

JavascriptRecursionOptimizationEcmascript 6Stack Overflow

Javascript Problem Overview


Having read Dr Rauschmayer's description of recursive tail call optimisation in es6, I've since been trying to recreate the 'zero-stack' execution of the recursive factorial function he details.

Using the Chrome debugger to step between stack frames, I'm seeing that the tail optimisation is not occurring and a stack frame is being created for each recursion.

I've also tried to test the optimisation by calling the function without the debugger, but instead passing 100000 to the factorial function. This throws a 'maximum stack' error, which implies that it is, in fact, not optimised.

Here is my code:

const factorial = (n, acc = 1) => n <= 1 ? acc : factorial(n - 1, n * acc)
console.log( factorial(100000) )

Result:

Uncaught RangeError: Maximum call stack size exceeded

Javascript Solutions


Solution 1 - Javascript

V8, the JavaScript engine in Chrome, had TCO support for a while, but as of this updated answer (November 2017) it no longer does and as of this writing, there is no active development on TCO in V8, and none is planned. You can read the details in the V8 tracking bug for it.

TCO support seems to have reached a decent level in V8 at one point, but remained behind a flag for several reasons (debugging issues, bugs). But then several things happened, not least that the V8 team raised significant issues with TCO and strongly supported a spec change called syntactic tail calls (STCs) that would require that tail calls be flagged in source code intentionally (e.g., return continue doThat();). That proposal became inactive in July 2017, though. Also in July, with no TCO work being done, the V8 team removed the code for supporting TCO from the source for TurboFan* as it would otherwise be subject to bitrot. (E.g., become a maintenance pain and source of bugs.)

So at present (Nov 2017) it's not clear that "invisible" TCO will ever be in V8, whether some kind of STCs will come in, or what. The Chrome Platform Status page for this indicates "mixed" public signals from Mozilla (Firefox/SpiderMonkey) and Microsoft (Edge/Chakra) on supporting TCO, that Safari is shipping with TCO, and that web developers are "positive" about the feature. We'll see where we go from here. If anywhere.

* (TurboFan = the current cutting-edge JIT compiler in V8, now they've switched from Full-Codegen [JIT] + Crankshaft [aggressive optimizing JIT] to Ignition [interpreter+] and TurboFan [aggressive optimizing JIT])

Solution 2 - Javascript

The V8 (Chrome's JS engine) team is not implementing TCO, for the time being. It's ripped out of the most recent versions (see this thread).

Of the major browsers, only Safari has actually implemented the feature (described in this 2016 Webkit blog post).

In Node.JS version 8 and later, TCO is not available.

There may be some hope of TCO being implemented: in a 2017 WebAssembly meeting, Google and all the other groups present were neutral or positive toward exploring TCO implementation further.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSam HanlanView Question on Stackoverflow
Solution 1 - JavascriptT.J. CrowderView Answer on Stackoverflow
Solution 2 - JavascriptFreewalkerView Answer on Stackoverflow