asm.js如何处理除零?

Fra*_*ila 6 javascript asm.js

在javascript中,使用"整数"参数除零就像浮点一样:

 1/0;    // Infinity
-1/0;    // -Infinity
 0/0;    // NaN
Run Code Online (Sandbox Code Playgroud)

asm.js规范说,返回带有整数参数的除法intish,必须立即强制转换为有符号或无符号.如果我们在javascript中执行此操作,则使用"整数"参数除零始终在coersion后返回零:

(1/0)|0;    // == 0, signed case.
(1/0) >> 0; // == 0, unsigned case.
Run Code Online (Sandbox Code Playgroud)

但是,在具有Java和C等实际整数类型的语言中,将整数除以零是一个错误,执行会以某种方式停止(例如,抛出异常,触发陷阱等).

这似乎也违反了asm.js指定的类型签名.的类型的InfinityNaNdouble/是假想(从规格):

(签名,签名)→intish∧(无符号,无符号)→intish∧(double?,double?)→double∧(float?,float?)→floatish

但是,如果其中任何一个具有零分母,结果是double,所以看起来类型只能是:

(双?,双?)→双

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

JF *_*ien 5

asm.js是JavaScript的一个子集,所以它必须返回JavaScript的作用:Infinity|00.

你指出的Infinitydouble,但是这会将asm.js类型系统与C语言混合在一起(在JavaScript中number):asm.js使用JavaScript类型强制来使中间结果成为"正确"类型,而不是.当JavaScript中的一个小整数溢出到a时会发生同样的事情double:使用按位运算将其强制转换回整数.

这里的关键是它给编译器一个提示,它不需要计算JavaScript通常会计算的所有东西:如果一个小整数溢出是因为它被强制转换为整数,所以编译器无关紧要可以省略溢出检查并发出直线整数运算.请注意,它仍然必须针对每个可能的值正确运行!类型系统基本上暗示了编译器要做一堆强度降低.

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

  • 如果输入为零,则在分区周围分支,并直接返回零.
  • 使用提供的输入进行除法,但在程序开始时安装信号处理程序,捕获SIGFPE.当它出现故障时查找代码位置,如果编译器的元数据表明它是一个除法位置,则将返回值修改为零并继续执行.

前者是V8和OdinMonkey实现的.

在ARM上,整数除法指令定义为始终返回零,除了ARM的ARMv7-R配置文件(故障是未定义的指令,或者可以更改为返回零SCTRL.DZ == 0).ARM只添加UDIVSDIV使用ARMv7VE扩展(虚拟化扩展)指令最近,并使其可用于ARMv7-A处理器可选的(大多数手机和平板电脑使用这些).您可以使用检查指令/proc/cpuinfo,但请注意某些内核不知道该指令!解决方法是通过执行指令并使用sigsetjmp/ siglongjmp来捕获未处理的情况来检查进程启动时的指令.这有一个进一步的警告,即捕获内核正在"有用"并在不支持它的处理器上模拟UDIV/ IDIV处理的情况!如果指令不存在,则必须使用C库的整数除法指令(libgcccompiler_rt包含诸如此类的函数__udivmoddi4).注意,此函数除以零的行为可能在实现之间有所不同,必须使用零分母上的分支处理或在加载时检查(与上面针对UDIV/ 概述的相同SDIV).

我将给你一个问题:asm.js在执行以下C代码时会发生什么:INT_MIN/-1