Глава 19. Объясните рабочий процесс кэша компиляции и основные принципы.

Добро пожаловать в другие главы Давайте разберемся с Chrome V8

Из соображений производительности V8 использует кэш компиляции для хранения SharedFunction, который является результатом компиляции, кэш возвращает результат непосредственно после повторной компиляции того же кода JavaScript.

Вы можете спросить, почему один и тот же код компилируется снова. Сначала скомпилируйте, а затем выполните — это конвейер V8. Даже точно такой же код, ту же функцию все равно нужно отправить компилятору, но не всегда перекомпилировать. На самом деле, код JavaScript может изменяться во время выполнения, поэтому первое действие всегда заключается в том, что мы получаем хеш-значение кода JavaScript из кеша компиляции, возвращаем SharedFunction при попадании в кеш и перекомпилируем JavaScript наоборот.

1. Инициализация и заполнение

Isolate, экземпляр виртуальной машины V8, отвечает за инициализацию CompilationCache, isolate::Init, как показано ниже:

Последняя строка теперь представляет собой CompilationCache, а именно initialization. Давайте углубимся в это глубже.

Есть три основных принципа вышеупомянутой функции, которые важны:

1. LookupScript() в строке 3. Он используется для поиска в кеше функции SharedFunction, которая содержит байт-коды, соответствующие вашему коду JavaScript. При попадании пропустите компиляцию непосредственно в исполнительный блок.

2. PutScript() в строке 13. Если LookupScript промахивается, PutScript() помещает хэш, соответствующий вашему коду JavaScript и SharedFunciton, которые компилятор генерирует в кэш перед выполнением.

3. LookupEval и PutEval в строках 7 и 16. Они такие же, как LookupScript и PutScript, но специализируются на методе оценки JavaScript, поскольку для оценки требуется не только SharedFunction, но и контекст.

Давайте рассмотрим LookupScript более подробно:

Мы можем обнаружить, что CompilationCache::LookupScript — это только вход, а ключевая функция, а также важный код находятся в CompilationCacheScript::Lookup().

1. В Lookup() источником аргумента является код JavaScript, который вы, как разработчики, фактически пишете и который будет скомпилирован.

2. GetTable в строке 20. Это фактическая таблица, содержащая данные, в которые помещается PutScript.

3. CompilationCacheTable::LookupScript в строке 21. Найдите в таблице результат, в котором попадание означает, что SharedFunction или промах равны нулю.

4. В строке 25: проверьте правильность SharedFunction в зависимости от Origin.

Давайте взглянем на HasOrigin.

Комментарии от строки 1 до строки 3 содержат правила проверки происхождения. В частности, реализация находится от строки 14 до строки 16.

Далее, давайте перейдем к PutScript.

Как и LookupScript(), CompilationCache::PutScript является входным, все самое важное находится в CompilationCacheTable::PutScript.

В PutScript я хотел бы сообщить вам, что таблица кеша будет заполняться. Ниже приведен исходный код CacheTable:

От строки 1 до строки 11 комментарии дают достаточно соответствующих объяснений.

Вернемся к CompilationCacheScript::Put() и перейдем к строке 16, которая называется CompilationCacheTable::PutScript().

Я думаю, что важно то, что PutScript связывает исходный код JavaScript и SharedFuncation как хеш-пару, а также помещает его в кеш, реализация которого находится в строках с 9 по 15.

2. Поиск и обновление

Перейдем к Compiler::GetSharedFunctionInfoForScript.

В строке 14 это означает, что нам нужно скомпилировать код JavaScript, если LookupScript отсутствует, поэтому мы переходим к строке 21, чтобы выполнить компиляцию и сгенерировать inner_result. Затем в строке 29 поместите inner_result в кеш. Мы можем обнаружить, что innuer_result — это просто may_result в строке 32.

На рис. 1 показан стек вызовов.

Помимо LookupScript и PutScript, в V8 есть также LookupEval, PutEval, а также LookupRegExp, PutRegExp. Их рабочий процесс такой же, как у LookupScript и PutScript, изучите их сами.

Хорошо, на этом мы закончили. Увидимся в следующий раз, берегите себя!

Пожалуйста, свяжитесь со мной, если у вас есть какие-либо проблемы. WeChat: qq9123013 Электронная почта: [email protected]

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord.