VM import suspension for browser lazy loading

Bytecode compiler now emits OP_PERFORM for (import ...) and compiles
(define-library ...) bodies. The VM stores the import request in
globals["__io_request"] and stops the run loop — no exceptions needed.
vm-execute-module returns a suspension dict, vm-resume-module continues.

Browser: sx_browser.ml detects suspension dicts from execute_module and
returns JS {suspended, op, request, resume} objects. The sx-platform.js
while loop handles cascading suspensions via handleImportSuspension.

13 modules load via .sxbc bytecode in 226ms (manifest-driven), both
islands hydrate, all handlers wired. 2650/2650 tests pass including
6 new vm-import-suspension tests.

Also: consolidated sx-platform-2.js → sx-platform.js, fixed
vm-execute-module missing code-from-value call, fixed bootstrap.py
protocol registry transpiler issues.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 17:11:12 +00:00
parent efd0d9168f
commit 2727577702
43 changed files with 4672 additions and 3991 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -62,7 +62,8 @@
vm-run
vm-step
vm-call-closure
vm-execute-module)
vm-execute-module
vm-resume-module)
(begin
(define make-upvalue-cell (fn (value) {:uv-value value}))
(define uv-get (fn (cell) (get cell "uv-value")))
@@ -443,7 +444,11 @@
(if
(>= (frame-ip frame) (len bc))
(vm-set-frames! vm (list))
(do (vm-step vm frame rest-frames bc consts) (loop))))))))
(do
(vm-step vm frame rest-frames bc consts)
(when
(nil? (get (vm-globals-ref vm) "__io_request"))
(loop)))))))))
(loop)))
(define
vm-step
@@ -595,8 +600,7 @@
(= op 112)
(let
((request (vm-pop vm)))
(error
(str "VM: IO suspension (OP_PERFORM) — request: " request)))
(dict-set! (vm-globals-ref vm) "__io_request" request))
:else (error (str "VM: unknown opcode " op))))))
(define
vm-call-closure
@@ -614,14 +618,29 @@
(fn
(code globals)
(let
((closure (make-vm-closure code (list) "module" globals nil))
(vm (make-vm globals)))
((vm-code (code-from-value code)) (vm (make-vm globals)))
(let
((frame (make-vm-frame closure 0)))
(pad-n-nils vm (code-locals code))
((closure (make-vm-closure vm-code (list) "module" globals nil))
(frame (make-vm-frame closure 0)))
(pad-n-nils vm (code-locals vm-code))
(vm-set-frames! vm (list frame))
(vm-run vm)
(vm-pop vm))))))) ;; end define-library
(let
((io-req (get (vm-globals-ref vm) "__io_request")))
(if (nil? io-req) (vm-pop vm) {:vm vm :suspended true :op "import" :request io-req}))))))
(define
vm-resume-module
(fn
(suspended-result)
"Resume a suspended VM after IO (import) has been resolved.\n Clears __io_request in globals, pushes nil (import result), re-runs."
(let
((vm (get suspended-result :vm)))
(dict-set! (vm-globals-ref vm) "__io_request" nil)
(vm-push vm nil)
(vm-run vm)
(let
((io-req (get (vm-globals-ref vm) "__io_request")))
(if (nil? io-req) (vm-pop vm) {:vm vm :suspended true :op "import" :request io-req}))))))) ;; end define-library
;; Re-export to global namespace for backward compatibility
(import (sx vm))