ReviewOS

zig-utils/zig-js

Perf: predecode VM quickening candidates and cache misses

#70
Closed chris opened this 9 days ago ·
9 days ago

Parent: #62 Measured rejections: #68, #69, zig-utils/zig-gc#9

Problem

The post-#67 profile attributes most remaining time to runChunk itself. Every load_local currently re-scans following bytecodes for call-loop and array-loop quickening, even though the chunk is immutable and most sites can never match. Object-churn loop heads are checked millions of times and structurally reject both plans on every iteration. The ordinary numeric-property quickener also does not cache unsupported plans, so array index patterns repeatedly attempt to decode a property assignment trace.

Scope

  • precompute immutable per-instruction call-loop/array-loop candidate bits when a Chunk is finalized;
  • make runChunk consult those bits instead of rescanning up to eleven opcodes at every load_local;
  • preserve the existing full plan compilers and runtime type/shape/step guards for actual candidates;
  • cache unsupported isolated numeric-property plans with an explicit sentinel so immutable misses decode once;
  • let known-negative property sites bypass repeated frame/object/plan work without disabling the independent multi-property kernel;
  • preserve atomic publication in shared mode and all exact step/checkpoint semantics;
  • measure a clean pinned object_churn A/B with exact checksum equality.

Acceptance criteria

  • Non-candidate load_local sites do no call/array structural rescanning.
  • Actual call, array, polymorphic-property, and four-property kernels still select and preserve exact step counts.
  • Unsupported property traces decode once and remain ordinary bytecode.
  • Shared-mode plan publication remains race-safe.
  • Focused quickening, VM fallback, and semantic tests pass.
  • Clean pinned object_churn A/B improves at checksum 1030552128.
  • Commit references this issue and evidence is added to #62.
9 days ago

Implemented and pushed to main in 971f994 (perf(vm): predecode quickening candidates (#70)).

What landed:

  • immutable call-loop and array-loop candidate masks computed once in Chunk.finalize;
  • VM dispatch consults the mask instead of rescanning up to eleven following bytecodes at every load_local;
  • unsupported isolated numeric-property plans use an explicit negative-cache sentinel;
  • sites with independently unsupported kernel and ordinary plans bypass repeated frame/object/decoder work;
  • shared-mode atomic kernel publication and isolated-mode fallback remain independent.

Validation:

  • full zig-js suite: 754/754 passed;
  • benchmark comparison harness: 7/7 passed;
  • focused call-loop, packed-array, four-property-kernel, and negative-cache coverage passed;
  • clean order-balanced A/B, 12 fresh processes per side, object_churn single/100/1:
    • baseline median: 645.740 ms;
    • current median: 616.878 ms;
    • reduction: 4.47%;
    • checksum: 1030552128 on all 24 samples.

Sign in to comment on this issue.