Sigil 0.22.9
A size release. Web builds of native-compiled apps are about 70% smaller, and call-heavy native code runs faster, because the compiler no longer spends most of each function's code on bookkeeping. Measured on Crash The Stack, Harkfell and Phantom Burn at the same commits.
Existing projects build without changes. Rebuild to pick up the smaller output.
Web builds are about 70% smaller
A game's wasm is almost all code the compiler emits for its Sigil modules, and two thirds of that was per-function boilerplate: every local variable registered with the garbage collector by its own inlined call, and every call followed by its own copies of the error and exception exits. Locals are now kept in one array that is registered once, and a function's exits share one label.
| Game | 0.22.8 | 0.22.9 | Change |
|---|---|---|---|
| Crash The Stack | 44.8 MB | 12.0 MB | -73% |
| Harkfell | 31.7 MB | 9.0 MB | -72% |
| Phantom Burn | 11.4 MB | 3.7 MB | -68% |
Gzipped downloads shrink by 35 to 42%. Crash The Stack and Harkfell were over Cloudflare Pages' 25 MiB file limit and are now well under it.
Native code calls faster
Native desktop builds use the same compiler, so a function now makes room for its garbage collector roots once instead of once per local. A call-heavy benchmark (fib, tak) runs in about half the time. In the browser, Crash The Stack's game tick went from 11.7 ms to 9.2 ms a frame, and its whole frame callback from 14.4 ms to 10.6 ms.
Fixes
(remainder 7.0 2)returned an undefined value in release and web builds, for every inexact argument. It now returns1.0, and a zero divisor raises an error, as on the bytecode VM.applywith an improper list as its last argument silently dropped the tail in native code:(apply f 1 '(2 . 3))calledfwith(1 2). It now raises the same error as the bytecode VM.integer?was wrong on both backends:(integer? 1.0)was#fon the bytecode VM, and(integer? 3.5)and(integer? +inf.0)were#tin native code. It now follows R7RS everywhere: exact integers and finite integral floats.- A
-0.0literal lost its sign in release and web builds, and prints as-0on every backend now.+inf.0,-inf.0and NaN literals are also emitted exactly. - Forcing a promise whose body yielded inside
with-asyncreturned an undefined value on the bytecode VM and cached it, so every laterforcewas wrong too. It now returns the body's value, as native code already did. - Release and web builds and the bytecode VM now agree on all of the above, checked by a new test that runs the same cases on both backends.
Known issues
- Release builds of desktop apps still run the standard library and dependency packages as bytecode; only the app's own modules are native. A proper fix is coming.
- In web builds, forcing a promise whose body yields inside
with-asyncstops the program, as it did in 0.22.8. The bytecode VM fix above doesn't cover the web path yet.