Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

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

オープン
#14,451 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
62/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
rust, wasm
領域
compilers

調査の方向性

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.

索引モデルが issue の本文から書いたものです。

説明

bug

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.

主要言語
Rust
スター
18.7k
フォーク
1.8k
平均マージ
1日 7時間
マージ済み PR(30日)
140

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

bytecodealliance/wasmtime のほかの issue

bytecodealliance/wasmtime の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。