Машинопись преобразуется в JS. Затем идет встряска дерева, «меньше» (необязательно) и что еще в процессе развертывания. Но ничего подобного (afaik) не имеет ничего общего с "компиляцией". Все объединяется и сильно оптимизируется, но на самом деле не компилируется, верно?
Компиляция означает преобразование программы, написанной на языке A, в семантически эквивалентную программу, написанную на языке B, таким образом, что оценка скомпилированной программы в соответствии с правилами языка B (например, интерпретация ее с помощью интерпретатора для B ) дает тот же результат и имеет те же побочные эффекты, что и при оценке исходной программы в соответствии с правилами языка A (например, при ее интерпретации с помощью интерпретатора для A ).
Составление просто означает перевод программы с языка А на язык Б . Это все, что это значит. (Также обратите внимание, что A и B могут быть одним и тем же языком.)
В некоторых случаях у нас есть более специализированные имена для определенных типов компиляторов, в зависимости от того, что такое A и B , и что делает компилятор:
- если A воспринимается как язык ассемблера, а B - как машинный язык, то мы называем это ассемблером ,
- если A воспринимается как машинный язык, а B воспринимается как язык ассемблера, то мы называем это дизассемблером ,
- если A воспринимается как более низкий уровень, чем B , то мы называем это декомпилятором ,
- если A и B - это один и тот же язык, и полученная программа в некотором роде быстрее или легче, то мы называем ее оптимизатором ,
- если A и B - это одни и те же языки, и полученная программа меньше, то мы называем ее минификатором ,
- если A и B являются одними и теми же языками, и полученная программа менее читабельна, то мы называем ее обфускатором ,
- если воспринимается, что A и B находятся примерно на одном уровне абстракции, то мы называем это транспилятором и
- если A и B воспринимаются как находящиеся примерно на одном уровне абстракции, а результирующая программа сохраняет форматирование, комментарии и намерения программиста, так что можно поддерживать полученную программу таким же образом, как и исходная программа, тогда мы вызываем это инструмент реинжиниринга .
Также обратите внимание, что старые источники могут использовать термины «перевод» и «переводчик» вместо «компиляция» и «компилятор». Например, C говорит о «единицах перевода».
Вы также можете встретить термин «языковой процессор». Это может означать либо компилятор, либо интерпретатор, либо оба компилятора и интерпретатора в зависимости от определения.
Сам Javascript все еще интерпретируется, верно?
JavaScript - это язык. Языки - это набор логических правил и ограничений. Языки не интерпретируются и не компилируются. Языки просто есть .
Компиляция и интерпретация - это особенности компилятора или интерпретатора (да!). Каждый язык может быть реализован с помощью компилятора, и каждый язык может быть реализован с помощью интерпретатора. Многие языки имеют как компиляторы, так и интерпретаторы. Многие современные высокопроизводительные механизмы выполнения имеют как минимум один компилятор и как минимум один интерпретатор.
Эти два термина относятся к разным уровням абстракции. Если бы английский был типизированным языком, «интерпретируемый язык» был бы ошибкой типа.
Также обратите внимание, что в некоторых языках нет ни интерпретатора, ни компилятора. Есть языки, у которых вообще нет реализации. Тем не менее, это языки, и на них можно писать программы. Вы просто не можете их запустить.
Также обратите внимание, что в какой-то момент все интерпретируется : если вы хотите что-то выполнить, вы должны это интерпретировать. Компиляция просто переводит код с одного языка на другой. Это не работает. Это управляет интерпретация . (Иногда, когда интерпретатор реализован на оборудовании, мы называем его «ЦП», но это все равно интерпретатор.)
Показательный пример: каждая существующая в настоящее время основная реализация JavaScript имеет компилятор.
V8 начинался как чистый компилятор: он компилировал JavaScript прямо в умеренно оптимизированный машинный код. Позже был добавлен второй компилятор. Теперь есть два компилятора: легкий компилятор, который производит умеренно оптимизированный код, но сам компилятор очень быстр и использует мало оперативной памяти. Этот компилятор также вставляет код профилирования в скомпилированный код. Второй компилятор - это более тяжелый, медленный и более дорогой компилятор, который, однако, создает гораздо более жесткий и более быстрый код. Он также использует результаты кода профилирования, введенного первым компилятором, для принятия решений по динамической оптимизации. Кроме того, решение, какой код перекомпилировать с использованием второго компилятора, принимается на основе этой информации о профилировании. Обратите внимание, что переводчик ни разу не задействован. V8 никогда не интерпретирует, он всегда компилируется. Это не t даже есть интерпретатор. (На самом деле, я считаю, что сейчас это так, я описываю первые две итерации.)
SpiderMonkey компилирует JavaScript в байт-код SpiderMonkey, который затем интерпретирует. Интерпретатор также профилирует код, а затем код, который выполняется чаще всего, компилируется компилятором в собственный машинный код. Итак, SpiderMonkey содержит два компилятора: один из байт-кода JavaScript в SpiderMonkey, а другой из байт-кода SpiderMonkey в собственный машинный код.
Почти все механизмы выполнения JavaScript (за исключением V8) следуют этой модели компилятора AOT, который компилирует JavaScript в байт-код, и механизма смешанного режима, который переключается между интерпретацией и компиляцией этого байт-кода.
Вы написали в комментарии:
Я действительно думал, что здесь замешан машинный код.
Что вообще означает «машинный код»?
Что такое машинный язык одного человека, что является промежуточным языком другого человека, и наоборот? Например, есть процессоры, которые могут выполнять байт-код JVM изначально, на таком ЦП байт-код JVM является собственным машинным кодом. И есть интерпретаторы для машинного кода x86, когда вы запускаете этот машинный код x86 , интерпретируется байт-код.
Существует интерпретатор x86 под названием JPC, написанный на Java. Если я запускаю машинный код x86 на JPC, работающем на собственном процессоре JVM ... какой байт-код, а какой собственный? Если я скомпилирую машинный код x86 в JavaScript (да, есть инструменты, которые могут это сделать) и запустил его в браузере на моем телефоне (который имеет процессор ARM), какой будет байт-код, а какой - собственный машинный код? Что, если программа, которую я компилирую, представляет собой эмулятор SPARC, и я использую его для запуска кода SPARC?
Обратите внимание, что каждый язык порождает абстрактную машину и является машинным языком для этой машины. Итак, каждый язык (включая языки очень высокого уровня) - это собственный машинный код. Кроме того, вы можете написать переводчика для любого языка. Итак, каждый язык (включая машинный код x86) не является родным.