Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
0715390
[pr1] base
frank-emrich Mar 12, 2025
175d189
prtest:full
frank-emrich Mar 12, 2025
476ba8a
Merge remote-tracking branch 'upstream/main'
frank-emrich Apr 20, 2025
f8162ae
make sure to use ControlFlow result in trace_suspended_continuation
frank-emrich Apr 21, 2025
d03246b
Merge remote-tracking branch 'upstream/main'
frank-emrich Apr 22, 2025
47da5a4
stack-switching: cleanup: remove stray c-api changes
posborne May 20, 2025
0c6c58a
stack-switching: reuse async_stack_size
posborne May 20, 2025
cb0df54
stack-switching: delete delete_me debugging
posborne May 20, 2025
8f0ba05
stack-switching: address feedback in environ::types
posborne May 20, 2025
f93903a
stack-switching: remove unused code from vmoffsets
posborne May 20, 2025
4237cdc
stack-switching: drop dependency on std
posborne May 20, 2025
85f593f
stack-switching: add compilation checks to ci matrix
posborne May 20, 2025
f3a1cab
stack-switching: remove debug_println cruft
posborne May 20, 2025
257f958
stack-switching: export environ consts consistently
posborne May 20, 2025
ba91bd0
stack-switching: export vm pub items consistently
posborne May 20, 2025
7fbb3fa
table_pool: reduced capacity for large elements
posborne May 22, 2025
27fb201
Merge remote-tracking branch 'upstream/main' into stack-switching-infra
posborne May 23, 2025
ffd8a1d
Merge remote-tracking branch 'upstream/main' into stack-switching-infra
posborne May 27, 2025
e823b74
stack-switching: extend conditional compilation
posborne May 27, 2025
b63e072
stack-switching: formatting fixes
posborne May 27, 2025
f69a569
stack-switching: address new clippy checks
posborne May 27, 2025
e3e8d6a
stack-switching: more conditional compilation fixes
posborne May 27, 2025
12b2d3f
stack-switching: additional conditional compile on table builtins for…
posborne May 27, 2025
fc60266
stack-switching: additional conditional compile fixes
posborne May 28, 2025
7e77662
stack-switching: additional conditional compile in store
posborne May 28, 2025
17645fa
stack-switching: remove overly strict assertion
posborne May 28, 2025
da37984
stack-switching: remove errantly dropped no_mangle in config c-api
posborne May 28, 2025
5db7836
stack-switching: VMContObj::from_raw_parts
posborne May 30, 2025
7b72aa3
stack-switching: remove duplicate async_stack_size feature check
posborne May 30, 2025
22bf039
stack-switching: VMArray -> VMHostArray
posborne May 30, 2025
2f994c3
stack-switching: remove unnecessary clippy exception
posborne May 30, 2025
6a60fe6
stack-switching: fix docs referenced VMRuntimeLimits
posborne May 30, 2025
4ebb04b
stack-switching: fix doc typo
posborne May 30, 2025
1daeb0f
stack-switching: follow recommendations for type casts
posborne May 30, 2025
e3a3d4c
stack-switching: use usize::next_multiple_of
posborne May 30, 2025
9bab3fd
stack-switching: update outdated comment
posborne Jun 3, 2025
3f3e366
stack-switching: use feature gate instead of allow(dead_code)
posborne Jun 3, 2025
f6dd45f
stack-switching: rework backtrace using chunks/zip
posborne Jun 3, 2025
3957e50
Merge remote-tracking branch 'upstream/main' into stack-switching-infra
posborne Jun 3, 2025
d93132e
stack-switching: move tests to footer module
posborne Jun 4, 2025
ce4e088
stack-swictchding: verify stack_chain offsets at runtime
posborne Jun 4, 2025
d6a3ae3
fixup! stack-switching: use feature gate instead of allow(dead_code)
posborne Jun 4, 2025
ca5bcb6
Merge remote-tracking branch 'upstream/main' into stack-switching-infra
posborne Jun 4, 2025
60c9cdb
stack-switching: document continuation roots tracing using match arms
posborne Jun 4, 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
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ default = [
"gc",
"gc-drc",
"gc-null",
"stack-switching",
"winch",
"pulley",

Expand Down Expand Up @@ -489,6 +490,7 @@ gc = ["wasmtime-cli-flags/gc", "wasmtime/gc"]
gc-drc = ["gc", "wasmtime/gc-drc", "wasmtime-cli-flags/gc-drc"]
gc-null = ["gc", "wasmtime/gc-null", "wasmtime-cli-flags/gc-null"]
pulley = ["wasmtime-cli-flags/pulley"]
stack-switching = ["wasmtime/stack-switching", "wasmtime-cli-flags/stack-switching"]

# CLI subcommands for the `wasmtime` executable. See `wasmtime $cmd --help`
# for more information on each subcommand.
Expand Down
16 changes: 16 additions & 0 deletions crates/c-api/include/wasmtime/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,22 @@ WASMTIME_CONFIG_PROP(void, wasm_wide_arithmetic, bool)

#ifdef WASMTIME_FEATURE_COMPILER

/**
* \brief Configures whether the WebAssembly function references
* proposal is enabled.
*
* This setting is `false` by default.
*/
WASMTIME_CONFIG_PROP(void, wasm_function_references, bool)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, I don't see a function definition for this one either.

Copy link
Contributor

@dhil dhil Mar 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reason as above. Should just be deleted for now, I think.


/**
* \brief Configures whether the WebAssembly stack switching
* proposal is enabled.
*
* This setting is `false` by default.
*/
WASMTIME_CONFIG_PROP(void, wasm_stack_switching, bool)

/**
* \brief Configures how JIT code will be compiled.
*
Expand Down
10 changes: 10 additions & 0 deletions crates/c-api/include/wasmtime/linker.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ WASM_API_EXTERN void wasmtime_linker_delete(wasmtime_linker_t *linker);
WASM_API_EXTERN void wasmtime_linker_allow_shadowing(wasmtime_linker_t *linker,
bool allow_shadowing);

/**
* \brief Configures whether the given Linker will allow unknown exports from
* command modules.
*
* By default this setting is `false`.
*/
WASM_API_EXTERN void
wasmtime_linker_allow_unknown_exports(wasmtime_linker_t *linker,
bool allow_unknown_exports);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a corresponding function definition in crates/c-api, I think it is missing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a stray declaration from some of our downstream experiments. It has been needed to capture the C shadow stack pointer, that clang generates. It must be kept in sync with the stack switching done by the engine. To be clear, this is just due to the fact that clang doesn't know about stack switching.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, exposing these things the C API would be good in general, so if you want to do it here or in a new PR, you're more than welcome to!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes sure! I am leaning towards adding this in a follow-up PR focused on the C API. What do you think @frank-emrich ?


/**
* \brief Defines a new item in this linker.
*
Expand Down
4 changes: 4 additions & 0 deletions crates/c-api/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ pub extern "C" fn wasmtime_config_wasm_memory64_set(c: &mut wasm_config_t, enabl
}

#[unsafe(no_mangle)]
pub extern "C" fn wasmtime_config_wasm_stack_switching_set(c: &mut wasm_config_t, enable: bool) {
c.config.wasm_stack_switching(enable);
}

#[cfg(any(feature = "cranelift", feature = "winch"))]
pub extern "C" fn wasmtime_config_strategy_set(
c: &mut wasm_config_t,
Expand Down
1 change: 1 addition & 0 deletions crates/cli-flags/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ gc-null = ["gc", "wasmtime/gc-null"]
threads = ["wasmtime/threads"]
memory-protection-keys = ["wasmtime/memory-protection-keys"]
pulley = ["wasmtime/pulley"]
stack-switching = ["wasmtime/stack-switching"]
14 changes: 14 additions & 0 deletions crates/cli-flags/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,8 @@ wasmtime_option_group! {
pub trap_on_grow_failure: Option<bool>,
/// Maximum execution time of wasm code before timing out (1, 2s, 100ms, etc)
pub timeout: Option<Duration>,
/// Size of stacks created with cont.new instructions
pub stack_switching_stack_size: Option<usize>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least for now, I'm not sure it is worth having separate config knobs for stacks created via cont.new versus API-level fibers. This effectively creates two different kinds of stacks in the system, and I'd prefer to try and keep things simple for as long as we can by having a single kind of stack that we config and allocate and handle in the system.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting question, which Frank and I have discussed in the past. If my memory serves me right, then our layout is slightly different. However perhaps we can unify the layouts (or we can perhaps simply adopt the fibers' layout). I am not too sure about the implications, I think @frank-emrich has the key knowledge to best answer this question.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The automatic pooling allocator integration would also get you fast allocation of new stacks from a pool, which would look nice on your benchmarks and what have you ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, agreed! I totally see the appeal!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a technical perspective, there is no need for us to have our own config setting for the stack size.
I guess the reason we didn't just re-use the existing stack_size option is that the latter always felt like a soft limit to me: AFAIK you can still occupy stack space beyond that limit, for example with host functions.
But I have no strong feelings about re-using the existing stack_size config option, or merging our stack_switching_stack_size with async_stack_size.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK you can still occupy stack space beyond that limit, for example with host functions.

We are generally a little loosey-goosey with our nomenclature here, but to make things precise for a moment:

  • "Host functions" = functions defined in native code by the Wasmtime embedder (e.g. via wasmtime::Func::new) and imported by Wasm
  • "libcalls" = various bits of Wasm functionality (e.g. memory.grow) that are not implemented inline in JIT code, but instead in native functions inside of Wasmtime's runtime.

libcalls are part of Wasmtime's trusted compute base, host functions are not (modulo some hand waving around their usage of unsafe).

Given all that: we will execute libcalls on async fibers, but will never execute host functions on async fibers. When Wasm calls an imported host function, we first switch from the async fiber to the native stack, then run the host function, and finally switch back to the Wasm's async fiber stack to pass the function results back to Wasm JIT code.

A libcall should never access stack memory beyond the async_stack_size limit (and we rely on guard pages to help enforce this). The Wasm JIT code is given max_wasm_stack bytes for its own use, it must always be true that async_stack_size > max_wasm_stack, and therefore that leaves async_stack_size - max_wasm_stack bytes of stack space for libcalls in the worst case.

This is all a little bit of an aside and I'm mostly just explaining all this to make sure we are on the same page here. I don't think any of this needs to change for stack-switching, and I would also expect that we would call libcalls, but never host functions, on stack-switching stacks, same way we do things on our async fibers.

/// Configures support for all WebAssembly proposals implemented.
pub all_proposals: Option<bool>,
/// Configure support for the bulk memory proposal.
Expand Down Expand Up @@ -366,6 +368,8 @@ wasmtime_option_group! {
pub component_model_async: Option<bool>,
/// Configure support for the function-references proposal.
pub function_references: Option<bool>,
/// Configure support for the stack-switching proposal.
pub stack_switching: Option<bool>,
/// Configure support for the GC proposal.
pub gc: Option<bool>,
/// Configure support for the custom-page-sizes proposal.
Expand Down Expand Up @@ -803,6 +807,12 @@ impl CommonOptions {
config.native_unwind_info(enable);
}

match_feature! {
["stack-switching" : self.wasm.stack_switching_stack_size]
size => config.stack_switching_stack_size(size),
_ => err,
}

match_feature! {
["pooling-allocator" : self.opts.pooling_allocator.or(pooling_allocator_default)]
enable => {
Expand Down Expand Up @@ -964,6 +974,9 @@ impl CommonOptions {
if let Some(enable) = self.wasm.memory64.or(all) {
config.wasm_memory64(enable);
}
if let Some(enable) = self.wasm.stack_switching {
config.wasm_stack_switching(enable);
}
if let Some(enable) = self.wasm.custom_page_sizes.or(all) {
config.wasm_custom_page_sizes(enable);
}
Expand Down Expand Up @@ -994,6 +1007,7 @@ impl CommonOptions {
("gc", gc, wasm_gc)
("gc", reference_types, wasm_reference_types)
("gc", function_references, wasm_function_references)
("stack-switching", stack_switching, wasm_stack_switching)
}
Ok(())
}
Expand Down
17 changes: 17 additions & 0 deletions crates/cranelift/src/func_environ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3441,3 +3441,20 @@ fn index_type_to_ir_type(index_type: IndexType) -> ir::Type {
IndexType::I64 => I64,
}
}

/// TODO(10248) This is removed in the next stack switching PR. It stops the
/// compiler from complaining about the stack switching libcalls being dead
/// code.
#[allow(
dead_code,
reason = "Dummy function to supress more dead code warnings"
)]
pub fn use_stack_switching_libcalls() {
let _ = BuiltinFunctions::delete_me_print_str;
let _ = BuiltinFunctions::delete_me_print_int;
let _ = BuiltinFunctions::delete_me_print_pointer;

let _ = BuiltinFunctions::cont_new;
let _ = BuiltinFunctions::table_grow_cont_obj;
let _ = BuiltinFunctions::table_fill_cont_obj;
}
22 changes: 17 additions & 5 deletions crates/cranelift/src/gc/enabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,12 @@ fn read_field_at_addr(
.call(get_interned_func_ref, &[vmctx, func_ref_id, expected_ty]);
builder.func.dfg.first_result(call_inst)
}
WasmHeapTopType::Cont => todo!(), // FIXME: #10248 stack switching support.
WasmHeapTopType::Cont => {
// TODO(#10248) GC integration for stack switching
return Err(wasmtime_environ::WasmError::Unsupported(
"Stack switching feature not compatbile with GC, yet".to_string(),
));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not something that needs to be handled in this PR, but there is no reason we can't enable GC and also maintain the existing memory management for continuations, where they have the same lifetime as the Store. We don't have to implement full GC of continuations before we allow enabling both GC and stack switching at the same time.

}
},
},
};
Expand Down Expand Up @@ -1011,6 +1016,8 @@ pub fn translate_ref_test(
| WasmHeapType::NoExtern
| WasmHeapType::Func
| WasmHeapType::NoFunc
| WasmHeapType::Cont
| WasmHeapType::NoCont
| WasmHeapType::I31 => unreachable!("handled top, bottom, and i31 types above"),

// For these abstract but non-top and non-bottom types, we check the
Expand Down Expand Up @@ -1063,8 +1070,12 @@ pub fn translate_ref_test(

func_env.is_subtype(builder, actual_shared_ty, expected_shared_ty)
}

WasmHeapType::Cont | WasmHeapType::ConcreteCont(_) | WasmHeapType::NoCont => todo!(), // FIXME: #10248 stack switching support.
WasmHeapType::ConcreteCont(_) => {
// TODO(#10248) GC integration for stack switching
return Err(wasmtime_environ::WasmError::Unsupported(
"Stack switching feature not compatbile with GC, yet".to_string(),
));
}
};
builder.ins().jump(continue_block, &[result]);

Expand Down Expand Up @@ -1403,8 +1414,9 @@ impl FuncEnvironment<'_> {
WasmHeapType::Func | WasmHeapType::ConcreteFunc(_) | WasmHeapType::NoFunc => {
unreachable!()
}

WasmHeapType::Cont | WasmHeapType::ConcreteCont(_) | WasmHeapType::NoCont => todo!(), // FIXME: #10248 stack switching support.
WasmHeapType::Cont | WasmHeapType::ConcreteCont(_) | WasmHeapType::NoCont => {
unreachable!()
}
};

match (ty.nullable, might_be_i31) {
Expand Down
12 changes: 11 additions & 1 deletion crates/cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ pub const TRAP_HEAP_MISALIGNED: TrapCode =
TrapCode::unwrap_user(Trap::HeapMisaligned as u8 + TRAP_OFFSET);
pub const TRAP_TABLE_OUT_OF_BOUNDS: TrapCode =
TrapCode::unwrap_user(Trap::TableOutOfBounds as u8 + TRAP_OFFSET);
pub const TRAP_UNHANDLED_TAG: TrapCode =
TrapCode::unwrap_user(Trap::UnhandledTag as u8 + TRAP_OFFSET);
pub const TRAP_CONTINUATION_ALREADY_CONSUMED: TrapCode =
TrapCode::unwrap_user(Trap::ContinuationAlreadyConsumed as u8 + TRAP_OFFSET);
pub const TRAP_DELETE_ME_DEBUG_ASSERTION: TrapCode =
TrapCode::unwrap_user(Trap::DeleteMeDebugAssertion as u8 + TRAP_OFFSET);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, we already have TRAP_INTERNAL_ASSERT that we use for debug-only assertions inside JIT code.

pub const TRAP_CAST_FAILURE: TrapCode =
TrapCode::unwrap_user(Trap::CastFailure as u8 + TRAP_OFFSET);

Expand Down Expand Up @@ -202,7 +208,11 @@ fn reference_type(wasm_ht: WasmHeapType, pointer_type: ir::Type) -> ir::Type {
match wasm_ht.top() {
WasmHeapTopType::Func => pointer_type,
WasmHeapTopType::Any | WasmHeapTopType::Extern => ir::types::I32,
WasmHeapTopType::Cont => todo!(), // FIXME: #10248 stack switching support.
WasmHeapTopType::Cont =>
// TODO(10248) This is added in a follow-up PR
{
unimplemented!("codegen for stack switching types not implemented, yet")
}
}
}

Expand Down
61 changes: 50 additions & 11 deletions crates/cranelift/src/translate/code_translator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2876,6 +2876,56 @@ pub fn translate_operator(
// representation, so we don't actually need to do anything.
}

Operator::ContNew { cont_type_index: _ } => {
// TODO(10248) This is added in a follow-up PR
return Err(wasmtime_environ::WasmError::Unsupported(
"codegen for stack switching instructions not implemented, yet".to_string(),
));
}
Operator::ContBind {
argument_index: _,
result_index: _,
} => {
// TODO(10248) This is added in a follow-up PR
return Err(wasmtime_environ::WasmError::Unsupported(
"codegen for stack switching instructions not implemented, yet".to_string(),
));
}
Operator::Suspend { tag_index: _ } => {
// TODO(10248) This is added in a follow-up PR
return Err(wasmtime_environ::WasmError::Unsupported(
"codegen for stack switching instructions not implemented, yet".to_string(),
));
}
Operator::Resume {
cont_type_index: _,
resume_table: _,
} => {
// TODO(10248) This is added in a follow-up PR
return Err(wasmtime_environ::WasmError::Unsupported(
"codegen for stack switching instructions not implemented, yet".to_string(),
));
}
Operator::ResumeThrow {
cont_type_index: _,
tag_index: _,
resume_table: _,
} => {
// TODO(10248) This depends on exception handling
return Err(wasmtime_environ::WasmError::Unsupported(
"resume.throw instructions not supported, yet".to_string(),
));
}
Operator::Switch {
cont_type_index: _,
tag_index: _,
} => {
// TODO(10248) This is added in a follow-up PR
return Err(wasmtime_environ::WasmError::Unsupported(
"codegen for stack switching instructions not implemented, yet".to_string(),
));
}

Operator::GlobalAtomicGet { .. }
| Operator::GlobalAtomicSet { .. }
| Operator::GlobalAtomicRmwAdd { .. }
Expand Down Expand Up @@ -2917,17 +2967,6 @@ pub fn translate_operator(
));
}

Operator::ContNew { .. }
| Operator::ContBind { .. }
| Operator::Suspend { .. }
| Operator::Resume { .. }
| Operator::ResumeThrow { .. }
| Operator::Switch { .. } => {
return Err(wasm_unsupported!(
"stack-switching operators are not yet implemented"
));
}

Operator::I64MulWideS => {
let (arg1, arg2) = state.pop2();
let arg1 = builder.ins().sextend(I128, arg1);
Expand Down
29 changes: 29 additions & 0 deletions crates/environ/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,32 @@ macro_rules! foreach_builtin_function {
// Raises an unconditional trap where the trap information must have
// been previously filled in.
raise(vmctx: vmctx);

// Creates a new continuation from a funcref.
cont_new(vmctx: vmctx, r: pointer, param_count: u32, result_count: u32) -> pointer;

// FIXME(frank-emrich) The next three builtins are used by the debug printing mechanism.
// They are not supposed to be part of the final upstreamed code.
//
// Prints a 'static str, represented as a
// pointer and a length.
delete_me_print_str(vmctx: vmctx, s: pointer, len : u64);
// Prints integer
delete_me_print_int(vmctx: vmctx, arg : u64);
// Prints pointer, formatted as hex.
delete_me_print_pointer(vmctx: vmctx, arg : pointer);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were these going to be removed in the next PR, or should they be removed now? Maybe throw an item into the meta task list if not now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My take is that they shouldn't make it into the main branch -- probably a stray include?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question! These only exist for some hacky debug printing code that should not end up in main. Initially, when we thought that there would only be a single, big PR, the plan was to keep them during reviewing, and then remove them at the last moment before merging. Now that we will land this in smaller pieces, we could either remove them now, or once all PRs from the series have landed.

The reason why we don't want to land this is explained here: On the codegen side, we just emit the addresses of Rust string literals as literals into generated code, with no relocation information. So this crashes and burns if you ever try to re-use the same generated code from a different invocation of wamtime.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why we don't want to land this is explained here: On the codegen side, we just emit the addresses of Rust string literals as literals into generated code, with no relocation information. So this crashes and burns if you ever try to re-use the same generated code from a different invocation of wamtime.

Ah okay! Yes, definitely should not land these bits in that case.


// Returns an index for Wasm's `table.grow` instruction
// for `contobj`s. Note that the initial
// Option<VMContObj> (i.e., the value to fill the new
// slots with) is split into two arguments: The underlying
// continuation reference and the revision count. To
// denote the continuation being `None`, `init_contref`
// may be 0.
table_grow_cont_obj(vmctx: vmctx, table: u32, delta: u64, init_contref: pointer, init_revision: u64) -> pointer;
// `value_contref` and `value_revision` together encode
// the Option<VMContObj>, as in previous libcall.
table_fill_cont_obj(vmctx: vmctx, table: u32, dst: u64, value_contref: pointer, value_revision: u64, len: u64) -> bool;
}
};
}
Expand Down Expand Up @@ -347,6 +373,7 @@ impl BuiltinFunctionIndex {
(@get memory32_grow pointer) => (TrapSentinel::NegativeTwo);
(@get table_grow_func_ref pointer) => (TrapSentinel::NegativeTwo);
(@get table_grow_gc_ref pointer) => (TrapSentinel::NegativeTwo);
(@get table_grow_cont_obj pointer) => (TrapSentinel::NegativeTwo);

// Atomics-related functions return a negative value indicating trap
// indicate a trap.
Expand All @@ -371,6 +398,8 @@ impl BuiltinFunctionIndex {
(@get intern_func_ref_for_gc_heap u64) => (return None);
(@get is_subtype u32) => (return None);

(@get cont_new pointer) => (TrapSentinel::Negative);

// Bool-returning functions use `false` as an indicator of a trap.
(@get $name:ident bool) => (TrapSentinel::Falsy);

Expand Down
9 changes: 8 additions & 1 deletion crates/environ/src/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,15 @@ pub const VM_GC_HEADER_TYPE_INDEX_OFFSET: u32 = 4;
/// Get the byte size of the given Wasm type when it is stored inside the GC
/// heap.
pub fn byte_size_of_wasm_ty_in_gc_heap(ty: &WasmStorageType) -> u32 {
use crate::{WasmHeapType::*, WasmRefType};
match ty {
WasmStorageType::I8 => 1,
WasmStorageType::I16 => 2,
WasmStorageType::Val(ty) => match ty {
WasmValType::Ref(WasmRefType {
nullable: _,
heap_type: ConcreteCont(_) | Cont,
}) => unimplemented!("Stack switching feature not compatbile with GC, yet"),
WasmValType::I32 | WasmValType::F32 | WasmValType::Ref(_) => 4,
WasmValType::I64 | WasmValType::F64 => 8,
WasmValType::V128 => 16,
Expand Down Expand Up @@ -162,7 +167,9 @@ pub trait GcTypeLayouts {
WasmCompositeInnerType::Array(ty) => Some(self.array_layout(ty).into()),
WasmCompositeInnerType::Struct(ty) => Some(self.struct_layout(ty).into()),
WasmCompositeInnerType::Func(_) => None,
WasmCompositeInnerType::Cont(_) => None,
WasmCompositeInnerType::Cont(_) => {
unimplemented!("Stack switching feature not compatbile with GC, yet")
}
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/environ/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub mod obj;
mod ref_bits;
mod scopevec;
mod stack_map;
pub mod stack_switching;
mod trap_encoding;
mod tunables;
mod types;
Expand Down
Loading
Loading