Отключение JIT в Safari 6 для обхода серьезных ошибок JIT Javascript

Мы обнаружили серьезную проблему с интерпретацией нашего кода Javascript, которая встречается только в iOS 5 / Safari 6 (тогда - выпуск iPad), что, по нашему мнению, связано с критической ошибкой в компиляторе Just in Time JS в Safari. (Видетьобновления ниже для более уязвимых версий и версий, которые, кажется, теперь содержат исправление).

Мы изначально нашли проблему в нашем онлайндемос из нашей библиотеки: демонстрации более или менее случайны, но это происходит только во второй раз (или даже позже), когда выполняется тот же код. То есть если вы выполняете часть кода один раз, все работает нормально, однако последующие запуски приводят к сбою приложения

Интересно, что при выполнении того же кода в Chrome для iOS проблема не проявляется, что, по нашему мнению, связано с отсутствующими возможностями JIT в Webview, который используется в Chrome для iOS.

После долгих хлопот мы наконец-то подумали, что нашли хотя бы один проблемный фрагмент кода:

  var a = 0; // counter for index
  for (var b = this.getStart(); b !== null; b = b.getNext()) // iterate over all cells
    b.$f = a++; // assign index to cell and then increment 

По сути, это простой цикл for, который присваивает каждой ячейке в структуре данных связанного списка свой индекс. Проблема здесь - операция постинкремента в теле цикла. Текущий счетчик присваивается полю и обновляется после вычисления выражения, в основном, так же, как сначала присваивание a, а затем увеличение его на единицу.

Это работает нормально во всех браузерах, которые мы тестировали, и в Safari первые пару раз, а затем внезапно создается впечатление, что переменная счетчика a сначала увеличивается, а затем присваивается результат, как операция предварительного увеличения.

Я создал скрипку, которая показывает проблему здесь:http://jsfiddle.net/yGuy/L6t5G/

При запуске примера на iPad 2 с iOS 6 и всеми обновлениями результат в порядке для первых 2 запусков в моем случае, и при третьем прогоне идентично внезапно последний элемент в списке имеет присвоенное значение, которое выключено на единицу (выход при нажатии кнопки «Нажми меня» изменится с «от 0 до 500» на «с 0 до 501»)

Интересно, что если вы переключаете вкладки или немного ждете, может случиться так, что неожиданно результаты окажутся правильными для двух или более прогонов! Кажется, что Safari иногда сбрасывает JIT-кэши.

Так как я думаю, что команде Safari может потребоваться очень много времени, чтобы исправить эту ошибку (о которой я еще не сообщал), и могут быть другие подобные ошибки, подобные этой, скрывающиеся в JIT, которые одинаково трудно найти, я хотел бы знать, есть ли способ отключить функциональность JIT в Safari. Конечно, это замедлило бы наш код (который уже сильно загружает процессор), но лучше, чем сбой.

ОбновитьНеудивительно, что это касается не только оператора постинкремента, но также и оператора посткремента. Менее удивительно и более тревожно то, что не имеет значения, назначено ли значение, поэтому поиск присваивания в существующем коде недостаточно. Например. следующий кодb.$f = (a++ % 2 == 0) ? 1 : 2; где значение переменных не присваивается, а просто используется для условия троичного оператора, также «терпит неудачу» в том смысле, что иногда выбирается неправильная ветвь. В настоящее время похоже, что проблемы можно избежать, только если почтовые операторы вообще не используются.

Обновить: Та же проблема существует не только на устройствах iOS, но итакже на Mac OSX в Safari 6 и последней версии Safari 5: они были проверены и обнаружены ошибки: Mac OS 10.7.4, Safari 5.1.7 Mac OS X 10.8.2, WebKit Nightly r132968: Safari 6.0.1 (8536.26. 14, 537+). Интересно это сделатьне похоже, что это затронуто: iPad 2 (Mobile) Safari 5.1.7 и iPad 1 Mobile Safari 5.1. Я сообщил об этих проблемах в Apple, но пока не получил никакого ответа.

Обновить: Ошибка сообщается как ошибка Webkit109036, Apple до сих пор не отреагировала на мое сообщение об ошибке, и все текущие (февраль 2013 года) версии Safari для iOS и MacOS все еще подвержены этой проблеме.

Обновление 27 февраля 2013: Похоже ошибка былаисправлено команда WebkitВот! Это была действительно проблема с JIT и пост-операторами! В комментариях указывается, что ошибка могла повлиять на большее количество кода, поэтому возможно, что теперь было исправлено больше загадочных гейзенгов!

Обновление октябрь 2013Исправление, наконец, превратило его в рабочий код: iOS 7.0.2, по крайней мере, на iPad2, похоже, больше не страдает от этой ошибки. Однако я не проверил все промежуточные версии, так как мы давным-давно решили эту проблему.

Ответы на вопрос(3)

Ваш ответ на вопрос