Wyłączanie JIT w Safari 6 w celu obejścia poważnych błędów JavaScript JIT

Znaleźliśmy poważny problem z interpretacją naszego kodu JavaScript, który występuje tylko na iOS 5 / Safari 6 (a następnie na bieżącej wersji iPada), który naszym zdaniem jest spowodowany krytycznym błędem w kompilatorze Just in Time JS w Safari. (Widziećaktualizacje poniżej, aby uzyskać więcej wersji i wersji, które wydają się zawierać poprawkę).

Pierwotnie znaleźliśmy ten problem w naszym Interneciedema naszej biblioteki: dema ulegają awarii mniej lub bardziej losowo, ale zdarza się to tylko drugi raz (lub nawet później), że ten sam kod jest wykonywany. To znaczy. jeśli uruchomisz część kodu raz, wszystko działa poprawnie, jednak kolejne uruchomienia powodują awarię aplikacji.

Co ciekawe, wykonanie tego samego kodu w Chrome na iOS nie powoduje problemu, który naszym zdaniem jest spowodowany brakiem możliwości JIT w przeglądarce internetowej, która jest używana w Chrome na iOS.

Po wielu manipulacjach w końcu myślimy, że znaleźliśmy co najmniej jeden problematyczny fragment kodu:

  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 

W istocie jest to prosta pętla for, która przypisuje każdej komórce strukturę danych połączonej listy swój indeks. Problemem jest tutaj operacja po inkrementacji w ciele pętli. Bieżąca liczba jest przypisana do pola i aktualizowana po oszacowaniu wyrażenia, zasadniczo tak samo jak przy pierwszym przypisaniu a, a następnie zwiększeniu o jeden.

Działa to poprawnie we wszystkich przeglądanych przez nas przeglądarkach oraz w Safari przez kilka pierwszych chwil, a potem nagle wydaje się, że zmienna licznika a jest najpierw zwiększana, a następnie wynik jest przypisywany, tak jak operacja przed przyrostem.

Stworzyłem skrzypce, które pokazuje problem tutaj:http://jsfiddle.net/yGuy/L6t5G/

Uruchamianie przykładu na iPadzie 2 z systemem iOS 6 i wszystkimi aktualizacjami wynik jest OK dla pierwszych 2 przebiegów w moim przypadku, aw trzecim przebiegu identycznym nagle ostatni element na liście ma przypisaną wartość, która jest wyłączona o jeden (wynik po kliknięciu przycisku „kliknij mnie” zmienia się z „od 0 na 500” na „od 0 do 501”)

Co ciekawe, jeśli przełączysz karty lub poczekasz chwilę, może się zdarzyć, że nagle wyniki będą poprawne dla dwóch lub więcej przebiegów! Wygląda na to, że Safari czasami resetuje pamięć podręczną JIT.

Odkąd myślę, że naprawienie tego błędu przez zespół Safari może zająć bardzo dużo czasu (czego jeszcze nie zgłosiłem) i mogą istnieć inne podobne błędy, takie jak czające się w JIT, które są równie trudne do znalezienia, chciałbym wiedzieć, czy istnieje sposób na wyłączenie funkcji JIT w Safari. Oczywiście spowolniłoby to nasz kod (który jest już bardzo obciążający procesor), ale lepiej wolniej niż zawieszenie.

Aktualizacja: Nic dziwnego, że nie dotyczy to tylko operatora przyrostu postu, ale także operatora post-dekrementacji. Mniej zaskakujące i bardziej niepokojące jest to, że nie ma znaczenia, czy wartość jest przypisana, więc szukanie przypisania w istniejącym kodzie nie wystarczy. Na przykład. następujący kodb.$f = (a++ % 2 == 0) ? 1 : 2; gdzie wartość zmiennych nie jest przypisana, ale używana tylko dla warunku operatora trójskładnikowego, również „zawiedzie” w tym sensie, że czasami wybierana jest niewłaściwa gałąź. Obecnie wygląda na to, że problemu można uniknąć tylko wtedy, gdy operatorzy pocztowi nie są w ogóle wykorzystywani.

Aktualizacja: Ten sam problem występuje nie tylko w urządzeniach z systemem iOS, aletakże na Mac OSX w Safari 6 i najnowszym Safari 5: błąd został przetestowany i wykryty pod kątem błędu: 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+). Co ciekawe, robią tonie dotyczy to: iPad 2 (Mobile) Safari 5.1.7 i iPad 1 Mobile Safari 5.1. Zgłaszałem te problemy firmie Apple, ale jeszcze nie otrzymałem żadnej odpowiedzi.

Aktualizacja: Błąd został zgłoszony jako błąd Webkit109036. Firma Apple nadal nie odpowiedziała na mój raport o błędzie, wszystkie aktualne (luty 2013) wersje Safari na iOS i MacOS nadal są dotknięte problemem.

Aktualizacja 27 lutego 2013 r: Wygląda na to, że błąd byłnaprawiony przez zespół Webkittutaj! To był rzeczywiście problem z JIT i post-operatorami! Komentarze wskazują, że błąd mógł wpłynąć na więcej kodu, więc może być tak, że więcej tajemniczych Heisenbugów zostało naprawionych!

Aktualizacja października 2013 r: Poprawka ostatecznie przekształciła się w kod produkcyjny: iOS 7.0.2 przynajmniej na iPad2 nie wydaje się już cierpieć na ten błąd. Nie sprawdziłem jednak wszystkich wersji pośrednich, ponieważ pracowaliśmy nad tym problemem już dawno temu.

questionAnswers(3)

yourAnswerToTheQuestion