Skip to content

Commit

Permalink
Refactor and simplify component trampolines
Browse files Browse the repository at this point in the history
In poking at #6696 I felt that the amount of boilerplate for defining
new kinds of trampolines in the component model was getting a bit
excessive. There was already 6 different types and I was adding two more
and I had to touch just a few too many places to get this done. In the
end I decided to refactor how trampolines are handled in the component
model to make it much easier to add new kinds of trampolines.

To that end the type-specific counts/lists/etc are all gone now in favor
of a single concept of a trampoline. This means components now track
trampolines in-bulk rather than individually by type. For example
compiling trampolines is now a loop over "compile this list of
trampolines" where previously it was N loops for the N types of
trampolines. The `Trampoline` definition is where the enum and dispatch
happens where that contains all possible trampolines that a component
could require.

This ended up being a large refactor to the Cranelift component
integration, but there is not intended to be any functional change from
this refactoring. Additionally all trampolines are now removed from the
global initializers list since there's nothing preventing them from
being initialized earlier on during the instantiation process.

Overall this should drastically reduce the number of locations that need
to have trampoline-specific knowledge to translation, the dataflow
graph, and compilation. Nearly everything else can operate over
everything in bulk and forward between these systems.
  • Loading branch information
alexcrichton committed Jul 24, 2023
1 parent 0f9ac11 commit 0df191a
Show file tree
Hide file tree
Showing 14 changed files with 804 additions and 1,874 deletions.
894 changes: 406 additions & 488 deletions crates/cranelift/src/compiler/component.rs

Large diffs are not rendered by default.

89 changes: 9 additions & 80 deletions crates/environ/src/component/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use crate::component::{
Component, ComponentTypes, LowerImport, ResourceDrop, ResourceNew, ResourceRep, Transcoder,
};
use crate::WasmFuncType;
use crate::component::{ComponentTranslation, ComponentTypes, TrampolineIndex};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::any::Any;
Expand Down Expand Up @@ -35,84 +32,16 @@ impl<T> AllCallFunc<T> {

/// Compilation support necessary for components.
pub trait ComponentCompiler: Send + Sync {
/// Creates a trampoline for a `canon.lower`'d host function.
/// Compiles the pieces necessary to create a `VMFuncRef` for the
/// `trampoline` specified.
///
/// This function will create a suitable trampoline which can be called from
/// WebAssembly code and which will then call into host code. The signature
/// of this generated trampoline should have the appropriate wasm ABI for
/// the `lowering.canonical_abi` type signature (e.g. System-V).
///
/// The generated trampoline will interpret its first argument as a
/// `*mut VMComponentContext` and use the `VMComponentOffsets` for
/// `component` to read necessary data (as specified by `lowering.options`)
/// and call the host function pointer. Notably the host function pointer
/// has the signature `VMLoweringCallee` where many of the arguments are
/// loaded from known offsets (for this particular generated trampoline)
/// from the `VMComponentContext`.
///
/// Returns a compiler-specific `Box<dyn Any>` which can be passed later to
/// `emit_obj` to crate an elf object.
fn compile_lowered_trampoline(
&self,
component: &Component,
lowering: &LowerImport,
types: &ComponentTypes,
) -> Result<AllCallFunc<Box<dyn Any + Send>>>;

/// Creates a function which will always trap that has the `ty` specified.
///
/// This will create a small trampoline whose only purpose is to generate a
/// trap at runtime. This is used to implement the degenerate case of a
/// `canon lift`'d function immediately being `canon lower`'d.
fn compile_always_trap(&self, ty: &WasmFuncType) -> Result<AllCallFunc<Box<dyn Any + Send>>>;

/// Compiles a trampoline to implement string transcoding from adapter
/// modules.
///
/// The generated trampoline will invoke the `transcoder.op` libcall with
/// the various memory configuration provided in `transcoder`. This is used
/// to pass raw pointers to host functions to avoid the host having to deal
/// with base pointers, offsets, memory32-vs-64, etc.
///
/// Note that all bounds checks for memories are present in adapters
/// themselves, and the host libcalls simply assume that the pointers are
/// valid.
fn compile_transcoder(
&self,
component: &Component,
transcoder: &Transcoder,
types: &ComponentTypes,
) -> Result<AllCallFunc<Box<dyn Any + Send>>>;

/// Compiles a trampoline to use as the `resource.new` intrinsic in the
/// component model.
///
/// The generated trampoline will invoke a host-defined libcall that will do
/// all the heavy lifting for this intrinsic, so this is primarily bridging
/// ABIs and inserting a `TypeResourceTableIndex` argument so the host
/// has the context about where this is coming from.
fn compile_resource_new(
&self,
component: &Component,
resource: &ResourceNew,
types: &ComponentTypes,
) -> Result<AllCallFunc<Box<dyn Any + Send>>>;

/// Same as `compile_resource_new` except for the `resource.rep` intrinsic.
fn compile_resource_rep(
&self,
component: &Component,
resource: &ResourceRep,
types: &ComponentTypes,
) -> Result<AllCallFunc<Box<dyn Any + Send>>>;

/// Similar to `compile_resource_new` but this additionally handles the
/// return value which may involve executing destructors and checking for
/// reentrance traps.
fn compile_resource_drop(
/// Each trampoline is a member of the `Trampoline` enumeration and has a
/// unique purpose and is translated differently. See the implementation of
/// this trait for Cranelift for more information.
fn compile_trampoline(
&self,
component: &Component,
resource: &ResourceDrop,
component: &ComponentTranslation,
types: &ComponentTypes,
trampoline: TrampolineIndex,
) -> Result<AllCallFunc<Box<dyn Any + Send>>>;
}
Loading

0 comments on commit 0df191a

Please sign in to comment.