JS_规范化spidermonkey引擎的目的是什么?
我想知道JS_规范化_NAN的目的是什么,是否所有平台都需要它?这是一个有趣的问题!因此,SpiderMonkey在内部使用标记值表示来表示JavScript的“非类型化值”——这允许VM确定“存储在JS_规范化spidermonkey引擎的目的是什么?,spidermonkey,Spidermonkey,我想知道JS_规范化_NAN的目的是什么,是否所有平台都需要它?这是一个有趣的问题!因此,SpiderMonkey在内部使用标记值表示来表示JavScript的“非类型化值”——这允许VM确定“存储在a中的变量是一个数字,存储在b中的值是一个数字,因此运行a+b进行数字相加” 有一系列不同的值标记方案,SpiderMonkey使用一种称为“NaN-boxing”的方案。这意味着引擎中的所有非类型化值都由64位值表示,这些值可以是: 双人房,或 存在于IEEE双精度浮点值的“NaN空间”中的标记
a
中的变量是一个数字,存储在b
中的值是一个数字,因此运行a+b
进行数字相加”
有一系列不同的值标记方案,SpiderMonkey使用一种称为“NaN-boxing”的方案。这意味着引擎中的所有非类型化值都由64位值表示,这些值可以是:
- 双人房,或
- 存在于IEEE双精度浮点值的“NaN空间”中的标记非双精度浮点值
sqrt(-1)
或log(0)
来观察NaN。但是根据IEEE浮点规范,有很多位模式也被认为是NAN
double由以下子字段组成:
{sign: 1, exponent: 11, significand: 52}
通过在指数字段中填充1并在有效位中放置非零值来表示NaN
如果您运行这样的小程序来查看平台的NaN值:
#include <stdio.h>
#include <math.h>
#include <limits>
static unsigned long long
DoubleAsULL(double d) {
return *((unsigned long long *) &d);
}
int main() {
double sqrtNaN = sqrt(-1);
printf("%5f 0x%llx\n", sqrtNaN, DoubleAsULL(sqrtNaN));
double logNaN = log(-1);
printf("%5f 0x%llx\n", logNaN, DoubleAsULL(logNaN));
double compilerNaN = NAN;
printf("%5f 0x%llx\n", compilerNaN, DoubleAsULL(compilerNaN));
double compilerSNAN = std::numeric_limits<double>::signaling_NaN();
printf("%5f 0x%llx\n", compilerSNAN, DoubleAsULL(compilerSNAN));
return 0;
}
请注意,安静NaN的唯一区别在于符号位,后面总是跟12位1,满足上述NaN要求。最后一个是信令NaN,它清除第12个(is_quiet)NaN位,并使第13个保持上述NaN不变
除此之外,NaN空间可以自由使用--11位来填充指数,确保significand不为零,这样就剩下了很多空间。在x64上,我们使用47位虚拟地址假设,这就为注释值类型留下了64-47-11=6
位。在x86上,所有对象指针都适合低32位
然而,我们仍然需要确保非规范的NaN,如果它们通过js ctypes之类的东西潜入,不会产生类似于标记的非双精度值的东西,因为这可能导致VM中的可利用行为。(将数字视为对象是一个非常坏的消息。)因此,当我们形成DOUBLE(如DOUBLE_TO_JSVAL)时,我们确保规范化d!=d
转换为规范NaN形式
更多信息在这里
-nan 0xfff8000000000000 // Canonical qNaNs...
nan 0x7ff8000000000000
nan 0x7ff8000000000000
nan 0x7ff4000000000000 // sNaN (signaling)