Skip to content

fix(codegen): gate closure-local-call implicit-this reset on callee reading dynamic this#5032

Closed
proggeramlug wants to merge 1 commit into
mainfrom
fix/closure-local-call-implicit-this
Closed

fix(codegen): gate closure-local-call implicit-this reset on callee reading dynamic this#5032
proggeramlug wants to merge 1 commit into
mainfrom
fix/closure-local-call-implicit-this

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Summary

Fixes #5030 — unbreaks the required compiler-output-regression check, red on main since #5004 (verified by adjacent-commit runs: gate green at 50c1a64 / #5003, red at f991e2e / #5004 with the exact failure signature from CI).

Root cause

#5004 added an OrdinaryCallBindThis reset (js_implicit_this_set(undefined) + restore) around receiverless calls. The FuncRef path correctly gates it on funcs_reading_dynamic_this ("ordinary helper calls pay nothing"), but try_lower_closure_typed_local_call (early_branches.rs) emits the pair unconditionally. In the h1_buffer_alias_negative fixture, closureCapture()'s hot loop calls a this-free arrow (read(i)) — the per-iteration js_implicit_this_set pair trips hot_loops_no_runtime_calls (it is the only call in the failing report that is not on the workload's allowlist).

Fix

Mirror the FuncRef gating in the closure-typed-local path:

  • Direct/guarded path, statically-known callee: emit the reset only when the mapped closure's body reads dynamic this (funcs_reading_dynamic_this, which conservatively includes arrows capturing lexical this).
  • Typed-feedback guard fallback: the runtime receiver is some other closure codegen never saw — when the static gate skipped the outer reset, the fallback block now does its own reset/restore around js_closure_callN. (Fallback blocks are not hot-loop blocks, so the gate stays green while runtime/object-model: implement strict and sloppy function this binding #3576 semantics are preserved even for reassigned closure locals.)
  • Generic js_closure_callN tail (unknown func id / rest params / arity mismatch): unconditional reset, as before.

Validation

  • compiler_output_regression.py suite --suite native-region-proofall workloads pass (failed_workloads: []), previously h1_buffer_alias_negative failed.
  • capture --gate for vectorized_buffer_transform and hir_fact_rewrite → pass.
  • python3 -m unittest tests.test_compiler_output_regression → 40/40.
  • test-files/test_object_model_semantics_3986.ts (the fix(runtime,hir): object-model semantics — Object boxing, this-binding, var-hoisting (#3986/#3577/#3576/#3575) #5004 semantics test) still prints object-model-semantics: ok under Perry.
  • New targeted behavioral check (compiled + ran): (1) closure local statically mapped to a this-free arrow but reassigned at runtime to a this-reading function — guard fallback binds this to undefined/globalThis, no receiver leak; (2) this-reading closure local on the fast path — reset still applied; (3) the CI: compiler-output-regression red on main (h1_buffer_alias_negative native-region-proof workload) #5030 hot-loop helper shape computes correctly.
  • cargo test --release -p perry-codegen → green except manifest_param_counts_match_dispatch_table (zlib::deflateRawSync arity drift), which is pre-existing macOS-local and unrelated (my diff touches neither manifest nor dispatch; the test passes in Linux CI on current main).

Related: #5031 fixes the cargo-test red (stream unshift); #5029 (gc_write_barrier_stress) is being bisected separately.

No version bump / changelog per external-PR convention.

@proggeramlug

Copy link
Copy Markdown
Contributor Author

Superseded by #5033 (same commit, stacked with the stream fix and the #5029 test gating so all required checks can pass together).

@proggeramlug proggeramlug deleted the fix/closure-local-call-implicit-this branch June 12, 2026 06:45
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.

CI: compiler-output-regression red on main (h1_buffer_alias_negative native-region-proof workload)

1 participant