Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Winch typed select can omit a live GC reference from stack maps

Chiusa
#14,451 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
62/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
rust, wasm
Ambito
compilers

Direzione di ricerca

Run the provided public-embedding reproducer with both null and copying collectors, then inspect visit_typed_select and visit_select in winch/codegen/src/visitor.rs alongside needs_stack_map and calculate_stack_map_offsets. Confirm the typed-select result retains a reference shadow type, the call-site stack map includes it, and the copying-collector case survives.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug wasm-proposal:gc winch

Summary

When Winch compiles a typed select whose result is a GC reference, the result's shadow type can incorrectly come from the second operand rather than the declared result type.

If the first operand is a non-null externref, the second operand is ref.null extern, and the condition selects the first operand, the runtime value is a real GC reference but its shadow type becomes I32.

At a later call site this causes the reference to be omitted from the stack map. With the copying collector, the referenced object can then be reclaimed or relocated without the stack copy being updated.

This was reproduced on the latest commit.

Technical Details

The missing check is the shadow-type filter used to decide whether a value needs a stack map. needs_stack_map (winch/codegen/src/stack.rs:315-327) is unconditionally false for I32, so a live GC reference whose shadow type is I32 neither increments gc_ref_count nor satisfies the collection condition in CodeGenContext::calculate_stack_map_offsets (winch/codegen/src/codegen/context.rs:663-695).

Because that function then returns an empty table, FnCall::emit (winch/codegen/src/codegen/call.rs:108-113) skips emitting any stack map.

The relevant data flow is:

  • visit_ref_null (winch/codegen/src/visitor.rs:2232-2252) pushes ref.null extern/exn as Val::i32(0).
  • visit_typed_select (winch/codegen/src/visitor.rs:2228-2230) ignores the instruction's declared result type _ty and dispatches to visit_select.
  • visit_select (winch/codegen/src/visitor.rs:2208-2226) pushes the result using the shadow type of the second operand (stack.push(val2.into())).
  • When operand 1 is a real GC reference, operand 2 is ref.null, and the condition is non-zero, the runtime result is the reference but its shadow type is I32.
  • At the next call, FnCall::emit spills the value, but calculate_stack_map_offsets returns an empty table, so no stack map is emitted.
  • During collection, Store::trace_wasm_stack_frame (crates/wasmtime/src/runtime/store/gc.rs:771-786) only treats slots present in the stack map as Wasm stack roots.

Reproduction

Tested at commit:

ff7896b6d97a424aed430a48a186773fd163667f

The reproducer uses the public embedding API with Winch and compares a normal reference path with the typed-select path.

Guest input:

(module
  (import "" "make" (func $make (result externref)))
  (import "" "gc"   (func $gc))

  (func (export "control") (result externref)
    call $make
    call $gc)

  (func (export "bug") (result externref)
    call $make
    ref.null extern
    i32.const 1
    select (result externref)
    call $gc)
)

With the null collector, both cases survive.

With the copying collector, the control case survives while the typed-select case loses the referenced object:

collector=null
  [control] data=Ok(0xdecaf)  SURVIVED
  [bug] data=Ok(0xdecaf)  SURVIVED

collector=copying
  [control] data=Ok(0xdecaf)  SURVIVED
  [bug] data=Err(BUG: invalid `ExternRefHostDataId`)  HOST-DATA-SWEPT

SUMMARY null_bug=Survived copying_control=Survived copying_bug=Swept
PROBE_RESULT: reproduced

The two cases differ only in whether the reference passes through the typed select, which appears to isolate the problem to the shadow type used for the select result.

Suggested Fix

visit_typed_select (winch/codegen/src/visitor.rs:2228-2230) should honor the instruction's declared result type instead of discarding _ty.

visit_select (winch/codegen/src/visitor.rs:2208-2226) should not derive the pushed shadow type from the second operand when the declared result is a reference type. The pushed value needs to retain a reference shadow type so that needs_stack_map returns true and the live reference is included in the call-site stack map.

Lingua principale
Rust
Stelle
18.7k
Fork
1.9k
Merge medio
23h 53m
PR unite (30g)
205

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di bytecodealliance/wasmtime

Tutte le issue di bytecodealliance/wasmtime

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.