Skip to content
Merged
Show file tree
Hide file tree
Changes from 62 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
7e88888
Initial work
TartanLlama Sep 16, 2025
275344e
Almost compiling
TartanLlama Sep 16, 2025
9cce52d
Partially working
TartanLlama Sep 19, 2025
6e6b83f
Cleanup
TartanLlama Sep 29, 2025
b78aa86
Merge branch 'main' into sy/coop_threading
TartanLlama Sep 29, 2025
4fb67b3
Fix merge
TartanLlama Sep 30, 2025
aaa1810
Cancellation and suspension refactoring
TartanLlama Sep 30, 2025
5a11d91
Remove printlns
TartanLlama Sep 30, 2025
08de34c
Test with several threads
TartanLlama Oct 1, 2025
3b4790e
More testing
TartanLlama Oct 1, 2025
7d5f98d
Cancellation
TartanLlama Oct 3, 2025
607e680
Fix cancellation for explicit suspends
TartanLlama Oct 3, 2025
73668c7
Finish cancellation test
TartanLlama Oct 3, 2025
aa565b2
Store threads in the instance table
TartanLlama Oct 4, 2025
67c3e90
Deletion almost there
TartanLlama Oct 7, 2025
4c811f7
Tests all pass
TartanLlama Oct 7, 2025
bac5c5a
Tighten up task deletion
TartanLlama Oct 9, 2025
af20cc7
Set thread state correctly
TartanLlama Oct 9, 2025
6c5c242
Store pairs of thread and task ids
TartanLlama Oct 9, 2025
c534023
Remove lift abi members
TartanLlama Oct 9, 2025
2d66c89
Cleanup unnecessary change
TartanLlama Oct 9, 2025
a650fe9
More cleanup
TartanLlama Oct 9, 2025
2718e65
Cleanup
TartanLlama Oct 9, 2025
474e156
Revert cargo changes
TartanLlama Oct 9, 2025
02c1303
Revert cargo changes
TartanLlama Oct 9, 2025
8dded53
Comments
TartanLlama Oct 9, 2025
8a97255
Comments on test
TartanLlama Oct 9, 2025
8f87514
Merge remote-tracking branch 'origin/main' into sy/coop_threading
TartanLlama Oct 10, 2025
a9a6ac7
Update comments
TartanLlama Oct 10, 2025
13fd954
Update comments
TartanLlama Oct 10, 2025
d287f84
Add space that was removed in an earlier commit
TartanLlama Oct 10, 2025
74fe6af
Cleanup
TartanLlama Oct 10, 2025
17a481c
Delete threads from the instance table
TartanLlama Oct 10, 2025
9fea7c3
Revert cargo file
TartanLlama Oct 10, 2025
6622b48
Remove dead code
TartanLlama Oct 10, 2025
a6a7af3
Clippy changes
TartanLlama Oct 10, 2025
ebe6237
Clippy
TartanLlama Oct 10, 2025
8eae443
Revert unnecessary changes
TartanLlama Oct 17, 2025
2c448f1
Revert unnecessary changes
TartanLlama Oct 17, 2025
5445d85
Revert unnecessary changes
TartanLlama Oct 17, 2025
a9a0e26
Revert unnecessary changes
TartanLlama Oct 17, 2025
80c130e
Revert unnecessary changes
TartanLlama Oct 17, 2025
f34811e
Review comments
TartanLlama Oct 17, 2025
5aeaf25
Review feedback
TartanLlama Oct 17, 2025
d01a51d
Make thread IDs per-component-instance
TartanLlama Oct 20, 2025
3ca304a
Merge branch 'main' into sy/coop_threading
TartanLlama Oct 21, 2025
5a5f67b
Fix config
TartanLlama Oct 21, 2025
249f76b
Tighten up completion
TartanLlama Oct 21, 2025
a3ed6d7
Clippy
TartanLlama Oct 21, 2025
6de172f
Trigger full PR test
TartanLlama Oct 21, 2025
ea94efb
Move funcref table reading
TartanLlama Oct 21, 2025
72292d8
Remove unused import
TartanLlama Oct 21, 2025
866cde6
Formatting
TartanLlama Oct 21, 2025
9eb8727
Rename RemoveOnDrop
TartanLlama Oct 22, 2025
6eb5f65
Review feedback
TartanLlama Oct 22, 2025
44ea1c8
Review feedback
TartanLlama Oct 22, 2025
7de1cbc
Move start thread closure
TartanLlama Oct 22, 2025
25a711f
Review feedback
TartanLlama Oct 22, 2025
c576d1c
Review feedback
TartanLlama Oct 22, 2025
0061501
Correct feature for import
TartanLlama Oct 22, 2025
773baad
Review feedback
TartanLlama Oct 23, 2025
1c76856
Disable failing tests
TartanLlama Oct 23, 2025
4c4aa63
Enable fixed tests
TartanLlama Oct 27, 2025
9f05792
Review feedback
TartanLlama Oct 27, 2025
77b0789
Readd tests
TartanLlama Oct 27, 2025
1de6f96
Ignore task deletion test with Miri
TartanLlama Oct 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/cli-flags/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,9 @@ wasmtime_option_group! {
/// Component model support for async lifting/lowering: this corresponds
/// to the 🚟 emoji in the component model specification.
pub component_model_async_stackful: Option<bool>,
/// Component model support for threading: this corresponds
/// to the 🧵 emoji in the component model specification.
pub component_model_threading: Option<bool>,
/// Component model support for `error-context`: this corresponds
/// to the 📝 emoji in the component model specification.
pub component_model_error_context: Option<bool>,
Expand Down Expand Up @@ -1059,6 +1062,7 @@ impl CommonOptions {
("component-model-async", component_model_async, wasm_component_model_async)
("component-model-async", component_model_async_builtins, wasm_component_model_async_builtins)
("component-model-async", component_model_async_stackful, wasm_component_model_async_stackful)
("component-model-async", component_model_threading, wasm_component_model_threading)
("component-model", component_model_error_context, wasm_component_model_error_context)
("threads", threads, wasm_threads)
("gc", gc, wasm_gc)
Expand Down
88 changes: 88 additions & 0 deletions crates/cranelift/src/compiler/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -871,6 +871,94 @@ impl<'a> TrampolineCompiler<'a> {
},
);
}
Trampoline::ThreadIndex => {
self.translate_libcall(
host::thread_index,
TrapSentinel::NegativeOne,
WasmArgs::InRegisters,
|_, _| {},
);
}
Trampoline::ThreadNewIndirect {
instance,
start_func_table_idx,
start_func_ty_idx,
} => {
self.translate_libcall(
host::thread_new_indirect,
TrapSentinel::NegativeOne,
WasmArgs::InRegisters,
|me, params| {
params.push(me.index_value(*instance));
params.push(me.index_value(*start_func_table_idx));
params.push(me.index_value(*start_func_ty_idx));
},
);
}
Trampoline::ThreadSwitchTo {
instance,
cancellable,
} => {
self.translate_libcall(
host::thread_switch_to,
TrapSentinel::NegativeOne,
WasmArgs::InRegisters,
|me, params| {
params.push(me.index_value(*instance));
params.push(
me.builder
.ins()
.iconst(ir::types::I8, i64::from(*cancellable)),
);
},
);
}
Trampoline::ThreadSuspend {
instance,
cancellable,
} => {
self.translate_libcall(
host::thread_suspend,
TrapSentinel::NegativeOne,
WasmArgs::InRegisters,
|me, params| {
params.push(me.index_value(*instance));
params.push(
me.builder
.ins()
.iconst(ir::types::I8, i64::from(*cancellable)),
);
},
);
}
Trampoline::ThreadResumeLater { instance } => {
self.translate_libcall(
host::thread_resume_later,
TrapSentinel::Falsy,
WasmArgs::InRegisters,
|me, params| {
params.push(me.index_value(*instance));
},
);
}
Trampoline::ThreadYieldTo {
instance,
cancellable,
} => {
self.translate_libcall(
host::thread_yield_to,
TrapSentinel::NegativeOne,
WasmArgs::InRegisters,
|me, params| {
params.push(me.index_value(*instance));
params.push(
me.builder
.ins()
.iconst(ir::types::I8, i64::from(*cancellable)),
);
},
);
}
}
}

Expand Down
12 changes: 12 additions & 0 deletions crates/environ/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,18 @@ macro_rules! foreach_builtin_component_function {
context_get(vmctx: vmctx, caller_instance: u32, slot: u32) -> u64;
#[cfg(feature = "component-model-async")]
context_set(vmctx: vmctx, caller_instance: u32, slot: u32, val: u32) -> bool;
#[cfg(feature = "component-model-async")]
thread_index(vmctx: vmctx) -> u64;
#[cfg(feature = "component-model-async")]
thread_new_indirect(vmctx: vmctx, caller_instance: u32, func_ty_id: u32, func_table_idx: u32, func_idx: u32, context: u32) -> u64;
#[cfg(feature = "component-model-async")]
thread_switch_to(vmctx: vmctx, caller_instance: u32, cancellable: u8, thread_idx: u32) -> u32;
#[cfg(feature = "component-model-async")]
thread_suspend(vmctx: vmctx, caller_instance: u32, cancellable: u8) -> u32;
#[cfg(feature = "component-model-async")]
thread_resume_later(vmctx: vmctx, caller_instance: u32, thread_idx: u32) -> bool;
#[cfg(feature = "component-model-async")]
thread_yield_to(vmctx: vmctx, caller_instance: u32, cancellable: u8, thread_idx: u32) -> u32;

trap(vmctx: vmctx, code: u8) -> bool;

Expand Down
69 changes: 68 additions & 1 deletion crates/environ/src/component/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ pub struct ComponentDfg {
/// Same as `reallocs`, but for post-return.
pub post_returns: Intern<PostReturnId, CoreDef>,

/// Same as `reallocs`, but for post-return.
/// Same as `reallocs`, but for memories.
pub memories: Intern<MemoryId, CoreExport<MemoryIndex>>,

/// Same as `reallocs`, but for tables.
pub tables: Intern<TableId, CoreExport<TableIndex>>,

/// Metadata about identified fused adapters.
///
/// Note that this list is required to be populated in-order where the
Expand Down Expand Up @@ -483,6 +486,27 @@ pub enum Trampoline {
instance: RuntimeComponentInstanceIndex,
slot: u32,
},
ThreadIndex,
ThreadNewIndirect {
instance: RuntimeComponentInstanceIndex,
start_func_ty_idx: ComponentTypeIndex,
start_func_table_id: TableId,
},
ThreadSwitchTo {
instance: RuntimeComponentInstanceIndex,
cancellable: bool,
},
ThreadSuspend {
instance: RuntimeComponentInstanceIndex,
cancellable: bool,
},
ThreadResumeLater {
instance: RuntimeComponentInstanceIndex,
},
ThreadYieldTo {
instance: RuntimeComponentInstanceIndex,
cancellable: bool,
},
}

#[derive(Copy, Clone, Hash, Eq, PartialEq)]
Expand Down Expand Up @@ -833,6 +857,15 @@ impl LinearizeDfg<'_> {
)
}

fn runtime_table(&mut self, table: TableId) -> RuntimeTableIndex {
self.intern(
table,
|me| &mut me.runtime_tables,
|me, table| me.core_export(&me.dfg.tables[table]),
|index, export| GlobalInitializer::ExtractTable(ExtractTable { index, export }),
)
}

fn runtime_realloc(&mut self, realloc: ReallocId) -> RuntimeReallocIndex {
self.intern(
realloc,
Expand Down Expand Up @@ -1135,6 +1168,40 @@ impl LinearizeDfg<'_> {
instance: *instance,
slot: *slot,
},
Trampoline::ThreadIndex => info::Trampoline::ThreadIndex,
Trampoline::ThreadNewIndirect {
instance,
start_func_ty_idx,
start_func_table_id,
} => info::Trampoline::ThreadNewIndirect {
instance: *instance,
start_func_ty_idx: *start_func_ty_idx,
start_func_table_idx: self.runtime_table(*start_func_table_id),
},
Trampoline::ThreadSwitchTo {
instance,
cancellable,
} => info::Trampoline::ThreadSwitchTo {
instance: *instance,
cancellable: *cancellable,
},
Trampoline::ThreadSuspend {
instance,
cancellable,
} => info::Trampoline::ThreadSuspend {
instance: *instance,
cancellable: *cancellable,
},
Trampoline::ThreadResumeLater { instance } => info::Trampoline::ThreadResumeLater {
instance: *instance,
},
Trampoline::ThreadYieldTo {
instance,
cancellable,
} => info::Trampoline::ThreadYieldTo {
instance: *instance,
cancellable: *cancellable,
},
};
let i1 = self.trampolines.push(*signature);
let i2 = self.trampoline_defs.push(trampoline);
Expand Down
54 changes: 53 additions & 1 deletion crates/environ/src/component/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ pub enum Trampoline {
ThreadYield {
/// The specific component instance which is calling the intrinsic.
instance: RuntimeComponentInstanceIndex,
/// If `true`, indicates the caller instance maybe receive notification
/// If `true`, indicates the caller instance may receive notification
/// of task cancellation.
cancellable: bool,
},
Expand Down Expand Up @@ -1123,6 +1123,52 @@ pub enum Trampoline {
/// Which slot to update.
slot: u32,
},

/// Intrinsic used to implement the `thread.index` component model builtin.
ThreadIndex,

/// Intrinsic used to implement the `thread.new_indirect` component model builtin.
ThreadNewIndirect {
/// The specific component instance which is calling the intrinsic.
instance: RuntimeComponentInstanceIndex,
/// The type index for the start function of the thread.
start_func_ty_idx: ComponentTypeIndex,
/// The index of the table that stores the start function.
start_func_table_idx: RuntimeTableIndex,
},

/// Intrinsic used to implement the `thread.switch-to` component model builtin.
ThreadSwitchTo {
/// The specific component instance which is calling the intrinsic.
instance: RuntimeComponentInstanceIndex,
/// If `true`, indicates the caller instance may receive notification
/// of task cancellation.
cancellable: bool,
},

/// Intrinsic used to implement the `thread.suspend` component model builtin.
ThreadSuspend {
/// The specific component instance which is calling the intrinsic.
instance: RuntimeComponentInstanceIndex,
/// If `true`, indicates the caller instance may receive notification
/// of task cancellation.
cancellable: bool,
},

/// Intrinsic used to implement the `thread.resume-later` component model builtin.
ThreadResumeLater {
/// The specific component instance which is calling the intrinsic.
instance: RuntimeComponentInstanceIndex,
},

/// Intrinsic used to implement the `thread.yield-to` component model builtin.
ThreadYieldTo {
/// The specific component instance which is calling the intrinsic.
instance: RuntimeComponentInstanceIndex,
/// If `true`, indicates the caller instance may receive notification
/// of task cancellation.
cancellable: bool,
},
}

impl Trampoline {
Expand Down Expand Up @@ -1188,6 +1234,12 @@ impl Trampoline {
ErrorContextTransfer => format!("error-context-transfer"),
ContextGet { .. } => format!("context-get"),
ContextSet { .. } => format!("context-set"),
ThreadIndex => format!("thread-index"),
ThreadNewIndirect { .. } => format!("thread-new-indirect"),
ThreadSwitchTo { .. } => format!("thread-switch-to"),
ThreadSuspend { .. } => format!("thread-suspend"),
ThreadResumeLater { .. } => format!("thread-resume-later"),
ThreadYieldTo { .. } => format!("thread-yield-to"),
}
}
}
63 changes: 52 additions & 11 deletions crates/environ/src/component/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,29 @@ enum LocalInitializer<'data> {
func: ModuleInternedTypeIndex,
i: u32,
},
ThreadIndex {
func: ModuleInternedTypeIndex,
},
ThreadNewIndirect {
func: ModuleInternedTypeIndex,
start_func_ty: ComponentTypeIndex,
start_func_table_index: TableIndex,
},
ThreadSwitchTo {
func: ModuleInternedTypeIndex,
cancellable: bool,
},
ThreadSuspend {
func: ModuleInternedTypeIndex,
cancellable: bool,
},
ThreadResumeLater {
func: ModuleInternedTypeIndex,
},
ThreadYieldTo {
func: ModuleInternedTypeIndex,
cancellable: bool,
},

// core wasm modules
ModuleStatic(StaticModuleIndex, ComponentCoreModuleTypeId),
Expand Down Expand Up @@ -1121,24 +1144,42 @@ impl<'a, 'data> Translator<'a, 'data> {
core_func_index += 1;
LocalInitializer::ContextSet { i, func }
}

wasmparser::CanonicalFunction::ThreadIndex => {
bail!("unimplemented `thread.index`");
let func = self.core_func_signature(core_func_index)?;
core_func_index += 1;
LocalInitializer::ThreadIndex { func }
}
wasmparser::CanonicalFunction::ThreadNewIndirect { .. } => {
bail!("unimplemented `thread.new-indirect`");
wasmparser::CanonicalFunction::ThreadNewIndirect {
func_ty_index,
table_index,
} => {
let func = self.core_func_signature(core_func_index)?;
core_func_index += 1;
LocalInitializer::ThreadNewIndirect {
func,
start_func_ty: ComponentTypeIndex::from_u32(func_ty_index),
start_func_table_index: TableIndex::from_u32(table_index),
}
}
wasmparser::CanonicalFunction::ThreadSwitchTo { .. } => {
bail!("unimplemented `thread.switch-to`");
wasmparser::CanonicalFunction::ThreadSwitchTo { cancellable } => {
let func = self.core_func_signature(core_func_index)?;
core_func_index += 1;
LocalInitializer::ThreadSwitchTo { func, cancellable }
}
wasmparser::CanonicalFunction::ThreadSuspend { .. } => {
bail!("unimplemented `thread.suspend`");
wasmparser::CanonicalFunction::ThreadSuspend { cancellable } => {
let func = self.core_func_signature(core_func_index)?;
core_func_index += 1;
LocalInitializer::ThreadSuspend { func, cancellable }
}
wasmparser::CanonicalFunction::ThreadResumeLater => {
bail!("unimplemented `thread.resume-later`");
let func = self.core_func_signature(core_func_index)?;
core_func_index += 1;
LocalInitializer::ThreadResumeLater { func }
}
wasmparser::CanonicalFunction::ThreadYieldTo { .. } => {
bail!("unimplemented `thread.yield-to`");
wasmparser::CanonicalFunction::ThreadYieldTo { cancellable } => {
let func = self.core_func_signature(core_func_index)?;
core_func_index += 1;
LocalInitializer::ThreadYieldTo { func, cancellable }
}
};
self.result.initializers.push(init);
Expand Down
Loading