Skip to content

perf(jit): reduce native entry, feedback, and PC validation overhead - #18

Merged
huacnlee merged 5 commits into
mainfrom
perf/m3-native-entry-overhead
Sep 5, 2026
Merged

perf(jit): reduce native entry, feedback, and PC validation overhead#18
huacnlee merged 5 commits into
mainfrom
perf/m3-native-entry-overhead

Conversation

@huacnlee

@huacnlee huacnlee commented Sep 5, 2026

Copy link
Copy Markdown
Member

Issue # (if available)

Follow-up to M2 (#16).

Description of changes

Generic native calls repeatedly acquired and released entry handles and allocated return/argument feedback storage. Cache one idle pc=0 entry handle per QuickJS runtime, replace the native-return queue with a synchronous inline handoff, reuse CALL feedback storage after warmup, and resume helper PC validation from a previously verified instruction boundary.

  • Preserve exclusive active pins during recursion and GC; invalidate idle reuse on feedback/tier changes, demotion, retirement, suspension, and detach. Suppress cache population across reentrant release callbacks and preserve original function-generation attribution.
  • Add the optional pure entry_cache_epoch query, bump JIT ABI minor to 20, and update the vtable fingerprint, bundled bindings, and patch manifest. OSR handles remain uncached.
  • Preserve helper PC range/end/operand rejection with a private per-function boundary cursor; backward queries rescan, and invalidation resets the cursor. Add a boundary/ownership regression verified with a failing validation-bypass mutation.
  • Add native-acquisition metrics, a generic-call probe, ownership/invalidation regressions, and a thread-local allocation regression: 100 warmed 32-type CALL events previously allocated or reallocated 400 times and now allocate zero times.

The final cursor diagnostic records 1.356x M2 speed for generic calls in automatic mode (actually Tier 1; paired 95% interval: 35.3%–35.9% faster). Relative to the complete pre-cursor version, Tier 1 generic calls are 1.135x speed, direct calls 2.226x, and recursive Fibonacci 1.108x; automatic generic calls improve only to 1.007x. CALL-buffer reuse independently eliminates warmed allocations; its earlier incremental timing result was statistically tied.

There are small measured tradeoffs: focused 60-pair repeats retain automatic direct-call speed of 0.979x the pre-cursor baseline (1.3%–3.3% slower) and Tier 2 scalar-loop speed of 0.985x (1.1%–2.2% slower). Direct-call Tier 2 and automatic scalar-loop repeats are statistically tied. Reports preserve raw samples, exact executable/script hashes, the cursor patch, and reproduction drivers. The profiler's helper-frame share falls from 36.08% to 18.24% of self sampled cycles; that attribution is not an overall speed claim.

The pre-cursor clean-source matrix is archived with raw evidence: 22 workloads, four modes, and 2,640 retained samples. The overall performance acceptance gate still fails: Tier 2 compute speed is 3.17x–3.23x the interpreter baseline (below the 5x target), startup/reload gates fail, and host-integration evidence is absent. Checksum, required native-entry, automatic-policy, and aggregate P99 gates pass. That matrix predates the cursor change; it is not acceptance evidence for the final revision. Its mode comparisons are separate from the revision diagnostics above. Report labels now distinguish qualifying native entries for each requested tier. See docs/M3.md for evidence, ownership proofs, and limitations.

Validation on final code:

  • 512 release runtime tests: cargo test --release -p quickjs-jit-runtime --features compiler,test-support --tests
  • 55 helper, native-boundary and Tier 1 call tests under AddressSanitizer/LeakSanitizer on native Linux x86_64
  • Full-workspace Clippy with --features full-async,bindgen -- -D warnings; formatting check
  • 15 bindgen-enabled ABI tests, including exact bundled/fresh declaration comparison
  • 11 patch tests and 24 benchmark tests
  • Independent reviews of cache ownership/invalidation, return handoff, feedback reuse, and PC boundary reuse; identified cache issues fixed with reproducing regressions

CI for the cursor commit remains pending. Its parent b7be6a4 passed 41 checks, including memory, address, and thread sanitizers. Per-call hot/enter/exit bookkeeping, feedback/tier-state lookups, and remaining frame-validation work persist; this PR does not complete the broader native-call-overhead target.

Checklist

  • Added change to the changelog
  • Created unit tests for my feature if needed

@huacnlee huacnlee changed the title perf(jit): cache native entries and reuse call feedback storage perf(jit): reduce native entry, feedback, and PC validation overhead Sep 5, 2026
@huacnlee
huacnlee merged commit a38bd01 into main Sep 5, 2026
14 checks passed
@huacnlee
huacnlee deleted the perf/m3-native-entry-overhead branch September 5, 2026 12:18
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