Show HN: Nova JavaScript Engine
Project Goals and Scope
- Aims to be a full ECMAScript- compliant engine, not just an experiment.
- Provides feature flags to strip out unneeded spec parts for embedders (e.g., disabling ArrayBuffers).
- Long‑term ambitions include potential use in browsers or runtimes; near term focus is one‑shot scripts and constrained environments (e.g., microcontrollers).
Architectural Design: ECS & Data-Oriented Layout
- Core idea: Entity‑Component‑System‑inspired, data‑oriented design.
- Heap is split into type‑specific “vectors” (arrays) indexed by integers, not pointers: numbers, arrays, ArrayBuffers, etc. each have their own storage.
- Objects may also be further decomposed (e.g., separate storage for properties), with some discussion of struct‑of‑arrays vs array‑of‑structs layouts.
- Motivation: better cache locality, tighter packing, fewer alignment gaps, and index-based “pointer compression”-like behavior.
GC and Memory Management Trade-offs
- Uses indices rather than native pointers; GC must manage dangling indexes and compaction.
- Strategy: heap vectors stay densely packed; GC compacts by moving surviving objects down, not filling “holes” via free lists.
- For generational GC, each vector tracks a “young generation start” index; promotion adjusts this boundary.
- Some participants question the cost of large compactions and suggest chunking, free lists, or virtual allocation; maintainer acknowledges trade-offs and open questions.
Comparisons with V8 and Mainstream Engines
- V8 uses multiple heap spaces (nursery/old), pointer or compressed-pointer references, and monolithic objects (with separate backing stores for some properties).
- Commenters note V8 and others already try for cache locality (e.g., JSON array parsing), but follow an array‑of‑structs pattern.
- Claim that Nova’s full “heap vectors + indexes” model would be nearly impossible to retrofit into existing engines without a rewrite.
Data-Oriented Design Debate
- Several discuss whether “all numbers in a vector, all arrays in a vector” actually matches typical JS access patterns.
- Pro‑Nova view: most performance hotspots are loops over large, linearly created datasets; data created together tends to be used together.
- Skeptical view: general-purpose workloads often access fields within the same object (
foo.name+foo.lastName), not across many objects, so ECS‑like layouts may help only for specific patterns.
Performance Expectations & Benchmarks
- Currently no robust benchmark results; large benchmarks can stall because GC is not yet interleavable with JS execution.
- Known current bottlenecks: property lookup (linear search on larger objects), value comparisons, slow string interning.
- Plan is to finish interleaved GC, implement object shapes and inline property caches, then compare with V8 in non‑JIT modes.
JIT, Optimizations, and TCO
- Engine currently has a bytecode compiler and interpreter only; no JIT.
- Maintainer hopes JIT will remain unnecessary if key optimizations (especially property access inline caching) are implemented.
- Cites no‑JIT modes in other engines and small‑scale timings as anecdotal support, but no hard data yet.
- Tail‑call optimization is planned, as it is in the ECMAScript spec; some code already marked with TODOs for TCO.
Safety, Indices, and Rust
- Using indices weakens some of Rust’s usual guarantees (e.g., referential safety), but is argued to preserve memory safety when bounds-checked.
- Design tries to prevent type confusion by keeping tag + index together in a tagged union; changing an index’s “kind” requires unsafe operations.
- Some worry this can still lead to silent logic errors or security issues via stale indices; mitigations are partly conceptual and partly via Rust lifetimes/ZST helpers, but not fully proven.
Miscellaneous
- Name “Nova” is acknowledged as overused but kept for historical/bikeshedding reasons.
- Thread includes suggestions to study related work (e.g., BIBOP, other JS and Lisp engines) and to benchmark against game‑oriented runtimes like Lua.
- Overall tone: mixture of enthusiasm for the experimental design and skepticism about its general applicability and GC complexity.