Релиз V8 v7.9
Каждые шесть недель мы создаем новую ветку V8 в рамках нашего процесса релиза. Каждая версия отделяется от главной ветки Git V8 непосредственно перед выпуском Chrome Beta. Сегодня мы рады объявить о нашей новой ветке, V8 версии 7.9, которая будет в бете до своего релиза в координации с Chrome 79 Stable через несколько недель. V8 v7.9 содержит множество улучшений для разработчиков. Этот пост предоставляет обзор некоторых ключевых моментов в преддверии релиза.
Производительность (размер и скорость)
Удаление устаревания для переходов Double ⇒ Tagged
Вы, возможно, помните из предыдущих записей в блоге, что V8 отслеживает, как представляются поля в формах объектов. Когда представление поля меняется, текущая форма объекта должна быть «устаревшей», и создается новая форма с новым представлением поля.
Исключение составляют случаи, когда старые значения поля гарантированно совместимы с новым представлением. В таких случаях мы можем просто заменить новое представление непосредственно в форме объекта, и оно будет работать для старых значений полей объектов. В V8 v7.6 мы включили эти изменения представления на месте для переходов Smi ⇒ Tagged и HeapObject ⇒ Tagged, но не могли избежать Double ⇒ Tagged из-за нашей оптимизации MutableHeapNumber.
В V8 v7.9 мы избавились от MutableHeapNumber и вместо этого используем HeapNumbers, которые по умолчанию являются изменяемыми, если они принадлежат полю с представлением Double. Это означает, что нам нужно немного внимательнее относиться к работе с HeapNumbers (которые теперь изменяемы, если находятся в поле с представлением Double, и неизменяемы в противном случае), но HeapNumbers совместимы с представлением Tagged, а значит, мы можем также избежать устаревания в случае Double ⇒ Tagged.
Это относительно простое изменение улучшило показатель Speedometer AngularJS на 4%.
Обработка API-геттеров во встроенных функциях
Ранее V8 всегда обращался к C++-runtime при обработке геттеров, определенных встроенным API (например, Blink). Сюда включены геттеры, определенные в спецификации HTML, такие как Node.nodeType
, Node.nodeName
и т.д.
V8 проходил по всей цепочке прототипов во встроенной функции, чтобы загрузить геттер, а затем переходил в runtime, когда обнаруживал, что геттер определен API. В C++-runtime снова проходился по цепочке прототипов, чтобы повторно получить геттер перед его выполнением, дублируя множество операций.
В целом, механизм кеширования на месте (IC) может смягчить это, поскольку V8 устанавливает обработчик IC после первого обращения в C++-runtime. Но с новой ленивой аллокацией обратной связи V8 не устанавливает обработчики IC, пока функция не выполнится несколько раз.
Теперь в V8 v7.9 эти геттеры обрабатываются во встроенных функциях без необходимости перехода в C++-runtime даже в случае отсутствия обработчиков IC, благодаря использованию специальных заглушек API, которые могут обращаться напрямую к геттеру API. Это приводит к 12%-му снижению времени, потраченного на IC runtime, в тестах Backbone и jQuery от Speedometer.
Кэширование OSR
Когда V8 определяет, что определенные функции являются «горячими», он отмечает их для оптимизации при следующем вызове. Когда функция выполняется повторно, V8 компилирует функцию с использованием оптимизирующего компилятора и начинает использовать оптимизированный код с последующего вызова. Однако для функций с длительными циклами этого недостаточно. V8 использует технику, называемую заменой в стеке (OSR), чтобы установить оптимизированный код для текущей выполняемой функции. Это позволяет нам начать использование оптимизированного кода уже при первом выполнении функции, если она застряла в горячем цикле.
Если функция выполняется второй раз, очень вероятно, что OSR сработает снова. До V8 v7.9 нам нужно было повторно оптимизировать функцию для OSR. Однако, начиная с v7.9 мы добавили кэширование OSR, чтобы сохранять оптимизированный код для замен OSR, связанный с заголовком цикла, который использовался как точка входа в функцию OSR. Это улучшило производительность некоторых тестов на пиковую производительность на 5–18%.
WebAssembly
Поддержка нескольких пространств кода
До сих пор каждый модуль WebAssembly состоял ровно из одного пространства кода на 64-битных архитектурах, которое резервировалось при создании модуля. Это позволяло использовать близкие вызовы внутри модуля, но ограничивало нас 128 МБ пространства кода на arm64 и требовало зарезервировать 1 ГБ заранее на x64.
В версии v7.9 V8 появилась поддержка нескольких пространств кода на 64-битных архитектурах. Это позволяет резервировать только оценочное необходимое пространство кода и добавлять дополнительные пространства позже, если это потребуется. Для вызовов между пространствами кода, которые находятся слишком далеко друг от друга для близких переходов, используется дальний переход. Вместо ~1000 модулей WebAssembly на процесс V8 теперь поддерживает несколько миллионов, ограниченных только фактическим доступным объемом памяти.
API V8
Пожалуйста, используйте git log branch-heads/7.8..branch-heads/7.9 include/v8.h
, чтобы получить список изменений в API.
Разработчики с активной копией V8 могут использовать git checkout -b 7.9 -t branch-heads/7.9
, чтобы экспериментировать с новыми функциями в V8 версии v7.9. В качестве альтернативы вы можете подписаться на Beta-канал Chrome и вскоре самостоятельно опробовать новые функции.