简体   繁体   English

Javascript引擎中的尾调用优化实现

[英]Tail Call Optimization implementation in Javascript Engines

As of February 2019 in Chrome Version 71.0.3578.98 on Mac , the following program throws Uncaught RangeError: Maximum call stack size exceeded error. 截至2019年2月,在Mac上的Chrome版本71.0.3578.98中,以下程序抛出Uncaught RangeError: Maximum call stack size exceeded error. at a count of 16516 . 数量为16516

const a = x => {
  console.log(x)
  a(x + 1)
}

a(1)

I've done quite a bit of Googling, but wasn't able to find any articles discussing Chrome or other browser support for Tail Call Optimization (TCO) or any future plans to implement it. 我已经做了很多谷歌搜索,但无法找到任何文章讨论Chrome或其他浏览器支持尾部呼叫优化(TCO)或任何未来实施它的计划。

My two questions are: 我的两个问题是:

  1. Is TCO currently supported in Chrome or any other browser or Javascript Engine Chrome或任何其他浏览器或Javascript引擎目前是否支持TCO
  2. Are there plans to implement TCO in the near future in any Javascript Engine 是否有计划在不久的将来在任何Javascript引擎中实施TCO

The posts that I've found are mostly old (2016 or earlier) or simply confusing. 我发现的帖子大多是旧的(2016年或更早),或者只是令人困惑。 eg https://www.chromestatus.com/feature/5516876633341952 例如https://www.chromestatus.com/feature/5516876633341952

TCO, or rather, Tail Call Elimination in JavaScript -- also often referred to as Proper Tail Calls (PTC) in discussions -- is a long and sad story. TCO,或者更确切地说,JavaScript中的尾部呼叫消除 - 在讨论中通常被称为正确的尾部呼叫(PTC) - 是一个漫长而悲伤的故事。

Around 2011, TC39 (the JavaScript standards committee) decided to adopt mandatory TCE for the forthcoming ES6 standard, with consensus from all major browser vendors. 2011年左右,TC39(JavaScript标准委员会)决定对即将推出的ES6标准采用强制性TCE,并得到所有主要浏览器厂商的一致认可。

In 2015, the new standard was officially adopted, under the name EcmaScript 2015. At this point, no browser had actually implemented TCE, mostly because there were too many new features in ES2015 that were deemed more important to get out. 2015年,新标准正式采用,名称为EcmaScript 2015.此时,没有任何浏览器实际实施过TCE,主要是因为ES2015中有太多新功能被认为更重要。 (Today's process for JS feature proposals and their adoption, which includes the requirement of two implementations in production engines, did not yet exist for ES6.) (今天的JS功能提案及其采用的过程,包括生产引擎中两个实现的要求,ES6尚不存在。)

In early 2016, both Safari and Chrome implemented TCE. 2016年初,Safari和Chrome都实施了TCE。 Safari announced shipping it, while Chrome kept it behind an Experimental Feature flag. Safari宣布发布它,而Chrome则将其置于实验功能标志之后。 Other browsers (Firefox and Internet Explorer / Edge) started looking into it as well and had second thoughts. 其他浏览器(Firefox和Internet Explorer / Edge)也开始研究它并且有了第二个想法。 Discussion evolved whether this is a viable feature after all. 毕竟,讨论是否是一个可行的特征。 Edge had problems implementing it efficiently for the Windows ABI, Firefox was concerned about the developer experience of calls "missing" from stack traces (an issue that was already discussed at length in 2011). Edge在为Windows ABI高效实现它时遇到了问题,Firefox担心开发人员在堆栈跟踪中“丢失”调用的经历(这个问题已在2011年详细讨论过)。

In an attempt to address some of these concerns while rescuing the tail call feature, several members, including the Chrome and Edge teams, proposed to make tail calls explicit , ie, require return statements to be annotated with an additional keyword to opt into tail call semantics. 在尝试解决尾部调用功能时解决其中一些问题时,包括Chrome和Edge团队在内的几个成员建议将尾调用显式化 ,即需要使用附加关键字注释return语句以选择尾调用语义。 These so-called " syntactic tail calls " (STC) were implemented in Chrome as a proof of concept. 这些所谓的“ 语法尾调用 ”(STC)在Chrome中实现,作为概念验证。

At the May 2016 TC39 meeting the issue of tail calls was discussed extensively for almost an entire day with no resolution. 在2016年5月的TC39会议上,尾部呼叫问题已被广泛讨论了将近一整天而没有解决方案。 Firefox and Edge made clear that they would not implement TCE as specified in the standard. Firefox和Edge明确表示他们不会按照标准中的规定实施TCE。 Firefox members proposed to take it out. Firefox成员建议将其删除。 Safari and Chrome did not agree with that, and the Safari team made clear that they have no intention of unshipping TCE. Safari和Chrome不同意这一点,Safari团队明确表示他们无意取消TCE。 The proposal for syntactic tail calls was rejected as well, especially by Safari. 语法尾部调用的提议也被拒绝,尤其是Safari。 The committee was in an impasse. 该委员会处于僵局。 You can read the meeting notes of this discussion . 您可以阅读本次讨论会议记录

Technically, this impasse still exists today, as far as I am aware. 从技术上讲,就我所知,这种僵局至今仍然存在。 Practically speaking, though, tail calls for JavaScript are pretty much dead, and it's unclear whether they will ever come back. 实际上,尾部调用JavaScript几乎已经死了,目前还不清楚它们是否会再次出现。 At least that was the conclusion of the Chrome team after the disastrous meeting, which led to the decision to remove the implementation of tail calls from Chrome, in order to simplify the engine and prevent bit rot. 至少那是在灾难性会议之后Chrome团队的结论,这导致决定从Chrome中删除尾部调用的实现,以简化引擎并防止有点腐烂。 They are still available in Safari. 它们仍可在Safari中使用。

Disclosure: I was a member of TC39 and of the Chrome/V8 team until 2017, so my views may be biased. 披露:我是TC39和Chrome / V8团队的成员,直到2017年,所以我的观点可能有偏见。

Even tho TCO seems to be a pipe dream for all of us, by using a trampoline technique, you can easily convert your code to run as if it is being tail optimized. 即使TCO似乎是我们所有人的梦想,通过使用trampoline技术,您可以轻松地将代码转换为运行,就好像它是尾部优化的一样。

 const a = x => { if(x > 500000) { console.log(x); return; } return ()=> a(x + 1); //you return a function, it hasn't been called yet } const trampoline = fn => (...args) => { let result = fn(...args) //repeatedly call the function till you hit your base case while (typeof result === 'function') { result = result(); } return result; } var t = trampoline(a); t(1); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM