Skip to content

Instantly share code, notes, and snippets.

@dlongley
Last active October 30, 2016 01:47
Show Gist options
  • Save dlongley/5b1f4284922ec0deac9abbed5665c7ed to your computer and use it in GitHub Desktop.
Save dlongley/5b1f4284922ec0deac9abbed5665c7ed to your computer and use it in GitHub Desktop.
Safari 10 optimization bug
<html>
<head>
<title>Safari 10 Optimization Bug</title>
</head>
<body>
<h1>Safari 10 Optimization Bug</h1>
<p>This test reveals an optimization bug in Safari 10. A
deterministic function is run in a loop. Its first return
value is stored and printed to the screen. If any subsequent
turn of the loop produces a different return value, the
test exits immediately and prints the different value.
</p>
<p>This test passes successfully on Chrome, Firefox, and
early versions of Safari (less than v10). It fails on
Safari 10. You may need to refresh the page a few times
to get a failure, but it typically fails every time.
</p>
<div>Attempt: <span id="iteration">...</span></div>
<div>First result is <span id="expected">...</span></div>
<div>Final result
<span id="result">matches first result.<br>
<span style="color: green">SUCCESS!</span></span>
</div>
<script>
var expected;
var attempts = 5;
for(var x = 0; x < attempts; ++x) {
if(!_runTest(x, 100)) {
break;
}
}
function _runTest(attempt, max) {
for(var itr = 0; itr < max; ++itr) {
var s = {
a: 0,
b: 0,
c: 0x80000000, // setting to anything less avoids the bug
d: 0,
e: 0
};
for(var i = 0; i < 15000; ++i) {
var t, a, b, c, d, e;
a = s.a;
b = s.b;
c = s.c;
d = s.d;
e = s.e;
for(var j = 0; j < 2; ++j) {
t = a + e;
e = d;
// uncommenting line below with `>>> 0` will avoid the bug
//c = c >>> 0;
d = c;
c = (b >>> 1);
b = a;
a = t;
}
s.a = a | 0;
s.b = b | 0;
s.c = c | 0;
s.d = d | 0;
s.e = e | 0;
}
// compute the result
var result = Object.keys(s).reduce(function(a, b) {
return a + (s[b] >>> 0).toString(16);
}, '');
// display and result comparison
document.getElementById('iteration').innerHTML =
(attempt + 1) + ', Iteration ' + (itr + 1) + ' / ' + max;
if(attempt === 0 && itr === 0) {
expected = result;
document.getElementById('expected').innerHTML = expected;
} else if(result !== expected) {
var output = {iteration: itr, result: result};
document.getElementById('result').innerHTML =
' is ' + output.result + '<br>' +
'<span style="color: red">FAILURE!</span> ' +
'Final result does not match first result.';
return false;
}
}
return true;
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment