Closed thlorenz closed 6 years ago
V8 integer sizes:
Outside these ranges, numbers are represented as boxed doubles (in special case like locals of optimized code, pure float arrays, doubles are stored immediately)
Test could be like
var assert = require("assert");
function IsInteger(val) {
return %_IsSmi(val);
}
var is64Bit = /64/.test(process.arch);
var min, max;
if (is64Bit) {
min = -2147483648;
max = 2147483647;
} else {
min = -1073741824;
max = 1073741823;
}
assert(IsInteger(min));
assert(IsInteger(max));
assert(!IsInteger(min - 1));
assert(!IsInteger(max + 1));
Thanks @petkaantonov, will add this as a test tomorrow.
The origin of the discussion however was how do you get a unsigned long long
from the C++ layer to the JavaScript layer since I ran into that problem.
Seems like the verdict is to use a string in the situations where the number value exceeds a long
(32-bit) and thus cannot be represented as a floating point number on the JS side. But if it's small enough just convert it to unit32_t
.
@petkaantonov I added the test along with some explanation about how the min
and max
values come about.
I'm a bit confused regarding the min/max values on a 64-bit
architecture though.
I was under the impression that SMIs would be represented the same way no matter what the architecture (with 31-bits
+ 1 bit for the tag).
However if they are represented differently I'd expect the following:
64-bit slot separation to hold a signed integer:
- 1 bit to tag it as value
- 1 bit for sign
- 62 bits for actual value
However 2147483647
is just the max of a signed 31-bit
value (just one bit more than on a 32-bit
architecture).
I would have expected it to be much larger:
pad > Math.pow(2, 62)
4611686018427388000
Could you explain why that is so?
On x64 Smis are 32-bit signed integers represented at higher half of 64bit value: tagged(x) = x << 32
, untag(y) = y >> 32
.
This was one of the things I wanted to leave a comment on, but my hands did not get to it.
Also in JS you don't have any use for 63-bit integer values because numeric type is double which has 53-bit of integer precision.
@mraleph thanks for the info, I'll add that to the comments in the test.
Also in JS you don't have any use for 63-bit integer values because numeric type is double which has 53-bit of integer precision.
I need to add this kind of info to the data-types section. Do you have any links to some resource that explains this in detail @mraleph?
I doubt there is anything beyond some comments in V8, like this (somewhat confusing, I must admit) one from objects.h
// Smi represents integer Numbers that can be stored in 31 bits.
// Smis are immediate which means they are NOT allocated in the heap.
// The this pointer has the following format: [31 bit signed int] 0
// For long smis it has the following format:
// [32 bit signed int] [31 bits zero padding] 0
// Smi stands for small integer.
Thanks. I guess I could also glean some more JavaScript specific info from the ECMA Spec.
Ah I misunderstood the question. If you were tallking about number type in JavaScript then ECMA-262 is indeed what you should read, though there is not much there except definition 4.3.12 that defined number as "primitive value corresponding to a double-precision 64-bit binary format IEEE 754 value."
The rest follows from the way doubles work and the size of mantissa (53-bits).
@mraleph totally fine the other info was useful as well and has been added to the test. I'll read up on the spec to get the JS limits specific info.
From discussion on irc -- we need links: