Оптимизированы ли хвосты для Javascript-двигателей?

У меня есть хвостовой рекурсивный алгоритм поиска пути, который я реализовал в Javascript, и хотел бы знать, могут ли какие-либо (все?) браузеры получить исключения.

Ответ 1

Спецификация ECMAScript 4 изначально собиралась добавить поддержку TCO, но она была удалена.

http://lambda-the-ultimate.org/node/3047

Насколько я знаю, широкодоступные реализации JS в настоящее время не выполняют автоматическую TCO. Это может быть полезно для вас:

http://www.paulbarry.com/articles/2009/08/30/tail-call-optimization

По существу, использование шаблона аккумулятора выполняет тот же эффект.

Ответ 3

Практически каждый браузер, с которым вы столкнулись, будет "слишком рекурсивно". Здесь находится запись в трекере V8, которая, вероятно, будет интересна для чтения.

Если это простая саморегуляция, вероятно, стоит попытаться использовать явную итерацию, а не надеяться на устранение хвостового вызова.

Ответ 4

Оптимизация вызовов в хвосте будет поддерживаться в строгом режиме ECMAScript 6 в будущем. Проверьте http://www.2ality.com/2015/06/tail-call-optimization.html для деталей.

Проверьте http://kangax.github.io/compat-table/es6/ для текущей поддержки двигателя.

На данный момент (18-07-2019) следующие механизмы поддерживают оптимизацию хвостовых вызовов:

  • Safari> = 10
  • iOS> = 10
  • Кинома XS6
  • Duktape 2.3

поддержка, если включены "экспериментальные функции JavaScript" -flag:

  • Узел 6.5
  • Chrome 54/Opera 41 Текущая версия таблицы сравнения больше не содержит ее

Ответ 5

Оптимизация звонков теперь доступна в LispyScript, который компилируется в javascript. Вы можете прочитать об этом здесь.

Ответ 6

В настоящее время реализация JS не распознает хвостовую рекурсию. Изменения приводятся в ECMAScript 6, и, как говорили другие, есть открытый билет на V8

Здесь вы можете увидеть V8 сгенерированный ассемблер для функции рекурсии хвоста

https://gist.github.com/mcfedr/832e3553964a014621d5

Сравните это с тем, как clang скомпилировал ту же функцию в C

https://gist.github.com/mcfedr/63ad08370d856bad3694

V8 сохраняет рекурсивный вызов, тогда как компилятор C распознал хвостовую рекурсию и изменил ее на цикл