Skip to content

BEAM-native JS engine and compiler#5

Open
dannote wants to merge 2809 commits into
masterfrom
beam-vm-interpreter
Open

BEAM-native JS engine and compiler#5
dannote wants to merge 2809 commits into
masterfrom
beam-vm-interpreter

Conversation

@dannote
Copy link
Copy Markdown
Member

@dannote dannote commented Apr 15, 2026

Introduces a BEAM-native JavaScript execution engine from the ground up. Before this branch, QuickBEAM executed JavaScript through native QuickJS only; there was no Elixir bytecode decoder, BEAM interpreter, or BEAM compiler backend.

BEAM execution path

  • Adds mode: :beam, mode: :auto, mode: :beam_compiler, and QUICKBEAM_MODE=beam_compiler.
  • Decodes QuickJS bytecode in Elixir and runs it through a BEAM interpreter.
  • Lowers supported QuickJS bytecode into generated BEAM modules with interpreter fallback and audit modes.
  • Supports runtime/context integration, module loading, dynamic import, globals, handlers, stack traces, source positions, and QuickBEAM.disasm/2.
  • Covers generators, async generators, promises, direct eval, refs, closures, locals/captures, classes, private fields, with, super, destructuring, iterators, and error propagation across interpreted and compiled paths.

Compiler and VM architecture

  • Introduces compiler analysis/lowering infrastructure: CFG, stack-depth inference, type analysis, block lowering, exception-region lowering, runtime helpers, and runtime ABI boundaries.
  • Centralizes opcode metadata in OpcodeSpec, including operand formats, byte sizes, stack effects, branch/control metadata, slot metadata, call arity, and lowering ownership.
  • Adds guardrails for opcode metadata, label/control-flow metadata, lowering registry coverage, compiler ABI calls, generated BEAM disassembly, and runtime-facing architecture boundaries.
  • Moves generated-code calls behind RuntimeABI and keeps compiler lowering from calling lower-level VM/object-model internals directly.

Object model and semantics

  • Routes observable object behavior through ObjectModel.InternalMethods for get/set/define/delete/own keys/prototype/extensibility paths, with focused proxy invariant modules.
  • Splits object-model behavior into focused helpers for ordinary get, own lookup, prototypes, callbacks, arrays, typed arrays, regexps, symbols, wrapped primitives, proxies, and descriptors.
  • Fixes semantic gaps found while bringing the BEAM backend online, including BigInt ToNumber, direct eval strictness, caller arguments reuse, transactional global writes, proxy invariants, invalid branch labels, malformed bytecode parsing, finally lowering arg-count, iterator-result owner lifecycle, and GC root handling.

Builtins, metadata, and runtime cleanup

  • Adds and expands the builtin DSL: grouped intrinsics, block-style constructors/install/prototype/statics, @ecma / @annex, nested symbol declarations, descriptor-aware object declarations, object extends:, object prototype:, and object into:.
  • Migrates broad builtin/runtime surfaces to declarative specs and DSL declarations across Array, ArrayBuffer, BigInt, DataView, Date, Error, FinalizationRegistry, Function, Iterator, JSON, Map/Set/WeakMap/WeakSet, Math, Number, Object, Promise, Proxy, Reflect, RegExp, String, Symbol, TypedArray, WeakRef, globals, and selected Web host bindings.
  • Validates ECMA metadata against a compact referenced-section whitelist and keeps proposal/host APIs untagged unless they are part of ECMA-262.
  • Extracts focused runtime helpers including ArrayIterator, IteratorResult, ObjectIntegrity, ObjectEnumeration, ObjectAssign, ObjectDescriptors, and TypedArrayInstallation.

Native/runtime reliability

  • Fixes DOM wrapper-cache GC ownership by avoiding GC traversal over cached JS wrappers owned by explicit JS_DupValue references.
  • Registers NAPI external/wrap classes per runtime, reserves reused QuickJS class IDs per runtime, and suppresses NAPI wrap finalizer callbacks during shutdown.
  • Adds DOM/NAPI ownership shutdown coverage and runs NAPI addon tests serially to avoid native addon/global-state races.
  • Stabilizes broad validation tests around generated warning noise, context-pool timing, and BEAM monitor races.

Audit and benchmark tooling

  • Adds compiler compatibility, corpus, opcode coverage, performance, semantic-gap, and Test262 audit scripts.
  • Adds runtime/compiler acceptance tests, auto-mode tests, compiler differential tests, compiler ABI boundary tests, and architecture boundary checks.
  • Current compiler audit status remains: all supported QuickJS opcodes covered except intentionally unsupported invalid, strict Test262 statement window passing, semantic compiler corpus passing, and compiler perf audit tracked.

Recent validation

  • mix format --check-formatted
  • mix compile --warnings-as-errors
  • mix reach.check
  • mix test test/vm/runtime test/vm/compiler test/vm/object_model test/vm/interpreter test/vm/builtin_dsl_test.exs test/vm/ecma_metadata_test.exs --max-failures 5
  • mix test test/vm/object_descriptors_order_test.exs test/vm/object_proxy_integrity_test.exs test/vm/object_define_accessor_test.exs test/vm/object_own_property_primitives_test.exs test/vm/object_keys_test.exs test/vm/object_model/proxy_test.exs test/vm/compiler/core_test.exs --max-failures 5
  • QUICKBEAM_BUILD=1 mix test --max-failures 1 --timeout 1200007 doctests, 4251 tests, 0 failures, 3 skipped
  • mix test --max-cases 1 --max-failures 1 --timeout 1200007 doctests, 4251 tests, 0 failures, 3 skipped
  • QUICKBEAM_BUILD=1 mix test test/napi_test.exs test/web_apis --max-failures 1 --timeout 1200001045 tests, 0 failures, 2 skipped

@dannote dannote force-pushed the beam-vm-interpreter branch from 0eb3475 to 7c1c574 Compare April 15, 2026 14:06
@dannote dannote changed the title BEAM-native JS interpreter (Phase 0-1) BEAM-native JS interpreter Apr 16, 2026
@dannote dannote marked this pull request as ready for review April 16, 2026 08:41
@dannote dannote force-pushed the beam-vm-interpreter branch 2 times, most recently from 75fdba5 to 527d5b9 Compare April 20, 2026 08:45
@dannote dannote changed the title BEAM-native JS interpreter BEAM-native JS engine and compiler Apr 21, 2026
dannote added 30 commits May 31, 2026 14:15
Result: {"status":"keep","compatibility_failures":0,"compiler_test262_cases":300,"compiler_test262_pass":300,"compiler_test262_failures":0,"compiler_test262_compiler_errors":0,"compiler_test262_compiler_crashes":0,"compiler_test262_compiler_fails":0,"compiler_test262_both_fail":0,"compiler_test262_interpreter_fail_compiler_pass":0,"compatibility_pass":300,"compatibility_cases":300,"compiler_errors":0,"compiler_crashes":0,"compiler_fails":0,"both_fail":0,"interpreter_fail_compiler_pass":0,"elapsed_ms":5034}
Result: {"status":"keep","compatibility_failures":0,"quickjs_parity_cases":17,"quickjs_parity_pass":17,"quickjs_parity_failures":0,"compatibility_pass":17,"compatibility_cases":17,"compiler_errors":0,"compiler_crashes":0,"compiler_fails":0,"both_fail":0,"interpreter_fail_compiler_pass":0,"elapsed_ms":73575}
Result: {"status":"keep","compatibility_failures":12,"quickjs_parity_all_cases":1170,"quickjs_parity_all_native_accepted":941,"quickjs_parity_all_pass":929,"quickjs_parity_all_failures":12,"quickjs_parity_all_native_rejected":5,"quickjs_parity_all_skipped":224,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":0,"both_fail":3,"interpreter_fail_compiler_pass":9,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":929,"compatibility_cases":941,"elapsed_ms":33278}
Result: {"status":"keep","compatibility_failures":11,"quickjs_parity_all_cases":1170,"quickjs_parity_all_native_accepted":941,"quickjs_parity_all_pass":930,"quickjs_parity_all_failures":11,"quickjs_parity_all_native_rejected":5,"quickjs_parity_all_skipped":224,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":0,"both_fail":2,"interpreter_fail_compiler_pass":9,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":930,"compatibility_cases":941,"elapsed_ms":14963}
Result: {"status":"keep","compatibility_failures":6,"quickjs_parity_all_cases":1170,"quickjs_parity_all_native_accepted":941,"quickjs_parity_all_pass":935,"quickjs_parity_all_failures":6,"quickjs_parity_all_native_rejected":5,"quickjs_parity_all_skipped":224,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":0,"both_fail":0,"interpreter_fail_compiler_pass":6,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":935,"compatibility_cases":941,"elapsed_ms":15040}
Result: {"status":"keep","compatibility_failures":0,"quickjs_parity_all_cases":1170,"quickjs_parity_all_native_accepted":941,"quickjs_parity_all_pass":941,"quickjs_parity_all_failures":0,"quickjs_parity_all_native_rejected":5,"quickjs_parity_all_skipped":224,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":0,"both_fail":0,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":941,"compatibility_cases":941,"elapsed_ms":35852}
Result: {"status":"keep","compatibility_failures":3,"quickjs_parity_all_cases":92,"quickjs_parity_all_native_accepted":85,"quickjs_parity_all_pass":82,"quickjs_parity_all_failures":3,"quickjs_parity_all_native_rejected":7,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":0,"both_fail":3,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":82,"compatibility_cases":85,"elapsed_ms":4571}
Result: {"status":"keep","compatibility_failures":0,"quickjs_parity_all_cases":92,"quickjs_parity_all_native_accepted":85,"quickjs_parity_all_pass":85,"quickjs_parity_all_failures":0,"quickjs_parity_all_native_rejected":7,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":0,"both_fail":0,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":85,"compatibility_cases":85,"elapsed_ms":6606}
Result: {"status":"keep","compatibility_failures":0,"quickjs_parity_all_cases":1170,"quickjs_parity_all_native_accepted":941,"quickjs_parity_all_pass":941,"quickjs_parity_all_failures":0,"quickjs_parity_all_native_rejected":5,"quickjs_parity_all_skipped":224,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":0,"both_fail":0,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":941,"compatibility_cases":941,"elapsed_ms":15452}
Result: {"status":"keep","compatibility_failures":52,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3356,"quickjs_parity_all_failures":52,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":36,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3356,"compatibility_cases":3408,"elapsed_ms":205703}
Result: {"status":"keep","compatibility_failures":39,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3369,"quickjs_parity_all_failures":39,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":23,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3369,"compatibility_cases":3408,"elapsed_ms":214752}
Result: {"status":"keep","compatibility_failures":35,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3373,"quickjs_parity_all_failures":35,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":19,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3373,"compatibility_cases":3408,"elapsed_ms":100769}
Result: {"status":"keep","compatibility_failures":30,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3378,"quickjs_parity_all_failures":30,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":14,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3378,"compatibility_cases":3408,"elapsed_ms":118168}
Result: {"status":"keep","compatibility_failures":28,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3380,"quickjs_parity_all_failures":28,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":12,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3380,"compatibility_cases":3408,"elapsed_ms":88168}
Result: {"status":"keep","compatibility_failures":27,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3381,"quickjs_parity_all_failures":27,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":11,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3381,"compatibility_cases":3408,"elapsed_ms":83131}
Result: {"status":"keep","compatibility_failures":24,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3384,"quickjs_parity_all_failures":24,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":8,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3384,"compatibility_cases":3408,"elapsed_ms":81592}
Result: {"status":"keep","compatibility_failures":21,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3387,"quickjs_parity_all_failures":21,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":5,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3387,"compatibility_cases":3408,"elapsed_ms":81733}
Result: {"status":"keep","compatibility_failures":20,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3388,"quickjs_parity_all_failures":20,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":4,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3388,"compatibility_cases":3408,"elapsed_ms":81858}
Result: {"status":"keep","compatibility_failures":19,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3389,"quickjs_parity_all_failures":19,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":3,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3389,"compatibility_cases":3408,"elapsed_ms":81810}
Result: {"status":"keep","compatibility_failures":17,"quickjs_parity_all_cases":3411,"quickjs_parity_all_native_accepted":3408,"quickjs_parity_all_pass":3391,"quickjs_parity_all_failures":17,"quickjs_parity_all_native_rejected":3,"quickjs_parity_all_skipped":0,"compiler_errors":0,"compiler_timeouts":0,"compiler_crashes":0,"compiler_fails":16,"both_fail":1,"interpreter_fail_compiler_pass":0,"interpreter_timeouts":0,"interpreter_crashes":0,"compatibility_pass":3391,"compatibility_cases":3408,"elapsed_ms":82899}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant