When perform bitwise operation (bit shift specificly) on js numbers they are casted to int32
, so in theory they must fit in v8's smi
(it must be fast befor 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 casted 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, instaed of performing all operations on uint32?
No, at least not in optimized code.
what if use standart array instad 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.