在Safari 6中禁用JIT以解决严重的Javascript JIT错误 [英] Disabling JIT in Safari 6 to workaround severe Javascript JIT bugs

查看:100
本文介绍了在Safari 6中禁用JIT以解决严重的Javascript JIT错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们发现仅在iOS 5/Safari 6(当时为当前的iPad版本)上出现的Java语言代码解释存在严重问题,我们认为这是由于Safari中的Just in Time JS编译器中的严重错误所致. (有关更多受影响的版本以及现在看来包含修复程序的版本,请参见下面的更新.

We found a severe problem with the interpretation of our Javascript code that only occurs on iOS 5/Safari 6 (then current iPad release) that we think is due to critical bug in the Just in Time JS compiler in Safari. (See updates below for more affected versions and versions that seem to now contain a fix).

我们最初是在我们库的在线 demos 中发现了该问题:演示崩溃或多或少是随机的,但这仅在第二次(甚至更晚)执行同一代码时才会发生. IE.如果您只运行部分代码,则一切正常,但是随后的运行会使应用程序崩溃.

We originally found the issue in our online demos of our library: the demos crash more or less randomly but this happens only the second time (or even later) that the same code is executed. I.e. if you run the part of the code once, everything works OK, however subsequent runs crash the application.

有趣的是,在iOS版Chrome中执行相同的代码并未显示该问题,我们认为这是由于iOS版Chrome中使用的Webview缺少了JIT功能.

Interestingly executing the same code in Chrome for iOS the problem does not show, which we believe is due to the missing JIT capabilities of the Webview that is used in Chrome for iOS.

经过反复摆弄,我们最终认为我们至少找到了一个有问题的代码段:

After a lot of fiddling we finally think we found at least one problematic piece of code:

  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然后再将其递增1相同.

In essence this is a simple for loop that assigns each cell in a linked list data structure its index. The problem here is the post-increment operation in the loop body. The current count is assigned to the field and updated after the expression is evaluated, basically the same as first assigning a and then incrementing it by one.

这在我们测试过的所有浏览器和Safari中第一次都可以正常工作,然后突然之间,好像计数器变量a先增加然后分配结果,就像预递增操作一样.

This works OK in all browsers we tested and in Safari for the first couple of times, and then suddenly it seems as if the counter variable a is incremented first and then the result is assigned, like a pre-increment operation.

我创建了一个小提琴,该小提琴在此处显示了问题: http://jsfiddle.net/yGuy/L6t5G/

I have created a fiddle that shows the problem here: http://jsfiddle.net/yGuy/L6t5G/

在装有iOS 6的iPad 2上运行示例并进行所有更新,对于我而言,前两次运行的结果都正常,而在第三次相同的运行中,列表中的最后一个元素突然分配的值被一个偏移了一个(当您单击单击我"按钮时,输出从从0到500"更改为从0到501")

Running the example on an iPad 2 with iOS 6 and all updates the result is OK for the first 2 runs in my case and in the third identic run suddenly the last element in the list has a value assigned that is off by one (the output when you click the "click me" button changes from "from 0 to 500" to "from 0 to 501")

有趣的是,如果您切换选项卡或稍等片刻,可能会突然发现两次或更多次运行的结果都是正确的!似乎Safari有时会重置为JIT缓存.

Interestingly if you switch tabs, or wait a little it can happen that suddenly the results are correct for two or so more runs! It seems as if Safari sometimes resets is JIT caches.

因此,由于我认为Safari团队可能需要很长时间才能解决此错误(我尚未报告),并且可能存在其他类似的类似错误也很难在JIT中找到,所以我想知道是否有一种方法可以禁用Safari中的JIT功能.当然,这会使我们的代码变慢(这已经非常占用CPU了),但是比崩溃更慢.

So since I think it may take a very long for the Safari team to fix this bug (which I have not yet reported) and there may be other similar bugs like this lurking in the JIT that are equally hard to find, I would like to know whether there is a way to disable the JIT functionality in Safari. Of course this would slow down our code (which is very CPU intensive already), but better slow than crashing.

更新: 毫不奇怪,受影响的不仅是职位增减运算符,还包括职位增减运算符.毫不奇怪,更令人担忧的是,如果分配了值,则没有任何区别,因此在现有代码中寻找分配是不够的.例如.在代码b.$f = (a++ % 2 == 0) ? 1 : 2;之后的代码中,未分配变量值而仅用于三元运算符条件的代码在某些时候选择了错误的分支的意义上也失败".目前看来,只有在根本不使用post运算符的情况下,才可以避免该问题.

Update: Unsurprisingly it's not just the post increment operator that is affected, but also the post decrement operator. Less surprisingly and more worryingly is that it makes no difference if the value is assigned, so looking for an assignment in existing code is not enough. E.g. the following the code b.$f = (a++ % 2 == 0) ? 1 : 2; where the variables value is not assigned but just used for the ternary operator condition also "fails" in the sense that sometimes the wrong branch is chosen. Currently it looks as if the problem can only be avoided if the post operators are not used at all.

更新: 相同的问题不仅在iOS设备中存在,而且在Safari 6和最新的Safari 5中在Mac OSX中也存在: 这些已经过测试,发现受此错误影响: 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+).有趣的是,这些 not 似乎没有受到影响:iPad 2(移动版)Safari 5.1.7和iPad 1移动版Safari 5.1.我已向Apple报告了这些问题,但尚未收到任何答复.

Update: The same issue does not only exist in iOS devices, but also on Mac OSX in Safari 6 and the latest Safari 5: These have been tested and found to be affected by the bug: 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+). Interestingly these do not seem to be affected: iPad 2 (Mobile) Safari 5.1.7, and iPad 1 Mobile Safari 5.1. I have reported these problems to Apple but have not received any response, yet.

更新: 该错误已报告为Webkit错误 109036 . Apple仍未回复我的错误报告,该问题仍影响iOS和MacOS上的所有当前(2013年2月)Safari版本.

Update: The bug has been reported as Webkit bug 109036. Apple still has not responded to my bug report, all current (February 2013) Safari versions on iOS and MacOS are still affected by the problem.

2013年2月27日更新: 该漏洞似乎已由Webkit团队在此处 已修复! JIT和后操作员确实存在问题!这些注释表明该错误可能影响了更多代码,因此,现在可能已修复了更多神秘的Heisenbug!

Update 27th of February 2013: It seems the bug has been fixed by the Webkit team here! It was indeed a problem with the JIT and the post-operators! The comments indicate that more code might have been affected by the bug, so it could be that more mysterious Heisenbugs have been fixed, now!

2013年10月更新: 该修复程序最终将其纳入了生产代码:至少在iPad2上的iOS 7.0.2似乎不再受此错误困扰.不过,由于我们很早以前就解决了这个问题,所以我没有检查所有的中间版本.

Update October 2013: The fix finally made it into production code: iOS 7.0.2 at least on iPad2 does not seem to suffer from this bug anymore. I did not check all of the intermediate versions, though, since we worked around the problem a long time ago.

推荐答案

Try-catch块似乎禁用了Lion上Safari 6上的JIT编译器,直接位于try块内(

Try-catch blocks seem to disable the JIT compiler on Safari 6 on Lion for the part directly inside the try block (this code worked for me on Safari 6.0.1 7536.26.14 and OS X Lion).

// test function
utility.test = function(){
    try {
        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
    }
    catch (e) { throw e }
    this.$f5 = !1; // random code
};

这至少是当前版本的Google V8的记录在案的行为(请参见有关V8的Google I/O演示文稿),但我不了解Safari.

This is at least a documented behavior of the current version of Google's V8 (see the Google I/O presentation on V8), but I don't know for Safari.

如果要对整个脚本禁用它,一种解决方案是编译JS,以使用

If you want to disable it for the whole script, one solution would be to compile your JS to wrap every function's content inside a try-catch with a tool such as burrito.

做好这一可重复性工作!

Good job on making this reproducible!

这篇关于在Safari 6中禁用JIT以解决严重的Javascript JIT错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆