Перейти к основному содержимому

Релиз V8 v8.6

· 6 мин. чтения
Ингвар Степанян ([@RReverser](https://twitter.com/RReverser)), тестировщик клавиатуры

Каждые шесть недель мы создаем новую ветку V8 в рамках нашего процесса релиза. Каждая версия создаётся из главной ветки Git V8 незадолго до этапа Beta Chrome. Сегодня мы рады сообщить о нашей новой ветке, V8 версии 8.6, которая находится в бета-версии до её релиза в сотрудничестве с Chrome 86 Stable через несколько недель. V8 v8.6 наполнен множеством полезных функций для разработчиков. Этот пост предоставляет предварительный обзор некоторых ключевых моментов в преддверии релиза.

Уважительный код

Версия v8.6 делает кодовую базу V8 более уважительной. Команда присоединилась к усилиям по всему Chromium, чтобы следовать обязательствам Google по расовому равенству, заменяя некоторые некорректные термины в проекте. Эта работа все еще продолжается, и любой сторонний участник может внести свой вклад! Вы можете увидеть список доступных задач здесь.

JavaScript

Открытый исходный код JS-Fuzzer

JS-Fuzzer — это основанный на мутациях JavaScript-фаззер, изначально написанный Оливером Чангом. Он был основой стабильности и безопасности V8 в прошлом и теперь имеет открытый исходный код.

Фаззер изменяет существующие тестовые случаи междвижковой совместимости, используя Babel AST-трансформации, настроенные с помощью расширяемых классов-мутаций. Мы недавно также начали запускать экземпляр фаззера в режиме дифференциального тестирования для обнаружения проблем точности JavaScript. Добро пожаловать к участию! Ознакомьтесь с README для получения дополнительной информации.

Ускорение Number.prototype.toString

Преобразование числа JavaScript в строку может быть удивительно сложной операцией в общем случае; необходимо учитывать точность с плавающей запятой, научную нотацию, NaN, бесконечности, округления и так далее. Мы даже не знаем, насколько большая строка будет получена, пока не вычислим её. Из-за этого наша реализация Number.prototype.toString вызывала функцию времени выполнения на C++.

Однако зачастую требуется просто вывести простое маленькое целое число ("Smi"). Это намного более простая операция, и затраты на вызов функции времени выполнения C++ уже не оправданы. Поэтому мы с нашими друзьями из Microsoft добавили простой быстрый путь для маленьких целых чисел в Number.prototype.toString, написанный на Torque, чтобы уменьшить эти издержки для этого распространенного случая. Это улучшило скорость микробенчмарков печати чисел на ~75%.

Удаление Atomics.wake

Atomics.wake был переименован в Atomics.notify в соответствии с изменением спецификации в v7.3. Устаревший псевдоним Atomics.wake теперь удален.

Небольшие нормативные изменения

WebAssembly

SIMD на Liftoff

Liftoff является базовым компилятором для WebAssembly, и начиная с V8 версии 8.5 он доступен на всех платформах. Предложение SIMD позволяет WebAssembly использовать доступные аппаратные векторные инструкции для ускорения вычислительных задач с высокой нагрузкой. В настоящее время оно находится в Origin Trial, что позволяет разработчикам экспериментировать с функцией до ее стандартизации.

До настоящего времени SIMD был реализован только в TurboFan, компиляторе высшего уровня V8. Это необходимо для достижения максимальной производительности инструкций SIMD. Модули WebAssembly, которые используют инструкции SIMD, будут иметь более быстрое время запуска и часто более высокую производительность во время выполнения по сравнению с их скалярными эквивалентами, скомпилированными с помощью TurboFan. Например, рассмотрим функцию, которая принимает массив чисел с плавающей точкой и ограничивает его значения нулем (написано здесь на JavaScript для ясности):

function clampZero(f32array) {
for (let i = 0; i < f32array.length; ++i) {
if (f32array[i] < 0) {
f32array[i] = 0;
}
}
}

Сравним два разных варианта реализации этой функции, используя Liftoff и TurboFan:

  1. Скалярная реализация с развертыванием цикла 4 раза.
  2. Реализация SIMD, использующая инструкцию i32x4.max_s.

Используя скалярную реализацию Liftoff в качестве базовой линии, мы получаем следующие результаты:

График, показывающий, что Liftoff SIMD примерно в 2,8 раза быстрее, чем Liftoff scalar, против TurboFan SIMD, который примерно в 7,5 раза быстрее

Более быстрые вызовы Wasm-to-JS

Если WebAssembly вызывает импортированную функцию JavaScript, мы используем так называемый «обертку Wasm-to-JS» (или «обертку импорта»). Эта обертка преобразует аргументы в объекты, которые понимает JavaScript, а когда вызов JavaScript возвращается, она преобразует возвращаемое значение(я) в WebAssembly.

Чтобы обеспечить, что объект аргументов JavaScript точно отражает аргументы, переданные из WebAssembly, мы используем так называемый «адаптер аргументов» в случаях, когда обнаруживается несоответствие в количестве аргументов.

Но во многих случаях этого не требуется, потому что вызываемая функция не использует объект arguments. В версии v8.6 мы добавили исправление от наших разработчиков Microsoft, которое позволяет избежать вызова через адаптер аргументов в таких случаях, что делает вызовы значительно быстрее.

API V8

Обнаружение фоновых задач в ожидании с помощью Isolate::HasPendingBackgroundTasks

Новая функция API Isolate::HasPendingBackgroundTasks позволяет встроенным разработчикам проверять наличие фоновых задач, которые в конечном итоге приведут к запуску новых задач на переднем плане, таких как компиляция WebAssembly.

Этот API должен решить проблему, когда внедренное приложение завершает работу V8, хотя есть еще не завершенная компиляция WebAssembly, которая в конечном итоге запустит дальнейшее выполнение скрипта. С помощью Isolate::HasPendingBackgroundTasks внедренное приложение может ожидать новые задачи на переднем плане вместо завершения работы V8.

Используйте git log branch-heads/8.5..branch-heads/8.6 include/v8.h для получения списка изменений в API.

Разработчики с активной копией V8 могут использовать git checkout -b 8.6 -t branch-heads/8.6 для экспериментов с новыми функциями в версии V8 v8.6. Кроме того, вы можете подписаться на бета-канал Chrome и в ближайшее время самостоятельно опробовать новые функции.