Skip to content

AOT: static property assign from closure must use module globals (#31965) - #31986

Merged
PurHur merged 1 commit into
masterfrom
agent/issue-31965-static-prop-closure-aot
Aug 17, 2026
Merged

AOT: static property assign from closure must use module globals (#31965)#31986
PurHur merged 1 commit into
masterfrom
agent/issue-31965-static-prop-closure-aot

Conversation

@PurHur

@PurHur PurHur commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Closes #31965

Problem

AOT typed static property writes inside closures were promoted to stack alloca slots, dropping staticPropertyGlobal / staticPropertyInitGlobal metadata. Stores updated the stack slot but never marked the module init flag, so reads after the closure failed with Typed static property … must not be accessed before initialization.

The probe-reported unstable garbage integer on untyped static properties could not be reproduced on current master (post-#31894); the untyped closure write/read repro is stable 12 across repeated runs. This PR adds regression guards for that path and fixes the typed-static failure found while hunting.

Fix (PHP-in-PHP, no new runtime/ C)

  • ObjectStaticPropertyLlvm::fetch($forWrite) — skip typed-static uninit read guard on BP_VAR_W fetches (matches VM !$mutates in TYPE_STATIC_PROPERTY_FETCH)
  • JIT::assignOperand — before native scalar KIND_VALUE promotion / same-type direct store, route class static lvalues through staticPropertyStore so init flags are marked

Verification

# Typed repro (was fatal, now 12)
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/compile.php -o /tmp/t test/repro/issue_31965_typed_static_closure.php && for i in 1 2 3; do /tmp/t; done'
# → 12 / 12 / 12

# Untyped repro (stable across runs)
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/compile.php -o /tmp/u test/repro/issue_31965_static_prop_closure.php && for i in 1 2 3; do /tmp/u; done'
# → 12 / 12 / 12

./script/phpunit.sh --filter static_prop_closure
# OK (2 tests, 10 assertions)

./script/aot-smoke.sh
# aot-smoke: 8 passed, 0 failed

Did not run full ci-local.sh, compliance shards, or north-star5-verify --strict.

Made with Cursor

)

Typed static property writes inside closures were promoted to stack allocas,
dropping staticPropertyGlobal metadata so stores never marked the init flag.
Route native-scalar static lvalues through staticPropertyStore, skip the
typed-static read guard on BP_VAR_W fetches, and add AOT regression fixtures.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

AOT: static property read through a closure returns uninitialised memory (unstable between runs)

1 participant