Тип вывода используется:
SpiderMonkey в основном использует определение типа, чтобы определить, какие свойства доступны; в тех случаях, когда вывод типа не находит точную форму объекта, к которому осуществляется доступ, SpiderMonkey использует PIC (полиморфные встроенные кэши) для хранения результата поиска.
Дополнительной формой обратной связи профилирования являются полиморфные встроенные кэши Baseline JIT. Полиморфные встроенные кэши - это классический метод оптимизации динамической отправки, созданный в сообществе Smalltalk.
Де-оптимизация - это имя процесса, который происходит при сбое вывода типа:
Конечно, JavaScript является динамически типизированным языком, иногда предположение о скрытом классе объекта будет неверным, и в этом случае V8 будет «де-оптимизировать» и вернется к исходной версии вызова метода в который скрытый класс объектов проверяется.
Для работы необходимо несколько компиляторов:
Технически это означает, что компилятор на самом деле представляет собой два компилятора: базовый компилятор и «оптимизатор». (Или даже больше, если речь идет об АО и SpiderMonkey). Концепция вполне разумна и может дать невероятную производительность, но есть нюанс: оптимизированный код может быть «деоптимизирован» в разных местах, а не только в точке входа, что означает, что среда (локальные переменные, аргументы, контекст) должна быть нанесены на карту и перемещены.
Ion, будучи оптимизирующим компилятором, не поддерживает компиляцию в проверках режима отладки. В самом деле, реализация такой поддержки весьма сомнительна, так как ее оптимизация сделает вызовы onStep в лучшем случае неудачными. Для поддержки режима отладки оптимизированный код в стеке деоптимизируется и выдается на базовый уровень. То есть кадр Ion в стеке перезаписывается восстановленным базовым кадром, соответствующим тому же местоположению, в котором в настоящее время выполняется код Ion.
Отладка выполняется с помощью динамической деоптимизации:
Мы можем сделать лучше. Мечта 90-х, воплощенная в языке Self, жива в JavaScript. Мы можем адаптировать динамическую деоптимизацию Self с помощью техники замены в стеке для отладки даже оптимизированного кода. Основная идея debug mode OSR
проста: когда требуется отладка, мы деоптимизируем и перекомпилируем JIT-код в стеке, исправляя адреса возврата по мере продвижения. Можно было бы сказать, что это почти элегантно, если бы не жестокое насилие, которое оно наносит стековым фреймам.
Рассмотрим следующую функцию JavaScript:
function foo(o) { return o.f + o.g; }
В этом примере доступ к свойству может привести к чему угодно - от простой загрузки из известных мест в куче до вызовов геттеров или даже сложных ловушек DOM, например, если o
был объектом документа, а f
был имя элемента на странице. Baseline JIT первоначально выполнит эти обращения к свойствам как полностью полиморфную диспетчеризацию. Но при этом он запишет необходимые шаги и затем изменит доступ к куче на месте, чтобы он стал кэшем необходимых шагов для повторения аналогичного доступа в будущем. Например, если объект имеет свойство f
по смещению 16 от основания объекта, код будет изменен, чтобы сначала быстро проверить, состоит ли входящий объект из свойства f
по смещению 16, а затем выполнить нагрузки. Эти кэши называются встроенными, потому что они полностью представлены в виде сгенерированного машинного кода. Говорят, что они полиморфны, потому что, если встречаются различные структуры объектов, машинный код модифицируется для включения ранее встреченных типов объектов перед выполнением полностью динамического поиска свойств. Когда DFG скомпилирует этот код, он проверит, является ли встроенный кэш мономорфным - оптимизирован ли он только для одной объектной структуры - и, если это так, он выдаст только проверку для этой объектной структуры с последующей прямой загрузкой. В этом примере, если o всегда был объектом со свойствами f
и g
с неизменными смещениями, тогда DFG должен был бы выполнить только одну проверку типа для o
, за которой следуют две прямые загрузки.
Ссылки