When perform bitwise operation (bit shift specifically) on js numbers they are cast to int32
, so in theory they must fit in v8's smi
(it must be fast before jit, and most likely after), but what happens when same operations performed on uint32
?
For example:
const arr = new Uint32Array([0x1]);
arr[0] = ((arr[0] << 31) >>> 0);
(V8 developer here.)
they are cast to
int32
, so in theory they must fit in v8'ssmi
No, Smi range is a signed 31-bit integer (on 32-bit platforms as well as pointer-compressed 64-bit platforms). That doesn't prevent the optimizing compiler from using untagged 32-bit integer values for local values (such as intermediate results, or the values loaded from typed arrays).
does v8 perform unnecessary unsigned right shift?
No, at least not in optimized code.
does v8 perform type casts like uint32 => double => int32 => double => uint32 => double => uint32, or something similar, instead of performing all operations on uint32?
No, at least not in optimized code.
what if use standard array instead of typed one?
Depends on type feedback, i.e. on what kinds of objects/values are in the array, and/or have been in arrays that have been processed at the same source code positions that this array has gone through. Standard arrays never store uint32
values; they'll either store generic tagged values (i.e. the result, having its top bit set, must be boxed as a HeapNumber
), or double values, so you'll get double
-> int32
-> double
conversions.
In summary, the given snippet will be more efficient when you use Uint32Array
s. However, keep in mind that typed arrays have more per-object overhead than regular arrays, so which array type is the overall better choice depends on the rest of your app and can't be decided based on a two-line snippet.