Подробное объяснение двигателя V8 (2) - AST

JavaScript

предисловие

Эта статья является второй частью серии подробных объяснений движка V8. Основное внимание уделяется некоторому пониманию абстрактного синтаксического дерева (AST), созданного V8 в процессе компиляции и работы. Если вы не знаете основной процесс работы v8 , сначала вы можете прочитать мою первую статью.Подробное объяснение двигателя V8 (1) - Обзор.

Концепция АСТ

1. Что такое АСТ

Студенты, прочитавшие мою предыдущую статью, должны знать, что движок V8 сначала преобразует код javascript в AST (абстрактное синтаксическое дерево), и фактически независимо от того, какой язык программирования (интерпретируемый или скомпилированный) используется, он преобразует исходный код. код анализируется в абстрактное синтаксическое дерево (AST). AST — это ранняя концепция в информатике, не уникальная для V8 (только в V8 была проведена большая оптимизация в процессе преобразования), а также не уникальная для javascript.

Всем известно, что если вы хотите запустить javascript-программу, вам нужно обработать исходный js-файл, чтобы движок v8 его понял, и первым шагом является преобразование js-кода в абстрактное синтаксическое дерево (AST), которое по сути представляет собой набор объектов, представляющих структуру программы. а затемLgnition(Подробнее об этом в моей будущей статье) Скомпилируйте AST для генерации байт-кода.

Во-вторых, использование АСТ.

Роль AST используется не только при компиляции v8, но и в самом процессе разработки, например, в нашем часто используемом плагине babel для es6->es5, ts->js, сжатии кода, предварительной обработке css. незаменимы в нашем фактическом развитии, и их основополагающие принципы на самом деле являются AST.

3. Структура

Мы уже знаем некоторые основные концепции AST и некоторые способы его использования, так что же это за структура AST? Я покажу вам небольшой инструмент. (Структура AST, сгенерированная v8, отличается от показанной ниже. Структура, сгенерированная V8, неудобна для чтения и была специально оптимизирована. Эта диаграмма предназначена для удобства понимания в первую очередь)

Адрес инструмента:ESPRima.org/demo/parse. …

На самом деле формат синтаксического анализа на приведенном выше рисунке соответствует отраслевому стандарту.JS-движок первого поколения SpiderMonkey был разработан Бренданом Эйхом, отцом js, а затем передан Mozilla для обслуживания, а затем он был открыт. .Parser_APIС обновлением и итерацией ECMAScript он постепенно обновлялся и постепенно стал текущим отраслевым стандартом.

Этот формат не сложный, его может открыть каждыйParser_APIСотрудничатьонлайн-инструмент эспримаВы можете быстро понять и освоить его, наблюдая и настраивая

Процесс компиляции АСТ

1. Основной процесс

Давайте сначала посмотрим на блок-схему:

Вы можете видеть, что процесс AST, сгенерированный стандартным инструментом AST и V8, немного отличается. Причина в том, что требования разные. Например, мы часто используем инструмент babel для es6-> es5. Ему нужно сохранить исходную структуру и выполнить полный анализ, а затем сгенерировать Новый код, а AST, сгенерированный v8, не нужно конвертировать в es6, поэтому будет много места для операций оптимизации в процессе генерации AST, что обуславливает разницу в процесс и поколение V8, о которых мы упоминали выше.Parser_APIканоническое дерево, но есть еще два важных шагаscannerа такжеParserНо все это нужно сделать.

2. Сканер лексического анализа

Самая важная функция сканера — преобразовать исходный код js в массив значимых слов (токен).
Давайте воспользуемся простым примером, чтобы понять его общий рабочий процесс или проанализируем его с помощью простейшего утверждения.

var a = 123;

Давайте представим, что код начинает читать символы из приведенного выше потока символов, полученного протоколом HTTP, когда мы читаем первый символ «v»:

  • Мы будем использовать условный оператор, чтобы определить, что символ является буквой, «/», «числом», пробелом, «(», «)», «;» и так далее.

  • Если это ';', это сгенерирует{"type" : "Punctuator" , "value" : ";" }$ в массив.

  • Если это буква, она будет продолжать смотреть вниз, или это буква или цифра, и она будет продолжать этот процесс до тех пор, пока это не будет. Ключевое слово и следующий символ — «пробел».{ "type" : "Keyword" , "value" : "var" }в массив.

  • Он продолжает смотреть вниз и находит букву «a» (поскольку последнее найденное значение — «var» в это время, если он обнаружит, что следующий символ не является буквой, он может напрямую вернуть ошибку), и за ним следует пространство, генерирующее{ "type" : "Identifier" , "value" : "a" }в массив.

  • нашел "=", сгенерировал{ "type" : "Punctuator" , "value" : "=" }помещается в массив.

  • найдено '123', сгенерировано{ "type" : "Numeric" , "value" : "123" }помещается в массив.

  • Наконец нашел ';', сгенерировал{ "type" : "Punctuator" , "value" : ";" }в массив.

Давайте посмотрим на сгенерированные результаты

Общий принцип в основном таков, конечноv8Иметь собственную стратегию реализации, конечно, не так просто, как я написал, но основные принципы схожи.
Если вам интересно, вы хотели бы узнать большеv8Для стратегии реализации сканера вы можете посмотреть официальную документацию v8:V8.Dev/blog/Как насчет трехразового питания...

На самом деле лексическая часть большинства языков реализована на схожих принципах конечного автомата, включая даже известныйОфициальная HTML-документация.

3. Парсер синтаксического анализа

ДалееParserНа самом деле проделанная работа заключается в том, чтобы снова проанализировать результат после лексического анализа (возвращенный массив) и преобразовать массив в объект в соответствии с определенным форматом в процессе анализа.Основной принцип заключается в том, чтобы пройти наш массив, чтобы судить о создании структуры ( AST), здесь я хочу акцентировать внимание на некоторых различиях между AST, сгенерированным v8, и обычными инструментами.

Я уже говорил, что обычное дерево AST использует тот же отраслевой стандарт, то есть черезParserСгенерированное дерево AST можно даже напрямую передатьbableОн напрямую скомпилирован и преобразован, а тот, который сгенерирован v8, предназначен для самой v8.LgnitionРезультат сгенерированного движком байт-кода оптимизирован, поэтому между ними есть большая разница.Далее я приведу несколько небольших примеров, чтобы помочь вам понять.

Начнем с самого простого

var a = 123;

Сравните сгенерированные результаты

Если вы внимательно прочитали вышеизложенное и провели простой эксперимент, то точно сможете понять стандартную структуру картинки слева, в то время как картинка справаv8Описание сгенерированного AST также можно совместить с кодом, рассмотрим этот код ниже:

var a = 6 * 7;

Сгенерированный результат:

Стандартная структура описана ниже6 * 7эта структура иv8Рассчитанные результаты генерируются напрямую, что уменьшитv8проходить позадиLgnitionРесурсы, потребляемые на генерацию байт-кодов, используются для повышения производительности.Если вы считаете, что потребление света не имеет значения, то мы продолжим смотреть вниз:

function test () {
	return 1 + 2;
}

когдаV8обнаружил, что исходный файл только что объявилtestКогда функция вызывается, но не вызывается, в ней вообще ничего не анализируется, поэтому давайте продолжим смотреть, что происходит, когда она вызывается:

function test () {
	return 1 + 2;
}
var a = test();

мы можем узнать, чтоv8Сгенерированное дерево AST индивидуальноtestФункция генерирует узел AST вместо генерации основного процесса, что имеет много преимуществ (например, в процессе инициализации, т.к. это не тема данной статьи, я не буду вдаваться в подробности), и более очевидно, что с увеличением исходного кода js Разрыв между размером AST-дерева, сгенерированного v8, и размером AST-дерева стандартной структуры становится все шире и шире, поэтому преимуществ в парсинге, естественно, больше.

Приведенные выше несколько простых примеров просто объясняют, почему с помощью самого простого и понятного кодаv8Сгенерированное дерево AST не является стандартным каноническим деревом (это верно, оно создано для скорости).
и на самом делеv8Работа и оптимизация, проделанная при создании дерева AST, намного больше, чем небольшие примеры, которые я упомянул выше.Если вам интересно узнать больше о стратегии реализации v8 Parser, вы можете взглянуть на официальную документацию v8:V8.Dev/blog/prepar…

Суммировать

Эта статья в основном знакомитдвигатель v8Первый шаг компиляции и выполнения - создание AST, путем понимания того, что такое AST, и процесс создания AST включает в себя объяснение, почемудвигатель v8Почему не следовал спецификации AST, автор не анализировал процесс генерации на уровне исходного кода, в основном, чтобы узнать так, чтобы больше людей могли понятьдвигатель v8(В основном уровень автора недостаточно), если есть какие-либо ошибки, пожалуйста, обсудите с автором в комментариях, если вы думаете, что эта статья вам полезна, пожалуйста, помогите вам, я благодарен.

Справочная статья

V8.Dev/blog/Как насчет трехразового питания...
V8.Dev/blog/prepar…
cloud.Tencent.com/developer/ ах…

серия статей

Подробное описание двигателя V8 (1) — обзор
Подробное объяснение двигателя V8 (2) - AST
Подробный двигатель V8 (три) - от байт-кода до эволюции V8
Подробное объяснение движка V8 (4) - как выполняется байт-код
Подробное объяснение двигателя V8 (5) - встроенный кэш
Подробное объяснение двигателя V8 (6) - структура памяти
Подробное объяснение двигателя V8 (7) — механизм сбора мусора
Подробное объяснение движка V8 (8) - очередь сообщений
Подробное объяснение двигателя V8 (9) - функция сопрограммы и генератора