Skip to content

Commit

Permalink
Merge wasmtime-fibre crate into runtime crate (bytecodealliance#127)
Browse files Browse the repository at this point in the history
This turns the `wasmtime_fibre` into a module called `fibre` in the
`runtime` crate. As a result, the `wasmtime_fibre` crate is removed from
the workspace. This is helpful for specializing the fibre implementation
further for our purposes in the future.

Arguably, we could actually make `fibre` a submodule of the existing
`continuation` module in `runtime` (i.e., instead of putting it at
`wasmtime_runtime::fibre`, put it at
`wasmtime_runtime::continuation::fibre`), but I decided against changing
the directory structure further for now.

The only noteworthy changes outside of moving the files are:
1. The types `SwitchDirection` and `SwitchDirectionEnum`, previously in
the `wasmtime_fibre` crate, are now in the `continuations` crate. We
need access to these in cranelift.
2. Instead of adding a lot of /// TODO comments I bailed out of
mandatory doc comments (as imposed by the `runtime` crate) on pub
definitions in the new `fibre` module.
  • Loading branch information
frank-emrich authored Mar 12, 2024
1 parent 395d2c4 commit 6434027
Show file tree
Hide file tree
Showing 16 changed files with 123 additions and 387 deletions.
14 changes: 0 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ wasmtime-winch = { path = "crates/winch", version = "=20.0.0" }
wasmtime-environ = { path = "crates/environ", version = "=20.0.0" }
wasmtime-explorer = { path = "crates/explorer", version = "=20.0.0" }
wasmtime-fiber = { path = "crates/fiber", version = "=20.0.0" }
wasmtime-fibre = { path = "crates/fibre", version = "=20.0.0" }
wasmtime-types = { path = "crates/types", version = "20.0.0" }
wasmtime-jit-debug = { path = "crates/jit-debug", version = "=20.0.0" }
wasmtime-runtime = { path = "crates/runtime", version = "=20.0.0" }
Expand Down
1 change: 0 additions & 1 deletion crates/continuations/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@ repository = "https://github.com/wasmfx/wasmtime"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
wasmtime-fibre = { workspace = true }
memoffset = "0.9.0"
111 changes: 106 additions & 5 deletions crates/continuations/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use std::ptr;
use wasmtime_fibre::Fiber;

pub use wasmtime_fibre::{SwitchDirection, SwitchDirectionEnum, TagId};

/// Default size for continuation stacks
pub const DEFAULT_FIBER_SIZE: usize = 2097152; // 2MB = 512 pages of 4k
Expand Down Expand Up @@ -51,8 +48,6 @@ pub struct WasmFXConfig {
pub stack_size: usize,
}

pub type ContinuationFiber = Fiber;

/// This type is used to save (and subsequently restore) a subset of the data in
/// `VMRuntimeLimits`. See documentation of `StackChain` for the exact uses.
#[repr(C)]
Expand Down Expand Up @@ -150,6 +145,112 @@ impl From<State> for i32 {
}
}

// Runtime representation of tags
pub type TagId = u32;

/// See SwitchDirection below for overall use of this type.
#[repr(u32)]
pub enum SwitchDirectionEnum {
// Used to indicate that the contination has returned normally.
Return = 0,

// Indicates that we are suspendinga continuation due to invoking suspend.
// The payload is the tag to suspend with
Suspend = 1,

// Indicates that we are resuming a continuation via resume.
Resume = 2,
}

impl SwitchDirectionEnum {
pub fn discriminant_val(&self) -> u32 {
// This is well-defined for an enum with repr(u32).
unsafe { *(self as *const SwitchDirectionEnum as *const u32) }
}
}

/// Values of this type are passed to `wasmtime_fibre_switch` to indicate why we
/// are switching. A nicer way of representing this type would be the following
/// enum:
///
///```
/// #[repr(C, u32)]
/// pub enum SwitchDirection {
/// // Used to indicate that the contination has returned normally.
/// Return = 0,
///
/// // Indicates that we are suspendinga continuation due to invoking suspend.
/// // The payload is the tag to suspend with
/// Suspend(u32) = 1,
///
/// // Indicates that we are resuming a continuation via resume.
/// Resume = 2,
/// }
///```
///
/// However, we want to convert values of type `SwitchDirection` to and from u64
/// easily, which is why we need to ensure that it contains no uninitialised
/// memory, to avoid undefined behavior.
///
/// We allow converting values of this type to and from u64.
/// In that representation, bits 0 to 31 (where 0 is the LSB) contain the
/// discriminant (as u32), while bits 32 to 63 contain the `data`.
#[repr(C)]
pub struct SwitchDirection {
pub discriminant: SwitchDirectionEnum,

// Stores tag value if `discriminant` is `suspend`, 0 otherwise.
pub data: u32,
}

impl SwitchDirection {
pub fn return_() -> SwitchDirection {
SwitchDirection {
discriminant: SwitchDirectionEnum::Return,
data: 0,
}
}

pub fn resume() -> SwitchDirection {
SwitchDirection {
discriminant: SwitchDirectionEnum::Resume,
data: 0,
}
}

pub fn suspend(tag: u32) -> SwitchDirection {
SwitchDirection {
discriminant: SwitchDirectionEnum::Suspend,
data: tag,
}
}
}

impl From<SwitchDirection> for u64 {
fn from(val: SwitchDirection) -> u64 {
// TODO(frank-emrich) This assumes little endian data layout. Should
// make this more explicit.
unsafe { std::mem::transmute::<SwitchDirection, u64>(val) }
}
}

impl From<u64> for SwitchDirection {
fn from(val: u64) -> SwitchDirection {
#[cfg(debug_assertions)]
{
let discriminant = val as u32;
debug_assert!(discriminant <= 2);
if discriminant != SwitchDirectionEnum::Suspend.discriminant_val() {
let data = val >> 32;
debug_assert_eq!(data, 0);
}
}
// TODO(frank-emrich) This assumes little endian data layout. Should
// make this more explicit.
unsafe { std::mem::transmute::<u64, SwitchDirection>(val) }
}
}

/// Defines offsets of the fields in the continuation-related types
pub mod offsets {
/// Offsets of fields in `Payloads`
Expand Down
2 changes: 1 addition & 1 deletion crates/cranelift/src/wasmfx/optimized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1374,7 +1374,7 @@ pub(crate) fn translate_resume<'a>(
// Now the parent contobj (or main stack) is active again
vmctx.store_stack_chain(env, builder, &parent_stack_chain);

// The `result` is a value of type wasmtime_fibre::SwitchDirection,
// The `result` is a value of type wasmtime_continuations::SwitchDirection,
// using the encoding described at its definition.
// Thus, the first 32 bit encode the discriminant, and the
// subsequent 32 bit encode the tag if suspending, or 0 otherwise.
Expand Down
3 changes: 2 additions & 1 deletion crates/environ/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ macro_rules! foreach_builtin_function {

/// Creates a new continuation from a funcref.
tc_cont_new(vmctx: vmctx, r: pointer, param_count: i64, result_count: i64) -> pointer;
/// Resumes a continuation. The result value is of type wasmtime_fibre::SwitchDirection.
/// Resumes a continuation. The result value is of type
/// wasmtime_continuations::SwitchDirection.
tc_resume(vmctx: vmctx, contobj: pointer, parent_stack_limits: pointer) -> i64;
/// Suspends a continuation.
tc_suspend(vmctx: vmctx, tag: i32);
Expand Down
27 changes: 0 additions & 27 deletions crates/fibre/Cargo.toml

This file was deleted.

Loading

0 comments on commit 6434027

Please sign in to comment.