kritzcreek added the bug label to Issue #9669.
kritzcreek opened issue #9669:
Thanks so much for working on implementing the gc proposal! When I tested it on my own small language I ran into a panic and managed to minify the example down to:
Test Case
Minimal reproduction:
use std::error::Error; use wasmtime::{Config, Engine, Instance, Module, Store}; fn main() -> Result<(), Box<dyn Error>> { let wat = "\ (module (rec (type (;0;) (func (result i32))) (type (;1;) (array (mut i32))) (type $Point (;2;) (struct (field $xs (mut (ref null 1))))) ) (export \"main\" (func $main)) (func $main (;0;) (type 0) (result i32) (local $p (ref null $Point)) i32.const 0 array.new_fixed 1 1 struct.new $Point local.set $p local.get $p struct.get $Point $xs i32.const 0 i32.const 1 array.set 1 local.get $p struct.get $Point $xs i32.const 0 array.get 1 ) )"; let engine = Engine::new(Config::new().wasm_function_references(true).wasm_gc(true))?; let mut store = Store::new(&engine, ()); let module = Module::new(&engine, wat)?; let instance = Instance::new(&mut store, &module, &[])?; let main_func = instance.get_typed_func::<(), i32>(&mut store, "main")?; let result = main_func.call(&mut store, ())?; println!("Result: {:?}", result); Ok(()) }
Panics with:
thread 'main' panicked at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\gc\enabled\drc.rs:238:13: every on-stack gc_ref inside a Wasm frame should have an entry in the VMGcRefActivationsTable; 0x20 is not in the table stack backtrace: 0: std::panicking::begin_panic_handler at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\std\src\panicking.rs:665 1: core::panicking::panic_fmt at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library\core\src\panicking.rs:74 2: wasmtime::runtime::vm::gc::enabled::drc::DrcHeap::trace at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\gc\enabled\drc.rs:238 3: wasmtime::runtime::vm::gc::enabled::drc::impl$9::collect_increment at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\gc\enabled\drc.rs:719 4: wasmtime::runtime::vm::gc::gc_runtime::GarbageCollection::collect<wasmtime::runtime::vm::gc::enabled::drc::DrcCollection> at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\gc\gc_runtime.rs:682 5: wasmtime::runtime::vm::gc::GcStore::gc at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\gc.rs:68 6: wasmtime::runtime::store::StoreOpaque::gc at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\store.rs:1629 7: wasmtime::runtime::store::impl$17::gc<tuple$<> > at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\store.rs:2645 8: wasmtime::runtime::vm::libcalls::gc at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\libcalls.rs:449 9: wasmtime::runtime::vm::libcalls::raw::gc::closure$0::closure$0 at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\libcalls.rs:115 10: wasmtime::runtime::vm::instance::Instance::from_vmctx<enum2$<core::result::Result<u32,anyhow::Error> >,wasmtime::runtime::vm::libcalls::raw::gc::closure$0::closure_env$0> at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\instance.rs:239 11: wasmtime::runtime::vm::libcalls::raw::gc::closure$0 at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\libcalls.rs:113 12: core::panic::unwind_safe::impl$25::call_once<enum2$<core::result::Result<u32,anyhow::Error> >,wasmtime::runtime::vm::libcalls::raw::gc::closure_env$0> at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\core\src\panic\unwind_safe.rs:272 13: std::panicking::try::do_call<core::panic::unwind_safe::AssertUnwindSafe<wasmtime::runtime::vm::libcalls::raw::gc::closure_env$0>,enum2$<core::result::Result<u32,anyhow::Error> > > at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\std\src\panicking.rs:557 14: core::iter::sources::once::impl$0::size_hint<wasmtime_environ::types::WasmSubType> 15: std::panicking::try at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\std\src\panicking.rs:521 16: std::panic::catch_unwind<core::panic::unwind_safe::AssertUnwindSafe<wasmtime::runtime::vm::libcalls::raw::gc::closure_env$0>,enum2$<core::result::Result<u32,anyhow::Error> > > at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\std\src\panic.rs:350 17: wasmtime::runtime::vm::traphandlers::catch_unwind_and_longjmp<enum2$<core::result::Result<u32,anyhow::Error> >,wasmtime::runtime::vm::libcalls::raw::gc::closure_env$0> at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\traphandlers.rs:136 18: wasmtime::runtime::vm::libcalls::raw::gc at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\libcalls.rs:112 19: <unknown> 20: <unknown> 21: <unknown> 22: wasmtime::runtime::func::typed::impl$1::call_raw::closure$0<tuple$<>,i32,tuple$<> > at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\func\typed.rs:217 23: wasmtime::runtime::vm::traphandlers::catch_traps::call_closure<wasmtime::runtime::func::typed::impl$1::call_raw::closure_env$0<tuple$<>,i32,tuple$<> > > at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\traphandlers.rs:290 24: wasmtime_setjmp_27_0_0 at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\helpers.c:72 25: wasmtime::runtime::vm::traphandlers::catch_traps::closure$1<wasmtime::runtime::func::typed::impl$1::call_raw::closure_env$0<tuple$<>,i32,tuple$<> > > at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\traphandlers.rs:267 26: wasmtime::runtime::vm::traphandlers::impl$3::with::closure$0<wasmtime::runtime::vm::traphandlers::catch_traps::closure_env$1<wasmtime::runtime::func::typed::impl$1::call_raw::closure_env$0<tuple$<>,i32,tuple$<> > > > at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\traphandlers.rs:414 27: wasmtime::runtime::vm::traphandlers::tls::set<i32,wasmtime::runtime::vm::traphandlers::impl$3::with::closure_env$0<wasmtime::runtime::vm::traphandlers::catch_traps::closure_env$1<wasmtime::runtime::func::typed::impl$1::call_raw::closure_env$0<tuple$<>,i32, at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\traphandlers.rs:790 28: wasmtime::runtime::vm::traphandlers::call_thread_state::CallThreadState::with<wasmtime::runtime::vm::traphandlers::catch_traps::closure_env$1<wasmtime::runtime::func::typed::impl$1::call_raw::closure_env$0<tuple$<>,i32,tuple$<> > > > at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\traphandlers.rs:414 29: wasmtime::runtime::vm::traphandlers::catch_traps<wasmtime::runtime::func::typed::impl$1::call_raw::closure_env$0<tuple$<>,i32,tuple$<> > > at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\vm\traphandlers.rs:259 30: wasmtime::runtime::func::invoke_wasm_and_catch_traps<tuple$<>,wasmtime::runtime::func::typed::impl$1::call_raw::closure_env$0<tuple$<>,i32,tuple$<> > > at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\func.rs:1613 31: wasmtime::runtime::func::typed::TypedFunc<tuple$<>,i32>::call_raw<tuple$<>,i32,tuple$<> > at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\func\typed.rs:214 32: wasmtime::runtime::func::typed::TypedFunc<tuple$<>,i32>::call<tuple$<>,i32,ref_mut$<wasmtime::runtime::store::Store<tuple$<> > > > at C:\Users\creek\.cargo\registry\src\index.crates.io-6f17d22bba15001f\wasmtime-27.0.0\src\runtime\func\typed.rs:107 33: nemo::main at .\crates\cli\src\main.rs:34 34: core::ops::function::FnOnce::call_once<enum2$<core::result::Result<tuple$<>,alloc::boxed::Box<dyn$<core::error::Error>,alloc::alloc::Global> > > (*)(),tuple$<> > at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c\library\core\src\ops\function.rs:250
Versions and Environment
Wasmtime version or commit: 27.0.0
Operating system: Verified on Windows and Mac
Architecture: x86_64 and arm64
pchickey assigned fitzgen to issue #9669.
pchickey commented on issue #9669:
Nick is on vacation right now so this may need to wait until he's back.
alexcrichton added the wasm-proposal:gc label to Issue #9669.
fitzgen commented on issue #9669:
Thanks for filing an issue and providing a
.wat
test case! Back from vacation now and slowly catching up on things.As I just mentioned in another issue, at this moment the default collector (DRC) does not yet transitively decrement reference counts, so many acyclic garbage objects will be leaked (in this case, the array objects referenced from
$Point
objects).This acyclic leakage is not fundamental nor intended long term, it just reflects that this is a young, WIP implementation. (Cycles will always leak with this collector, on the other hand, since it is a simple reference-counting collector and does not include a cycle collector.)
fitzgen commented on issue #9669:
Ah but I see that I didn't read closely enough, and that this is finding a stack map issue
fitzgen edited a comment on issue #9669:
Ah but I see that I didn't read closely enough, and that this is finding a stack map issue, which the panic is a symptom of. This is a separate issue, unrelated to the leakage.
14427 commented on issue #9669:
I ran into what appears to be the same issue. It only seems to occur for the
DeferredReferenceCounting
collector, switching to theNull
collector causes the test to pass. I'm using wasmtime 29.0.1 on OS X.Minimized test case:
#[test] fn test_bug() { let program = r#" (module (type $empty (struct)) (type $thing (struct (field $field1 (ref $empty)) (field $field2 (ref $empty)) )) (func (export "run") (local $object (ref $thing)) struct.new $empty struct.new $empty struct.new $thing local.tee $object struct.get $thing $field1 drop local.get $object struct.get $thing $field2 drop ) ) "#; let mut config = Config::new(); config.wasm_gc(true); config.collector(Collector::DeferredReferenceCounting); // Switch to Null here to make test pass let engine = Engine::new(&config).unwrap(); let mut store = Store::new(&engine, ()); let module = Module::new(&engine, program).unwrap(); let instance = Instance::new(&mut store, &module, &[]).unwrap(); let func = instance.get_typed_func::<(), ()>(&mut store, "run").unwrap(); func.call(&mut store, ()).unwrap(); }
fitzgen commented on issue #9669:
The minimized test case is super helpful, thanks! I've been running
creduce
on the original test case's.wat
disassembly and after five days its still at ~900KiB.
fitzgen commented on issue #9669:
Err whoops I've actually been trying to minimize https://github.com/bytecodealliance/wasmtime/issues/9714, not this issue's test case.
vouillon commented on issue #9669:
I'm not completely sure this is the same issue, but this small module fails in the same way.
(module (type $0 (sub (struct))) (type $1 (func (result (ref eq)))) (global $global$0 (ref eq) (struct.new_default $0)) (export "" (func $0)) (func $0 (result (ref eq)) (local $0 (ref eq)) (local.set $0 (struct.new_default $0) ) (drop (global.get $global$0) ) (local.get $0) ) )
Last updated: Feb 28 2025 at 03:10 UTC