FEX 2502 Tagged

One month later and we have another exciting FEX-Emu release! While we don’t have a lot of individual topics, these are some very good usability and performance improvements to enjoy!

Fix Steam again

Once again this last month Steam updated its version of their embedded Chromium source. This introduced a behaviour of passing around zero length environment variables. While this isn’t necessary a problem, FEX had mad an assumptions that all environment variables contained at least one character. This minor change in behaviour results in a crash, preventing Steam from fully starting. With this problem fixed, Steam is once again able to run.

Multiblock improvements

This is one of the more exciting improvements this month as it increasing both JIT compile performance and JIT runtime performance! bylaws this month took it upon themselves to fix bugs that had ended up in FEX’s “Multibock” implementation.

The changes:

  • Stop multiblock discovery beyond a page.
    • Signicantly reducing the search space.
  • Early exit multiblock entries if the instructions are two bytes of zero
    • Highly unlikely to be real code and likely zero initialized memory
  • Split blocks at jump target boundaries
    • Significantly reducing the amount of redundant code compilation that occurs
  • Ensure our RIP reconstruction can handle large code jumps
    • Fixes crashes in game engines that do faulting magic
  • Stop copying the IR after generation
    • While not huge, when compiling hundreds of thousands of entrypoints, it adds up

With the combination of all these changes, sometimes the JIT compilation time can get cut in half with multiblock enabled! Which means we get more performance, less stuttering, and less crashes when multiblock is in use.

We don’t yet enable this feature by default, but it can be enabled in our FEXConfig tool. After a month of dogfooding this feature, we are highly likely to enable it by default for next month.

Fix WINE memory allocator behaviour

This was an interesting bug that has technically been in FEX’s source for years but only recently got unearthed as a problem. Due to a recent change in reordering how FEX allocates memory, we started allocating a region of memory that WINE allocates at startup in their preloader. This wasn’t previously an error since WINE was most likely just overwriting some temporary buffer that FEX wasn’t actually using. At startup WINE used this memory region for some heap allocations and expects it to always be available.

The good thing is that this only happened on ARM devices that are configured to use a 48-bit Virtual Address size and due to ASLR it was unlikely to cause problems. Now in this situation, FEX makes sure to keep its allocations out of the way of x86-64 applications, ensuring that there isn’t a memory conflict.

Minor optimization for x87 address modes

While hard to say this will be visible in most cases, this showed up in Crysis 2: Maximum Edition’s audio thread that was consuming 100% CPU time. This game’s audio thread is so heavy that it completely maxes out a CPU core and drops audio samples. We noticed that for address modes with a small immediate, we weren’t optimizing those to ARM instructions that could do the same. With that fixed, the game is still dropping a ton of audio samples but hopefully we have more room for improvements there.

See the 2502 Release Notes or the detailed change log in Github.

Written on February 8, 2025