在javascript中,带有“整型”参数的零除法类似于浮点数:
1/0; // Infinity
-1/0; // -Infinity
0/0; // NaNasm.js规范指出,带有整数参数的除法返回intish,必须立即强制进行签名或无符号。如果在javascript中这样做,使用“整型”参数除以零的值在强制之后总是返回零:
(1/0)|0; // == 0, signed case.
(1/0) >> 0; // == 0, unsigned case.但是,在具有实际整数类型(如Java和C )的语言中,整数除以零是一个错误,执行以某种方式停止(例如抛出异常、触发陷阱等)。
这似乎也违反了asm.js指定的类型签名。Infinity和NaN的类型是double,/的类型应该是(来自规范):
(签名,签名)→intish∧(未签名,未签名)→intish∧( double ?,double?)→→double∧(浮点?,浮点数?)→浮点数
但是,如果其中任何一个都有零分母,则结果是double,因此类型似乎只能是:
(双?,双?)→双倍
在asm.js代码中预期会发生什么?它是否遵循javascript并返回0,还是会产生运行时错误?如果它遵循javascript,为什么输入错误是可以的呢?如果它产生运行时错误,为什么规范没有提到它?
发布于 2015-03-21 15:24:44
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只是最近在UDIV扩展(虚拟化扩展)中添加了ARMv7VE和SDIV指令,并使其在ARMv7-A处理器中可选(大多数手机和平板电脑都使用这些)。您可以使用/proc/cpuinfo检查指令,但请注意,有些内核不知道该指令!解决方法是在进程开始时通过执行指令检查指令,并使用sigsetjmp/siglongjmp捕捉未处理的情况。这还有一个进一步的警告:捕获内核“有用”的情况,并在不支持它的处理器上模拟UDIV/IDIV!如果指令不存在,则必须使用C库的整数除法指令(libgcc或compiler_rt包含诸如__udivmoddi4之类的函数)。请注意,此函数在除以零的情况下的行为可能因实现而异,必须使用零分母上的分支来处理,或者在加载时进行检查(与上面概述的UDIV/SDIV相同)。
我将不问您一个问题:在执行以下C代码时,在asm.js中发生了什么:INT_MIN/-1
https://stackoverflow.com/questions/29179876
复制相似问题