Fix JIT mutable closure bug: vm-global-get now checks closure env first

vm-global-get checked vm.globals before closure-env, while vm-global-set
wrote to closure-env first. This asymmetry meant set! mutations to mutable
closure variables (e.g. parser position counters) were invisible to sibling
closures reading via JIT — they saw stale snapshots in the globals table.

Reversed vm-global-get lookup order: closure env → globals → primitives,
matching vm-global-set. Also enabled JIT in the MCP harness (compiler.sx
loading, env_bind hook for live globals sync, jit_try_call hook) so
sx_harness_eval exercises the same code path as the server.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-06 12:08:08 +00:00
parent 022c4f7f26
commit 3a9d113537
2 changed files with 68 additions and 11 deletions

View File

@@ -297,27 +297,32 @@
vm-global-get
(fn
(vm frame name)
"Look up a global: globals table → closure env → primitives → HO wrappers"
"Look up a global: closure env → globals table → primitives → HO forms"
(let
((globals (vm-globals-ref vm)))
((closure-env (get (frame-closure frame) "vm-closure-env")))
(if
(has-key? globals name)
(get globals name)
(nil? closure-env)
(let
((closure-env (-> frame frame-closure closure-env)))
((globals (vm-globals-ref vm)))
(if
(nil? closure-env)
(has-key? globals name)
(get globals name)
(cek-try
(fn () (get-primitive name))
(fn (e) (vm-resolve-ho-form vm name)))
(fn (e) (vm-resolve-ho-form vm name)))))
(let
((found (env-walk closure-env name)))
(if
(nil? found)
(let
((found (env-walk closure-env name)))
((globals (vm-globals-ref vm)))
(if
(nil? found)
(has-key? globals name)
(get globals name)
(cek-try
(fn () (get-primitive name))
(fn (e) (vm-resolve-ho-form vm name)))
found))))))))
(fn (e) (vm-resolve-ho-form vm name)))))
found))))))
(define
vm-resolve-ho-form
(fn