Winch typed select can omit a live GC reference from stack maps
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
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
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) pushesref.null extern/exnasVal::i32(0).visit_typed_select(winch/codegen/src/visitor.rs:2228-2230) ignores the instruction's declared result type_tyand dispatches tovisit_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 isI32. - At the next call,
FnCall::emitspills the value, butcalculate_stack_map_offsetsreturns 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
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di bytecodealliance/wasmtime
-
bug cranelift
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
bytecodealliance/wasmtime#14572 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug cranelift
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
bytecodealliance/wasmtime#14569 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug cranelift:area:interpreter
Difficoltà 2/5 Meno di un'ora Idoneità per principianti 86/100
bytecodealliance/wasmtime#14568 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug wasm-proposal:exceptions wasmtime:debugging
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
bytecodealliance/wasmtime#14102 ·
I maintainer di solito rispondono entro 1 giorno
-
wasm-proposal:gc
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
bytecodealliance/wasmtime#13808 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di bytecodealliance/wasmtime
Issue simili
-
✨ enhancement needs-discussion
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
-
docs(openclaw): RTK_REWRITE_HOST relaxes every default ask, not only commands no rule matchedApertaarea:docs documentation good first issue priority:low
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
rtk-ai/rtk#4500 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
triage:accepted
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
open-telemetry/otel-arrow#4343 ·
I maintainer di solito rispondono entro 2 giorni
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
mishraprafful/multihull#150 ·
I maintainer di solito rispondono entro 1 giorno
-
area:tooling bug good first issue priority:P3
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
michaelnavazhylau/ngspice-rs#129 ·
I maintainer di solito rispondono entro 1 giorno