Log inGet started
World

ZeroJS

zerojs: compiled execution tier over the shared realm Dense integer-indexed array storage in the runtime (1-shifted Luau array-part with sparse/named fallback, rt.iget/rt.iset fast paths), a JS-to-Luau compiler covering the full parsed language against the same realm value model as the interpreter, and an auto engine in the api that runs every script compiled-first with a loud interpreter fallback on compile bail. Full suite green compiled-first; 18x on array-heavy scripts before type-directed emission. --- zerojs compiler: local type inference for native emission Per-function prescan classifies locals provably number-typed (every assignment produces a number, fixpoint over the candidate set, closures that mutate a name demote it) and array-typed (array-literal bindings). Number-typed operands compile to native Luau arithmetic and comparisons, loop counters increment natively, test positions elide the truthiness call for boolean-typed expressions, and integer-indexed element access on known arrays dispatches straight to the runtime's dense fast path. 20k-element fill+sum inside a function: 611ms interpreted, 30.6ms compiled. --- zerojs: compiled module evaluation Module bodies compile to Luau chunks taking (rtc, imports): imports bind as const chunk locals (assignment traps with the interpreter's exact TypeError, as do const declarations generally), export declarations lower to plain statements with an export-name snapshot returned at completion, dynamic import() and import.meta compile against the realm hook, and the module graph tries the compiled chunk first with the same loud interpreter fallback the api engine uses. Module-level bindings are chunk locals, so the function-level type inference applies to module code. --- zerojs compiler: register-pool temps Transient operand temps come from a per-function register pool declared once at the function head and reassigned, with the counter resetting at each statement; construct-persistent values (loop step functions, switch state, try results) keep dedicated locals. Large minified module bodies previously exhausted Luau's 200-local limit at loadstring and bailed to the interpreter; they now compile. --- zerojs compiler: chunk large literals and argument lists, pooled discards An array literal or call with hundreds of elements compiled to one Luau table constructor whose element expressions exhaust the register file; both now build incrementally past 100 elements. Expression statements discard through a recycled pool slot (or a bare call statement) instead of minting a fresh throwaway local each time. --- zerojs: module graph hands its parsed AST to the compiler The graph already parses each module for import resolution; the compiled tier now reuses that AST instead of re-parsing multi-megabyte sources. --- zerojs compiler: pool watermark recycling and chain slot reuse Element and property temps in large literals rewind the pool counter per item; logical chains reuse the left result's slot; operands already held in a temp pass through instead of copying to a fresh slot. A thousand- element data literal or a two-hundred-term guard chain now costs a handful of registers instead of exceeding the register file. --- zerojs compiler: module-binding spill table A module whose top-level binding count would exhaust Luau's local or upvalue register files (200 each) keeps every module-scope binding in a single spill table: nested functions capture one upvalue instead of one per referenced constant. Literal and argument fast paths drop to 30 elements so nested constructors stay clear of the register file. --- zerojs compiler: destination-threaded conditionals, template accumulator A Cond or Logical in another's arm position writes into the shared destination temp instead of allocating its own, so right-nested ternary and guard chains cost one register per chain; arm scratch rewinds once the result lands. Templates past eight interpolations accumulate into a single temp instead of one concatenation expression. --- zerojs compiler: budget every compiled body A compiled function invoked on a thread with no budget state (a timer or host callback outside any run) seeds one, honouring the realm's frame-slicing opt-in. The interpreter budgets every body; a runaway compiled callback now raises RangeError or parks per slice the same way instead of holding the frame unbounded. --- zerojs compiler: parking is exclusive to loop-spawned async bodies A synchronous compiled callback runs inline on the thread that pumps the timers; parking there suspends the pump its own resume depends on. Unseeded callback threads now get a plain RangeError guard, matching the interpreter's synchronous bodies. --- zerojs compiler: inline dense element access and loop budget back-edges A proven array binding with a numeric index reads its dense slot inline (hole/gap/fractional falls back to the runtime read) and writes inline for overwrites and boundary appends — a gap write marks the array sparse so appends near unabsorbed entries reconcile through the runtime. Loop back-edges fetch the coroutine's budget state once and decrement inline with a rare slow call. 20k fill+sum: 611ms interpreted, 5.1ms compiled. --- zerojs: Math intrinsics and own-property fast paths Math.<fn> on the unshadowed global compiles to the native library call for the methods whose Luau semantics match JS exactly (floor, ceil, abs, sqrt, trig, exp, log, pow, zero-arg random); non-number operands coerce through the runtime. Member reads resolve an own data property in two table reads before full dispatch, and writes to an existing own data property store directly — own presence shadows prototype setters, and frozen objects, proxies, typed arrays, and array length bookkeeping keep the full path. --- zerojs: Math.imul/max/min intrinsics imul multiplies exactly in split 16-bit halves (a double product loses low bits past 2^53 — mulberry32-class PRNG sequences depend on them); two-argument max/min coerce and propagate NaN per JS. One runtime call replaces the global-lookup + property-get + method-call chain that dominated seeded world generation. --- zerojs: callback guard budget scales with the realm The unseeded-thread guard defaulted far below the budgets hosts configure for their runs, so a long (finite) synchronous callback tripped RangeError where the interpreter's inherited budget survived. The guard now reads the realm's callbackBudget knob, defaulting to the same scale hosts use. --- fix(compiler): ctorRet only applies to the constructor body itself — an arrow nested in a derived constructor returns its own value; regression tests --- modules: cross-VM compiled-chunk cache — content-hash keyed; a hit skips parse, codegen, and loadstring; import/re-export/export metadata cached alongside the pure chunk --- errors: thrown-ring entries carry the realm's current stack context --- compiler: guarded inline arithmetic/compare — number-hot binary ops run as native Luau operators behind inline type guards; literal and proven-number sides skip their runtime check entirely --- compiler: inline own-property reads and writes (zero-call hot path mirroring the runtime fast paths); generated chunks request O2 + native compilation + sealed env on engines that support loadstring options (gated on luauNativeSupported) --- runtime+compiler: O(1) key-membership set on every object (kills the linear keys scan on new-key writes); plain object literals construct in one call (props/keys/keySet built directly); untouched dense arrays append inline on push. objLit 7.9x, push 11.6x measured --- compiler: rtc.set resolves plain-object writes inline — one prototype-chain accessor consult, then a direct own data write with key bookkeeping; only accessors, proxies, typed arrays, frozen objects, and arrays route through the runtime. Constructor field writes 2.3x, entity population 2.9x --- compiler: calling convention v2 — vararg call intrinsics (callv/mcallv/mcallcv), __direct dispatch slot, positional-param emission; budget seed confined to the call boundary; hole-safe boundary unpack; literal-receiver paren fix in inline member read/write --- compiler: classNew v2 — rtc.newv vararg construction, __directCtor on base-class constructors (positional ctor bodies via shared directEligible), construct boundary unpacks at declared width --- compiler+runtime: ctor field-write fast path (per-object hasAccessors + realm accGen sampling), rtc.newv direct construct for plain-function ctors, stdlib defineProperty plain-data descriptor fast path

cbf554236b931081009bf17bcf98b1d235f5bf4fc419467a84682fe73e6b2b32
Author
zero-proxy @ DESKTOP-DB3UJOJ
Date
Jul 24, 2026
Branch
main
Parent
4c4469713d

19 files changed

  • Changedzerojs.packageFolderBeforeAfter
  • Changedzerojs.package/api.moduleFolderBeforeAfter
  • Changedzerojs.package/api.module/init.luau21.7 KB → 28.2 KBBeforeAfter
  • Addedzerojs.package/compiler.moduleFolderAfter
  • Addedzerojs.package/compiler.module/.metadata17 BAfter
  • Addedzerojs.package/compiler.module/README.md1.9 KBAfter
  • Addedzerojs.package/compiler.module/init.luau174 KBAfter
  • Changedzerojs.package/errors.moduleFolderBeforeAfter
  • Changedzerojs.package/errors.module/init.luau2.9 KB → 3.2 KBBeforeAfter
  • Changedzerojs.package/interpreter.moduleFolderBeforeAfter
  • Changedzerojs.package/interpreter.module/init.luau94.7 KB → 94.8 KBBeforeAfter
  • Changedzerojs.package/modules.moduleFolderBeforeAfter
  • Changedzerojs.package/modules.module/init.luau7.5 KB → 11.6 KBBeforeAfter
  • Changedzerojs.package/runtime.moduleFolderBeforeAfter
  • Changedzerojs.package/runtime.module/init.luau29.8 KB → 37.9 KBBeforeAfter
  • Changedzerojs.package/stdlib.moduleFolderBeforeAfter
  • Changedzerojs.package/stdlib.module/object.luau23.6 KB → 25.4 KBBeforeAfter
  • Changedzerojs.package/tests/zerojs_semantics.testSuiteFolderBeforeAfter
  • Changedzerojs.package/tests/zerojs_semantics.testSuite/init.luau50.7 KB → 51.3 KBBeforeAfter