Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Something wrong with javascript unsigned shift operator on iPad?

I accidentally ran into what appears to be a very strange bug in Safari's javascript engine on iPad.

The unsigned shift operator >>> is supposed to bitwise right-shift a number. I experienced some errors in a script that worked fine on other platforms, stripped it down and ended up with this:

<html><head><script type='text/javascript'>

var one = 1;

function Zero()
{
    return one*0;
}

function Strange()
{
     return one = (Zero()+1) >>> 0;
}

var s = 'A bunch of ones: '; // except on iPad :(
for (var i=0; i<200; i++) 
{
     s += Strange()+' ';
}
document.write(s);

</script></head><body></body></html>

Live demo

Strangely enough, it correctly generates a bunch of ones, but at a certain point, something breaks and it only outputs zeroes from then on.

Obviously the >>> 0 is meaningless here (a shift over zero places typically does nothing, although it could have forced an integer to become unsigned if javascript made that distinction). It's just to demonstrate the problem, if you omit the >>> 0 it doesn't show up. In my actual situation there were different numbers and more complex expressions involved, but the same thing happened: everything works until a number of iterations, then something 'breaks' and variables suddenly become and remain zero, even after subsequent calculations that really ought to make them non-zero.

Works fine on Android and PC browsers. Strange huh?

like image 488
Rogier Avatar asked Oct 14 '13 10:10

Rogier


People also ask

How does unsigned shift operator work?

The unsigned right shift operator ( >>> ) (zero-fill right shift) evaluates the left-hand operand as an unsigned number, and shifts the binary representation of that number by the number of bits, modulo 32, specified by the right-hand operand.

What is << operator in Javascript?

The left shift operator ( << ) shifts the first operand the specified number of bits, modulo 32, to the left. Excess bits shifted off to the left are discarded. Zero bits are shifted in from the right.

What are signed and unsigned shift operators?

For unsigned numbers, the bit positions that have been vacated by the shift operation are zero-filled. For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used.

What does the operator do a zero fill right shift b right shift operator C Zero Fill Left Shift D left shift operator?

Zero-fill right shift (>>>) operator: The operator shifts the bits of the first operand by a number of bits specified by the second operand. The bits are shifted to the right and those excess bits are discarded, while 0 bit is added from left.


1 Answers

Not a "real" answer but perhaps a useful one, assuming (as seems VERY likely) that this is simply a bug in Apple's JIT compiler: This StackOverflow thread (Disabling JIT in Safari 6 to workaround severe Javascript JIT bugs) talks about how to disable the JIT on your code. Basically,

Wrap the offending statement in a do-nothing try-catch block.

I don't have an iOS device to test on, but does this make the problem go away? Can you apply the same kind of workaround to your original code?

function Strange()
{
    try
    {
        return one = (Zero()+1) >>> 0;
    }
    catch (e) { throw e }
}
like image 161
Quuxplusone Avatar answered Oct 20 '22 15:10

Quuxplusone