Skip to main content

TrapEncodingBuilder

Struct TrapEncodingBuilder 

Source
pub struct TrapEncodingBuilder { /* private fields */ }
Expand description

A helper structure to build the custom-encoded section of a wasmtime compilation image which encodes trap information.

This structure is incrementally fed the results of compiling individual functions and handles all the encoding internally, allowing usage of lookup_trap_code with the resulting section.

§Section format

The section encodes a sequence of (text_offset, trap_code) entries, sorted by text_offset, where text_offset is the location of a trapping instruction relative to the start of the text section and trap_code is the byte encoding of its CompiledTrap. This format is optimized to enable cheap (O(log n)) lookup given an offset to find a trap code while also being relatively compact as this is included in all modules by default. To satisfy this the section is encoded as two major pieces: an index and a sequence of blocks.

The index is used to perform a binary search given a particular text_offset to find a particular block. The index stores text offsets as well as byte offsets in the “block bodies” section. Once a block is found each block contains up to TRAP_BLOCK_SIZE entries encoded next to each other. Blocks take up a variable width of bytes to encode. More information on decoding each block is below, but the general layout of the section looks like:

┌───────────────────────────────────┐
│ entry_count: u32                  │
│ block_count: u32                  │
├───────────────────────────────────┤
│ block index                       │
│ ┌───────────────────────────────┐ │
│ │ first_offset: u32             │ │  one pair per block, sorted by
│ │ data_pos: u32                 │ │  `first_offset`; `data_pos` is
│ ├───────────────────────────────┤ │  relative to the start of the
│ │ ...                           │ │  block bodies area below
│ └───────────────────────────────┘ │
├───────────────────────────────────┤
│ block bodies                      │
│ ┌───────────────────────────────┐ │
│ │ default_code: u8              │ │
│ ├───────────────────────────────┤ │
│ │ entry: uleb token             │ │  one entry per trap in the
│ │ [trap_code: u8]               │ │  block, `TRAP_BLOCK_SIZE` max
│ ├───────────────────────────────┤ │
│ │ ...                           │ │
│ └───────────────────────────────┘ │
│ ┌───────────────────────────────┐ │
│ │ ...                           │ │
│ └───────────────────────────────┘ │
└───────────────────────────────────┘
  • entry_count is the total number of entries (pc/trap combos) in the section and block_count is the number of blocks, ceil(entry_count / TRAP_BLOCK_SIZE).
  • In the block index, first_offset is the text_offset of the block’s first entry and data_pos is the position of the block’s body, relative to the start of the bodies area (i.e. the end of the index).
  • Each block body starts with default_code, the block’s “default” trap code, chosen as the most common code among the block’s entries.
  • Each entry is a uleb-encoded token (pc_delta << 1) | code_differs. Here pc_delta is this entry’s text_offset minus the previous entry’s (the first entry’s delta is relative to the block’s first_offset and is therefore 0). If code_differs is set the token is followed by one byte holding this entry’s trap code, otherwise the entry has the block’s default code.

Lookup (lookup_trap_code) binary searches the fixed-width block index for the last block whose first_offset is <= the pc in question, then linearly decodes at most TRAP_BLOCK_SIZE entries of that block’s body looking for an exact match.

This encoding leans on two properties of trap metadata: consecutive trap sites are generally close together (pc deltas almost always fit in a single-byte leb) and most entries share one trap code (typically MemoryOutOfBounds for gc-less wasm), making explicit code bytes rare. This is all in service of shrinking the minimum 5 bytes per entry (u32 offset, u8 code), to a bit more than one byte per entry in practice.

Note that at this time this section has an alignment of 1. Additionally due to the 32-bit offsets in the block index this doesn’t support images

= 4GB.

Implementations§

Source§

impl TrapEncodingBuilder

Source

pub fn push(&mut self, func: Range<u64>, traps: &[TrapInformation])

Appends trap information about a function into this section.

This function is called to describe traps for the func range specified. The func offsets are specified relative to the text section itself, and the traps offsets are specified relative to the start of func.

This is required to be called in-order for increasing ranges of func to ensure the final array is properly sorted. Additionally traps must be sorted.

Source

pub fn append_to(self, obj: &mut Object<'_>)

Encodes this section into the object provided.

Trait Implementations§

Source§

impl Default for TrapEncodingBuilder

Source§

fn default() -> TrapEncodingBuilder

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.