rpjohnst / dejavu

Game Maker reimplementation
https://dejavu.abubalay.com
Apache License 2.0
72 stars 7 forks source link

`vm::Value` can't represent negative infinity #43

Closed rpjohnst closed 4 years ago

rpjohnst commented 4 years ago

The current implementation considers a Value to be a GML real if the top 12 bits are not all-ones. This excludes negative infinity, which has a sign of 1, an exponent of all-ones, and a mantissa of all-zero, which currently gets treated as a GML string instead, converting negative infinity to a Symbol with index 0, or "true".

One solution is to make Symbols non-zero and additionally check for a zero mantissa, but that's more expensive- looking at the bottom 63 bits, it interleaves GML reals (0x0000_0... through 0x7ff0_0..., and 0x7ff8_0...) with tagged values (0x7ff0_0...1 through 0x7ff7_f..., and 0x7ff8_0...1 through0x7fff_f...`).

LuaJIT has a nicer solution, which moves the tagged value bit patterns up to the top of the space so the comparison can be a single < or <=. However, this eats one of their payload bits, because tags must start with 1 to remain above the canonical NaN (LuaJIT/LuaJIT#49) and this causes problems on ARM64, where Linux's default memory map includes user-space addresses with the 48th bit set.

I can see a few options to resolve this: