Javascript asm.js如何处理被零除的问题?

Javascript asm.js如何处理被零除的问题?,javascript,asm.js,Javascript,Asm.js,在javascript中,使用“整数”参数除以零的行为类似于浮点,应该: 1/0; // Infinity -1/0; // -Infinity 0/0; // NaN js规范指出,带整数参数的除法返回intish,必须立即强制为有符号或无符号。如果我们在javascript中执行此操作,则使用“整数”参数除以零后,在协同运算后始终返回零: (1/0)|0; // == 0, signed case. (1/0) >> 0; // == 0, unsi

在javascript中,使用“整数”参数除以零的行为类似于浮点,应该:

 1/0;    // Infinity
-1/0;    // -Infinity
 0/0;    // NaN
js规范指出,带整数参数的除法返回
intish
,必须立即强制为有符号或无符号。如果我们在javascript中执行此操作,则使用“整数”参数除以零后,在协同运算后始终返回零:

(1/0)|0;    // == 0, signed case.
(1/0) >> 0; // == 0, unsigned case.
然而,在具有实际整数类型的语言(如Java和C)中,整数除以零是一个错误,执行会以某种方式停止(例如抛出异常、触发陷阱等)

这似乎也违反了asm.js指定的类型签名。
Infinity
NaN
的类型是
double
,而
/
的类型应该是(根据规范):

(签名,签名)→ 英蒂什∧ (未签名,未签名)→ 英蒂什∧ (双倍?,双倍?)→ 双重的∧ (浮动?,浮动?)→ 漂浮的

但是,如果其中任何一个分母为零,则结果为
double
,因此该类型似乎只能是:

(双倍?,双倍?)→ 双重的


在asm.js代码中预期会发生什么?它是否遵循javascript并返回0,还是被零除会产生运行时错误?如果它遵循javascript,为什么输入错误是可以的?如果它产生运行时错误,为什么规范没有提到它呢?

asm.js是JavaScript的一个子集,因此它必须返回JavaScript的功能:
Infinity | 0
→ <代码>0

您指出,
Infinity
double
,但它将asm.js类型系统与C类型系统(在JavaScript中是
number
)混为一谈:asm.js使用JavaScript类型强制使中间结果成为“正确”类型,而不是。当JavaScript中的一个小整数溢出到一个
double
时,也会发生同样的情况:它会使用位操作强制返回到一个整数

这里的关键是它给编译器一个提示,它不需要计算JavaScript通常让它计算的所有内容:小整数是否溢出并不重要,因为它被强制返回到整数,因此编译器可以省略溢出检查并发出直线整数算术。请注意,对于每个可能的值,它仍然必须正确运行!类型系统基本上提示编译器进行一系列强度缩减

现在回到整数除法:在x86上,这会导致浮点异常(是的!整数除法导致
SIGFPE
!)。编译器知道输出是一个整数,因此可以进行整数除法,但如果分母为零,则无法停止程序。这里有两个选项:

  • 如果输入为零,则围绕除法分支,并直接返回零
  • 使用提供的输入进行除法,但在程序开始时安装一个信号处理程序,捕捉
    SIGFPE
    。当它出错时,查找代码位置,如果编译器的元数据说这是一个除法位置,则将返回值修改为零并继续执行
前者是V8和OdinMonkey实现的

在ARM上,整数除法指令定义为始终返回零,但ARM的ARMv7-R配置文件出现故障时除外(故障为未定义指令,或者如果
SCTRL.DZ==0
,则可以更改为返回零)。ARM最近仅在ARMv7VE扩展(虚拟化扩展)中添加了
UDIV
SDIV
指令,并使其在ARMv7-A处理器中成为可选的(大多数手机和平板电脑都使用这些指令)。您可以使用
/proc/cpuinfo
检查该指令,但请注意,有些内核不知道该指令!解决方法是在进程启动时检查指令,方法是执行指令并使用
sigsetjmp
/
siglongjmp
捕获未处理的情况。这还有一个进一步的警告,即在不支持内核的处理器上捕获内核“有用”和模拟
UDIV
/
IDIV
的情况!如果指令不存在,则必须使用C库的整数除法指令(
libgcc
compiler\u rt
包含
\u udivmoddi4
等函数)。请注意,此函数在除以零上的行为可能因实现而异,必须使用零分母上的分支进行处理或在加载时进行检查(与上文针对
UDIV
/
SDIV
所述相同)


我想问你一个问题:当执行以下C代码时,asm.js中会发生什么:
INT_MIN/-1

因此,这里的一般原则是,asm.js继承所有js语义和额外的数字类型,并由针对asm.js的编译器在这些类型之上实现其语言的语义(例如C)<代码>INT_MIN/-1在C中未定义,但在截断后的asm.js中它又是INT_MIN(有符号溢出),而且由于行为在C中未定义,所以这没问题?@FrancisAvila有两个编译器:从C/C++生成asm.js代码的LLVM,以及从JavaScript生成汇编的SpiderMonkey/V8。SpiderMonkey有一个有效asm.js代码的快捷方式(OdinMonkey),但该快捷方式仍然必须是100%有效的JavaScript。V8与TurboFan做了类似的事情,但它不验证asm.js子集(只需“使用asm”就足以触发它)。LLVM必须生成遵循C规则的asm.js代码,这就是为什么
INT_MIN/-1
可以做任何它想做的事情,因为它是未定义的,所以JavaScript的结果和其他代码一样好。SpiderMonkey/V8对C规则一无所知!