Desabilitando o JIT no Safari 6 para solucionar erros graves de Javascript JIT

Encontramos um problema grave com a interpretação do nosso código Javascript que só ocorre no iOS 5 / Safari 6 (então o lançamento atual do iPad) que achamos que é devido a um bug crítico no compilador Just in Time JS no Safari. (Vejoatualizações abaixo para versões e versões mais afetadas que agora parecem conter uma correção).

Originalmente, encontramos o problema em nosso site on-linedemos de nossa biblioteca: as demos travam mais ou menos aleatoriamente, mas isso acontece apenas na segunda vez (ou até mais tarde) que o mesmo código é executado. Ou seja se você executar a parte do código uma vez, tudo funcionará bem, no entanto, as execuções subseqüentes irão travar o aplicativo.

Interessantemente executando o mesmo código no Chrome para iOS, o problema não aparece, o que acreditamos ser devido aos recursos JIT ausentes do Webview usado no Chrome para iOS.

Depois de muitas tentativas, finalmente achamos que encontramos pelo menos uma parte problemática do código:

  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 

Em essência, este é um loop for simples que atribui a cada célula em uma estrutura de dados de uma lista vinculada seu índice. O problema aqui é a operação pós-incremento no corpo do loop. A contagem atual é atribuída ao campo e atualizada depois que a expressão é avaliada, basicamente o mesmo que primeiro atribuir um e, em seguida, incrementá-lo por um.

Isso funciona bem em todos os navegadores que testamos e no Safari pelas primeiras vezes, e de repente parece que a variável contador a é incrementada primeiro e depois o resultado é atribuído, como uma operação de pré-incremento.

Eu criei um violino que mostra o problema aqui:http://jsfiddle.net/yGuy/L6t5G/

Executando o exemplo em um iPad 2 com iOS 6 e todas as atualizações, o resultado é OK para as primeiras duas execuções no meu caso e na terceira execução idêntica, de repente, o último elemento na lista tem um valor atribuído que está desativado em um quando você clica no botão "clique em mim" muda de "de 0 a 500" para "de 0 a 501")

Curiosamente, se você alternar as guias, ou esperar um pouco, pode acontecer que, de repente, os resultados estejam corretos para duas ou mais corridas! Parece que o Safari às vezes reinicia os caches JIT.

Então, como acho que pode levar muito tempo para a equipe do Safari consertar esse bug (que eu ainda não relatei) e pode haver outros bugs similares, como este escondido no JIT, que são igualmente difíceis de encontrar, eu gostaria de saber se existe uma maneira de desativar a funcionalidade JIT no Safari. É claro que isso desaceleraria nosso código (que já é muito intensivo em CPU), mas é melhor que lento.

AtualizarNão é novidade que não é apenas o operador pós-incremento que é afetado, mas também o operador pós-decremento. Menos surpreendente e mais preocupante é que não faz diferença se o valor é atribuído, então procurar uma atribuição no código existente não é suficiente. Por exemplo. o seguinte o códigob.$f = (a++ % 2 == 0) ? 1 : 2; onde o valor das variáveis ​​não é atribuído, mas apenas usado para a condição do operador ternário, também "falha" no sentido de que, às vezes, o ramo errado é escolhido. Atualmente, parece que o problema só pode ser evitado se os operadores de postagem não forem usados.

Atualizar: O mesmo problema não existe apenas em dispositivos iOS, mastambém no Mac OSX no Safari 6 e o ​​mais recente Safari 5: Foram testados e foram encontrados alguns problemas: Mac OS 10.7.4, Safari 5.1.7 Mac OS X 10.8.2, WebKit Noturno r132968: Safari 6.0.1 (8536.26. 14, 537+). Curiosamente estes fazemnão parece ser afetado: iPad 2 (Mobile) Safari 5.1.7 e iPad 1 Mobile Safari 5.1. Eu relatei esses problemas à Apple, mas ainda não recebi nenhuma resposta.

Atualizar: O bug foi reportado como bug do Webkit109036. A Apple ainda não respondeu ao meu relatório de bug, todas as versões atuais (fevereiro de 2013) do Safari no iOS e MacOS ainda são afetadas pelo problema.

Atualização de 27 de fevereiro de 2013: Parece que o bug foifixo pela equipe do WebkitAqui! Foi realmente um problema com o JIT e os pós-operadores! Os comentários indicam que mais código pode ter sido afetado pelo bug, então pode ser que mais Heisenbugs misteriosos tenham sido corrigidos, agora!

Atualização de outubro de 2013A correção finalmente chegou ao código de produção: iOS 7.0.2, pelo menos no iPad2, não parece mais sofrer desse bug. Eu não verifiquei todas as versões intermediárias, já que trabalhamos em torno do problema há muito tempo.

questionAnswers(3)

yourAnswerToTheQuestion