Введение

SpiderMonkey — это движок JavaScript и WebAssembly с открытым исходным кодом, разрабатываемый Mozilla Foundation. Это первый движок JavaScript, написанный Бренданом Эйхом в Netscape Communications, а затем выпущенный под открытой лицензией и в настоящее время поддерживаемый Mozilla Foundation. Он используется в веб-браузере Firefox.

Стандарты

SpiderMonkey реализует спецификацию ECMA 262 (ECMAScript). Поддержка ECMA 357 (ECMAScript для XML (E4X)) была прекращена в начале 2013 года.

Внутренние

SpiderMonkey написан на C/C++ и включает в себя интерпретатор, JIT-компилятор IonMonkey и сборщик мусора.

TraceMonkey (полное приложение)

TraceMonkey был первым JIT-компилятором, разработанным для языка JavaScript. Изначально представленный как опция в бета-версии и анонсированный в блоге Брендана Айха 23 августа 2008 года, компилятор вошел в состав основной версии SpiderMonkey в Firefox 3.5, обеспечивая "увеличение производительности в 20-40 раз" по сравнению с базовым интерпретатором в Firefox 3. Вместо компиляции целых функций, TraceMonkey являлся трассирующим JIT-компилятором, который работал путем записи потока управления и типов данных во время выполнения интерпретатором. Эти данные использовались для построения трассовых деревьев – высокоспециализированных путей машинного кода. Улучшения JägerMonkey в конечном итоге привели к устареванию TraceMonkey, особенно с развитием механизма вывода типов в SpiderMonkey. TraceMonkey отсутствует в SpiderMonkey, начиная с Firefox 11.

Ягер-обезьяна

JägerMonkey, внутренне названный MethodJIT, был JIT-компилятором всего метода, разработанным для повышения производительности в тех случаях, когда TraceMonkey не мог генерировать стабильный машинный код. Он впервые был выпущен в Firefox 4 и в конечном итоге полностью заменил TraceMonkey. Впоследствии он сам был заменен IonMonkey. JägerMonkey работал принципиально иначе, чем другие компиляторы подобного типа: в то время как типичные компиляторы строили и оптимизировали граф потока управления, представляющий функцию, JägerMonkey вместо этого последовательно проходил по байт-коду SpiderMonkey – внутреннему представлению функции. Хотя это ограничивает оптимизации, требующие переупорядочивания инструкций, компиляция JägerMonkey отличается высокой скоростью, что особенно важно для JavaScript, поскольку повторная компиляция из-за изменения типов переменных происходит часто. Mozilla реализовала в JägerMonkey ряд важных оптимизаций, в частности полиморфные встроенные кэши и вывод типов. Различия между техниками JIT TraceMonkey и JägerMonkey, а также необходимость использования обоих подходов, были объяснены в статье на hacks.mozilla.org. Более подробное описание технических деталей привел Крис Лири, один из разработчиков SpiderMonkey, в своем блоге. Дополнительную техническую информацию можно найти в блогах других разработчиков: dvander, dmandelin.

IonMonkey (ионная обезьяна)

IonMonkey был JIT-компилятором JavaScript от Mozilla, разработанным для реализации множества новых оптимизаций, которые были невозможны в предыдущей архитектуре JägerMonkey. IonMonkey представлял собой более традиционный компилятор: он преобразовывал байт-код SpiderMonkey в граф потока управления, используя статическую форму однозначного присваивания (SSA) в качестве промежуточного представления. Такая архитектура позволила применять к JavaScript известные оптимизации из других языков программирования, включая специализацию типов, подстановку функций, линейное распределение регистров, удаление неиспользуемого кода и вынос инвариантного кода из циклов. Компилятор способен генерировать быстрый машинный код для JavaScript-функций на платформах ARM, x86 и x86-64. Он являлся движком по умолчанию, начиная с Firefox 18.

Одина-Обезьяна

OdinMonkey — это название нового модуля оптимизации Mozilla для asm.js, легко компилируемого подмножества JavaScript. Сам OdinMonkey не является JIT-компилятором, а использует существующий JIT-компилятор. Он включен в Firefox, начиная с 22-й версии.

WarpMonkey (Варпояса)

WarpMonkey JIT заменяет прежний движок IonMonkey, начиная с версии 83. Он способен встраивать другие скрипты и специализировать код на основе обрабатываемых данных и аргументов. Он преобразует байт-код и данные Inline Cache в промежуточное представление среднего уровня (Ion MIR). Этот граф преобразуется и оптимизируется перед тем, как быть пониженным до низкоуровневого промежуточного представления (Ion LIR). Этот LIR выполняет распределение регистров, а затем генерирует машинный код непосредственно в процессе, называемом генерацией кода. Оптимизации здесь основаны на предположении, что скрипт продолжает обрабатывать данные, аналогичные тем, что он видел ранее. Базовые JIT-компиляторы необходимы для успеха, поскольку они генерируют Inline Cache, соответствующие наблюдаемым данным. Если после компиляции скрипта с помощью Warp он сталкивается с данными, к обработке которых он не подготовлен, происходит откат. Механизм отката восстанавливает фрейм стека машинного кода, соответствующий структуре, используемой базовым интерпретатором, и затем переходит к этому интерпретатору, как если бы он работал с самого начала. Для построения этого фрейма стека Warp может использовать специальную вспомогательную таблицу, сохраненную для восстановления значений, которые иначе были бы недоступны.