Машинопис надходить до 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 сприймаються приблизно на одному рівні абстракції, а отримана програма зберігає форматування, коментарі та намір програміста таким чином, що можна підтримувати отриману програму таким же чином, як і оригінальна програма, тоді ми називаємо це інструмент реінжинірингу .
Також зауважте, що в старих джерелах можуть використовуватися терміни "переклад" та "перекладач" замість "компіляція" та "компілятор". Наприклад, С говорить про "одиниці перекладу".
Ви також можете натрапити на термін "мовний процесор". Це може означати як компілятор, інтерпретатор, так і компілятори та інтерпретатори, залежно від визначення.
Сам Javascript все ще інтерпретується, так?
JavaScript - це мова. Мови - це сукупність логічних правил та обмежень. Мови не інтерпретуються та не компілюються. Мови просто є .
Компіляція та інтерпретація - це риси упорядника чи інтерпретатора (duh!). Кожна мова може бути реалізована за допомогою компілятора, а кожна мова - за допомогою інтерпретатора. Багато мов мають як компілятори, так і інтерпретатори. У багатьох сучасних високопродуктивних механізмах виконання є принаймні один компілятор і принаймні один інтерпретатор.
Ці два терміни належать до різних шарів абстракції. Якби англійська мова була типовою, "інтерпретована мова" була б помилкою типу.
Зауважте також, що деякі мови не мають ні інтерпретатора, ні компілятора. Є мови, які взагалі не мають реалізації. І все-таки це мови, і ви можете писати програми на них. Ви просто не можете їх запускати.
Також зауважте, що все в якийсь момент інтерпретується : якщо ви хочете щось виконати, ви повинні інтерпретувати це. Компіляція просто перекладає код з однієї мови на іншу. Це не запускає його. Інтерпретація запускає його. (Іноді, коли інтерпретатор реалізований в апаратному забезпеченні, ми називаємо його "ЦП", але це все одно інтерпретатор.)
Приклад: кожна окрема існуюча на сьогодні реалізація JavaScript має компілятор.
V8 починався як чистий компілятор: він компілював JavaScript прямо в помірно оптимізований власний машинний код. Пізніше був доданий другий компілятор. Зараз є два компілятори: легкий компілятор, який виробляє помірно оптимізований код, але сам компілятор дуже швидкий і використовує мало оперативної пам'яті. Цей компілятор також вводить код профілювання в скомпільований код. Другий компілятор - це більш важкий, повільний, дорожчий компілятор, який, однак, видає набагато жорсткіший, набагато швидший код. Він також використовує результати коду профілювання, введений першим компілятором, для прийняття рішень щодо динамічної оптимізації. Крім того, рішення, який код повторно скомпілювати за допомогою другого компілятора, приймається на основі цієї інформації профілювання. Зверніть увагу, що жодного разу не бере участь перекладач. V8 ніколи не інтерпретує, він завжди компілює. Це не навіть не містить перекладача. (Насправді, я вважаю, що сьогодні це так, я описую перші дві ітерації.)
SpiderMonkey компілює JavaScript в байт-код SpiderMonkey, який потім інтерпретує. Інтерпретатор також профілює код, а потім код, який виконується найчастіше, компілюється компілятором до власного машинного коду. Отже, SpiderMonkey містить два компілятори: один - від JavaScript до байт-коду SpiderMonkey, а інший - від байтового коду SpiderMonkey до власного машинного коду.
Майже всі механізми виконання JavaScript (за винятком V8) дотримуються цієї моделі компілятора AOT, який компілює JavaScript у байт-код, та механізму змішаного режиму, який перемикається між інтерпретацією та компіляцією цього байт-коду.
Ви написали в коментарі:
Я справді думав, що десь задіяний машинний код.
Що взагалі означає «машинний код»?
Що таке машинна мова однієї людини - це середня мова іншої людини і навпаки? Наприклад, є центральні процесори, які можуть виконувати власне байт-код JVM, на такому процесорі байт-код JVM є власним машинним кодом. І є перекладачі для x86 машинного коду, при запуску з цих x86 машинного коду буде інтерпретувати байти - код.
Існує інтерпретатор x86 під назвою JPC, написаний на Java. Якщо я запускаю машинний код x86 на JPC, що працює на вбудованому процесорі JVM…, який це байт-код, а який - власний код? Якщо я скомпілюю машинний код x86 в JavaScript (так, є інструменти, які можуть це зробити) і запустити його у браузері на своєму телефоні (який має ARM CPU), який є байт-кодом, а який є власним машинним кодом? Що робити, якщо програма, яку я складаю, є емулятором SPARC, і я використовую його для запуску коду SPARC?
Зверніть увагу, що кожна мова викликає абстрактну машину і є машинною мовою для цієї машини. Отже, кожна мова (включаючи мови високого рівня) є рідним машинним кодом. Крім того, ви можете написати перекладача для будь-якої мови. Отже, кожна мова (включаючи машинний код x86) не є рідною.