From cb0c5c22a81a940753d632a21ed3d7f101e0f6e3 Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 22 May 2026 14:52:47 +0000 Subject: [PATCH] =?UTF-8?q?feat(arje-wasm):=20bump=20wasmi=200.40=20?= =?UTF-8?q?=E2=86=92=201.0=20=E2=80=94=20unifica=20el=20runtime=20WASM=20c?= =?UTF-8?q?on=20renaser?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit brahman y renaser ya corren la misma versión de wasmi (1.0): el ABI WASM del host es idéntico en Linux y en bare-metal. Desbloquea el Paso 3 de la integración (converger el ABI Card/WASM). El delta de la API resultó pequeño: - `Linker::instantiate` + `InstancePre::start` → `instantiate_and_start` (wasmi 1.0 fusiona instanciación y arranque). - Motor configurado en `CompilationMode::Eager` — traducción completa del módulo por adelantado, comportamiento predecible, paridad con el motor wasmi del kernel de renaser. Primer test de arje-wasm: `demo_corre_en_wasmi_1` ejecuta el módulo demo de punta a punta (WAT→wasm, instanciación, host imports log/exit). arje-zero (PID 1, consumidor) compila sin cambios. Co-Authored-By: Claude Opus 4.7 --- Cargo.lock | 37 +++++++++--------------- Cargo.toml | 4 ++- crates/runtime/arje-wasm/src/lib.rs | 45 +++++++++++++++++++++++++---- 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 605c158..2cd2d81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7988,12 +7988,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "multi-stash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" - [[package]] name = "multiaddr" version = "0.18.2" @@ -12852,9 +12846,9 @@ dependencies = [ [[package]] name = "string-interner" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a3275464d7a9f2d4cac57c89c2ef96a8524dba2864c8d6f82e3980baf136f9b" +checksum = "23de088478b31c349c9ba67816fa55d9355232d63c3afea8bf513e31f0f1d2c0" dependencies = [ "hashbrown 0.15.5", "serde", @@ -14681,53 +14675,50 @@ dependencies = [ [[package]] name = "wasmi" -version = "0.40.0" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19af97fcb96045dd1d6b4d23e2b4abdbbe81723dbc5c9f016eb52145b320063" +checksum = "22bf475363d09d960b48275c4ea9403051add498a9d80c64dbc91edabab9d1d0" dependencies = [ - "arrayvec 0.7.6", - "multi-stash", - "smallvec", "spin", "wasmi_collections", "wasmi_core", "wasmi_ir", - "wasmparser 0.221.3", + "wasmparser 0.228.0", + "wat", ] [[package]] name = "wasmi_collections" -version = "0.40.0" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e80d6b275b1c922021939d561574bf376613493ae2b61c6963b15db0e8813562" +checksum = "85851acbdffd675a9b699b3590406a1d37fc1e1fd073743c7c9cf47c59caacba" dependencies = [ "string-interner", ] [[package]] name = "wasmi_core" -version = "0.40.0" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a8c51482cc32d31c2c7ff211cd2bedd73c5bd057ba16a2ed0110e7a96097c33" +checksum = "ef64cf60195d1f937dbaed592a5afce3e6d86868fb8070c5255bc41539d68f9d" dependencies = [ - "downcast-rs", "libm", ] [[package]] name = "wasmi_ir" -version = "0.40.0" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e431a14c186db59212a88516788bd68ed51f87aa1e08d1df742522867b5289a" +checksum = "5dcb572ce4400e06b5475819f3d6b9048513efbca785f0b9ef3a41747f944fd8" dependencies = [ "wasmi_core", ] [[package]] name = "wasmparser" -version = "0.221.3" +version = "0.228.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d06bfa36ab3ac2be0dee563380147a5b81ba10dd8885d7fbbc9eb574be67d185" +checksum = "4abf1132c1fdf747d56bbc1bb52152400c70f336870f968b85e89ea422198ae3" dependencies = [ "bitflags 2.11.1", "indexmap 2.14.0", diff --git a/Cargo.toml b/Cargo.toml index 5209af0..dcb612f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -358,7 +358,9 @@ argon2 = "0.5" rand = "0.8" # === WASM (arje) === -wasmi = "0.40" +# wasmi 1.0: unifica la versión con renaser (su kernel ya corre 1.0), para +# que el ABI WASM del host sea idéntico en Linux y en bare-metal. +wasmi = "1.0" wat = "1" # === Storage / DB === diff --git a/crates/runtime/arje-wasm/src/lib.rs b/crates/runtime/arje-wasm/src/lib.rs index 4b4461d..6c08d87 100644 --- a/crates/runtime/arje-wasm/src/lib.rs +++ b/crates/runtime/arje-wasm/src/lib.rs @@ -15,7 +15,7 @@ use arje_card::EntityCard; use std::sync::atomic::{AtomicI32, Ordering}; use std::sync::Arc; use tracing::{error, info, warn}; -use wasmi::{Caller, Engine, Linker, Memory, Module, Store}; +use wasmi::{Caller, CompilationMode, Config, Engine, Linker, Memory, Module, Store}; /// Estado por instancia Wasm. Se accede tanto desde host imports (vía /// `Caller::data()`) como desde el thread runner para estado de salida. @@ -45,7 +45,13 @@ pub fn incarnate_wasm(card: &EntityCard, module_bytes: Vec, entry: String) - } fn run_wasm(ente: WasmEnte, module_bytes: &[u8], entry: &str) -> anyhow::Result<()> { - let engine = Engine::default(); + // Compilación ansiosa (Eager): el módulo se traduce entero ahora, no + // perezosamente bajo demanda. Da un comportamiento predecible y + // paridad con el motor wasmi del kernel de renaser — ambos en + // wasmi 1.0, mismo ABI de host en Linux y en bare-metal. + let mut config = Config::default(); + config.compilation_mode(CompilationMode::Eager); + let engine = Engine::new(&config); let module = Module::new(&engine, module_bytes) .map_err(|e| anyhow::anyhow!("Wasm module compile: {e}"))?; let mut store = Store::new(&engine, ente); @@ -59,10 +65,13 @@ fn run_wasm(ente: WasmEnte, module_bytes: &[u8], entry: &str) -> anyhow::Result< caller.data_mut().exit_code.store(code, Ordering::Relaxed); })?; - let pre = linker.instantiate(&mut store, &module) + // wasmi 1.0 fusiona instanciación y arranque: `instantiate_and_start` + // instancia el módulo y ejecuta su sección `(start)` si la tuviera + // (este módulo no la tiene — su `_start` es un export convencional + // que el caller invoca explícitamente más abajo). + let instance = linker + .instantiate_and_start(&mut store, &module) .map_err(|e| anyhow::anyhow!("Wasm instantiate: {e}"))?; - let instance = pre.start(&mut store) - .map_err(|e| anyhow::anyhow!("Wasm start: {e}"))?; let func = instance.get_typed_func::<(), ()>(&store, entry) .map_err(|e| anyhow::anyhow!("Wasm get_func {entry}: {e}"))?; @@ -116,3 +125,29 @@ pub fn demo_module_bytes() -> anyhow::Result> { "#; Ok(wat::parse_str(wat)?) } + +#[cfg(test)] +mod tests { + use super::*; + + /// Verifica el runtime de punta a punta sobre wasmi 1.0: WAT → wasm, + /// motor Eager, `Module::new`, `Linker` + `func_wrap`, + /// `instantiate_and_start`, llamada a `_start`, y los host imports + /// `ente.log` / `ente.exit`. Que compile no basta — debe ejecutar. + #[test] + fn demo_corre_en_wasmi_1() { + let bytes = demo_module_bytes().expect("el WAT del demo compila a wasm"); + let exit_code = Arc::new(AtomicI32::new(-99)); + let ente = WasmEnte { + id: ulid::Ulid::new(), + label: "test".into(), + exit_code: exit_code.clone(), + }; + run_wasm(ente, &bytes, "_start").expect("el módulo demo ejecuta sin error"); + assert_eq!( + exit_code.load(Ordering::Relaxed), + 0, + "el host import `ente.exit(0)` fijó el código de salida" + ); + } +}