| 914 | #[test] |
| 915 | #[cfg_attr(miri, ignore)] |
| 916 | fn host_structref_has_trace_info_for_gc() -> Result<()> { |
| 917 | for collector in [Collector::Copying, Collector::DeferredReferenceCounting] { |
| 918 | println!("Using GC collector: {collector:?}"); |
| 919 | |
| 920 | let mut config = Config::new(); |
| 921 | config.wasm_exceptions(true).wasm_gc(true); |
| 922 | config.collector(collector); |
| 923 | |
| 924 | let engine = Engine::new(&config)?; |
| 925 | |
| 926 | // Create a store and allocate the GC store by instantiating a module |
| 927 | let mut store = Store::new(&engine, ()); |
| 928 | let module = Module::new( |
| 929 | &engine, |
| 930 | r#"(module |
| 931 | (global (export "g") (mut structref) (ref.null struct)) |
| 932 | (table 1 anyref) |
| 933 | )"#, |
| 934 | )?; |
| 935 | let instance = Instance::new(&mut store, &module, &[])?; |
| 936 | let g = instance.get_global(&mut store, "g").unwrap(); |
| 937 | |
| 938 | // Allocate a host structref object in a nested scope and put it into the |
| 939 | // module that was just allocated. |
| 940 | let struct_ty = StructType::new( |
| 941 | &engine, |
| 942 | [FieldType::new(Mutability::Const, StorageType::I8)], |
| 943 | )?; |
| 944 | let structpre = StructRefPre::new(&mut store, struct_ty.clone()); |
| 945 | { |
| 946 | let mut scope = RootScope::new(&mut store); |
| 947 | let s = StructRef::new(&mut scope, &structpre, &[Val::I32(29)])?; |
| 948 | g.set(&mut scope, Val::AnyRef(Some(s.into())))?; |
| 949 | } |
| 950 | |
| 951 | // The structref should stay alive and be traced properly... |
| 952 | store.gc(None)?; |
| 953 | |
| 954 | assert!(matches!(g.get(&mut store), Val::AnyRef(Some(_)))); |
| 955 | } |
| 956 | |
| 957 | Ok(()) |
| 958 | } |