Path: blob/main/crates/environ/src/component/vmcomponent_offsets.rs
1692 views
// Currently the `VMComponentContext` allocation by field looks like this:1//2// struct VMComponentContext {3// magic: u32,4// builtins: &'static VMComponentBuiltins,5// limits: *const VMStoreContext,6// flags: [VMGlobalDefinition; component.num_runtime_component_instances],7// trampoline_func_refs: [VMFuncRef; component.num_trampolines],8// lowerings: [VMLowering; component.num_lowerings],9// memories: [*mut VMMemoryDefinition; component.num_runtime_memories],10// tables: [VMTable; component.num_runtime_tables],11// reallocs: [*mut VMFuncRef; component.num_runtime_reallocs],12// post_returns: [*mut VMFuncRef; component.num_runtime_post_returns],13// resource_destructors: [*mut VMFuncRef; component.num_resources],14// }1516use crate::PtrSize;17use crate::component::*;1819/// Equivalent of `VMCONTEXT_MAGIC` except for components.20///21/// This is stored at the start of all `VMComponentContext` structures and22/// double-checked on `VMComponentContext::from_opaque`.23pub const VMCOMPONENT_MAGIC: u32 = u32::from_le_bytes(*b"comp");2425/// Flag for the `VMComponentContext::flags` field which corresponds to the26/// canonical ABI flag `may_leave`27pub const FLAG_MAY_LEAVE: i32 = 1 << 0;2829/// Flag for the `VMComponentContext::flags` field which corresponds to the30/// canonical ABI flag `may_enter`31pub const FLAG_MAY_ENTER: i32 = 1 << 1;3233/// Flag for the `VMComponentContext::flags` field which is set whenever a34/// function is called to indicate that `post_return` must be called next.35pub const FLAG_NEEDS_POST_RETURN: i32 = 1 << 2;3637/// Runtime offsets within a `VMComponentContext` for a specific component.38#[derive(Debug, Clone, Copy)]39pub struct VMComponentOffsets<P> {40/// The host pointer size41pub ptr: P,4243/// The number of lowered functions this component will be creating.44pub num_lowerings: u32,45/// The number of memories which are recorded in this component for options.46pub num_runtime_memories: u32,47/// The number of tables which are recorded in this component for options.48pub num_runtime_tables: u32,49/// The number of reallocs which are recorded in this component for options.50pub num_runtime_reallocs: u32,51/// The number of callbacks which are recorded in this component for options.52pub num_runtime_callbacks: u32,53/// The number of post-returns which are recorded in this component for options.54pub num_runtime_post_returns: u32,55/// Number of component instances internally in the component (always at56/// least 1).57pub num_runtime_component_instances: u32,58/// Number of cranelift-compiled trampolines required for this component.59pub num_trampolines: u32,60/// Number of resources within a component which need destructors stored.61pub num_resources: u32,6263// precalculated offsets of various member fields64magic: u32,65builtins: u32,66vm_store_context: u32,67flags: u32,68trampoline_func_refs: u32,69lowerings: u32,70memories: u32,71tables: u32,72reallocs: u32,73callbacks: u32,74post_returns: u32,75resource_destructors: u32,76size: u32,77}7879#[inline]80fn align(offset: u32, align: u32) -> u32 {81assert!(align.is_power_of_two());82(offset + (align - 1)) & !(align - 1)83}8485impl<P: PtrSize> VMComponentOffsets<P> {86/// Creates a new set of offsets for the `component` specified configured87/// additionally for the `ptr` size specified.88pub fn new(ptr: P, component: &Component) -> Self {89let mut ret = Self {90ptr,91num_lowerings: component.num_lowerings,92num_runtime_memories: component.num_runtime_memories,93num_runtime_tables: component.num_runtime_tables,94num_runtime_reallocs: component.num_runtime_reallocs,95num_runtime_callbacks: component.num_runtime_callbacks,96num_runtime_post_returns: component.num_runtime_post_returns,97num_runtime_component_instances: component.num_runtime_component_instances,98num_trampolines: component.trampolines.len().try_into().unwrap(),99num_resources: component.num_resources,100magic: 0,101builtins: 0,102vm_store_context: 0,103flags: 0,104trampoline_func_refs: 0,105lowerings: 0,106memories: 0,107tables: 0,108reallocs: 0,109callbacks: 0,110post_returns: 0,111resource_destructors: 0,112size: 0,113};114115// Convenience functions for checked addition and multiplication.116// As side effect this reduces binary size by using only a single117// `#[track_caller]` location for each function instead of one for118// each individual invocation.119#[inline]120fn cmul(count: u32, size: u8) -> u32 {121count.checked_mul(u32::from(size)).unwrap()122}123124let mut next_field_offset = 0;125126macro_rules! fields {127(size($field:ident) = $size:expr, $($rest:tt)*) => {128ret.$field = next_field_offset;129next_field_offset = next_field_offset.checked_add(u32::from($size)).unwrap();130fields!($($rest)*);131};132(align($align:expr), $($rest:tt)*) => {133next_field_offset = align(next_field_offset, $align);134fields!($($rest)*);135};136() => {};137}138139fields! {140size(magic) = 4u32,141align(u32::from(ret.ptr.size())),142size(builtins) = ret.ptr.size(),143size(vm_store_context) = ret.ptr.size(),144align(16),145size(flags) = cmul(ret.num_runtime_component_instances, ret.ptr.size_of_vmglobal_definition()),146align(u32::from(ret.ptr.size())),147size(trampoline_func_refs) = cmul(ret.num_trampolines, ret.ptr.size_of_vm_func_ref()),148size(lowerings) = cmul(ret.num_lowerings, ret.ptr.size() * 2),149size(memories) = cmul(ret.num_runtime_memories, ret.ptr.size()),150size(tables) = cmul(ret.num_runtime_tables, ret.size_of_vmtable_import()),151size(reallocs) = cmul(ret.num_runtime_reallocs, ret.ptr.size()),152size(callbacks) = cmul(ret.num_runtime_callbacks, ret.ptr.size()),153size(post_returns) = cmul(ret.num_runtime_post_returns, ret.ptr.size()),154size(resource_destructors) = cmul(ret.num_resources, ret.ptr.size()),155}156157ret.size = next_field_offset;158159// This is required by the implementation of160// `VMComponentContext::from_opaque`. If this value changes then this161// location needs to be updated.162assert_eq!(ret.magic, 0);163164return ret;165}166167/// The size, in bytes, of the host pointer.168#[inline]169pub fn pointer_size(&self) -> u8 {170self.ptr.size()171}172173/// The offset of the `magic` field.174#[inline]175pub fn magic(&self) -> u32 {176self.magic177}178179/// The offset of the `builtins` field.180#[inline]181pub fn builtins(&self) -> u32 {182self.builtins183}184185/// The offset of the `flags` field.186#[inline]187pub fn instance_flags(&self, index: RuntimeComponentInstanceIndex) -> u32 {188assert!(index.as_u32() < self.num_runtime_component_instances);189self.flags + index.as_u32() * u32::from(self.ptr.size_of_vmglobal_definition())190}191192/// The offset of the `vm_store_context` field.193#[inline]194pub fn vm_store_context(&self) -> u32 {195self.vm_store_context196}197198/// The offset of the `trampoline_func_refs` field.199#[inline]200pub fn trampoline_func_refs(&self) -> u32 {201self.trampoline_func_refs202}203204/// The offset of `VMFuncRef` for the `index` specified.205#[inline]206pub fn trampoline_func_ref(&self, index: TrampolineIndex) -> u32 {207assert!(index.as_u32() < self.num_trampolines);208self.trampoline_func_refs() + index.as_u32() * u32::from(self.ptr.size_of_vm_func_ref())209}210211/// The offset of the `lowerings` field.212#[inline]213pub fn lowerings(&self) -> u32 {214self.lowerings215}216217/// The offset of the `VMLowering` for the `index` specified.218#[inline]219pub fn lowering(&self, index: LoweredIndex) -> u32 {220assert!(index.as_u32() < self.num_lowerings);221self.lowerings() + index.as_u32() * u32::from(2 * self.ptr.size())222}223224/// The offset of the `callee` for the `index` specified.225#[inline]226pub fn lowering_callee(&self, index: LoweredIndex) -> u32 {227self.lowering(index) + self.lowering_callee_offset()228}229230/// The offset of the `data` for the `index` specified.231#[inline]232pub fn lowering_data(&self, index: LoweredIndex) -> u32 {233self.lowering(index) + self.lowering_data_offset()234}235236/// The size of the `VMLowering` type237#[inline]238pub fn lowering_size(&self) -> u8 {2392 * self.ptr.size()240}241242/// The offset of the `callee` field within the `VMLowering` type.243#[inline]244pub fn lowering_callee_offset(&self) -> u32 {2450246}247248/// The offset of the `data` field within the `VMLowering` type.249#[inline]250pub fn lowering_data_offset(&self) -> u32 {251u32::from(self.ptr.size())252}253254/// The offset of the base of the `runtime_memories` field255#[inline]256pub fn runtime_memories(&self) -> u32 {257self.memories258}259260/// The offset of the `*mut VMMemoryDefinition` for the runtime index261/// provided.262#[inline]263pub fn runtime_memory(&self, index: RuntimeMemoryIndex) -> u32 {264assert!(index.as_u32() < self.num_runtime_memories);265self.runtime_memories() + index.as_u32() * u32::from(self.ptr.size())266}267268/// The offset of the base of the `runtime_tables` field269#[inline]270pub fn runtime_tables(&self) -> u32 {271self.tables272}273274/// The offset of the table for the runtime index provided.275#[inline]276pub fn runtime_table(&self, index: RuntimeTableIndex) -> u32 {277assert!(index.as_u32() < self.num_runtime_tables);278self.runtime_tables() + index.as_u32() * u32::from(self.size_of_vmtable_import())279}280281/// Return the size of `VMTableImport`, used here to hold the pointers to282/// the `VMTableDefinition` and `VMContext`.283#[inline]284pub fn size_of_vmtable_import(&self) -> u8 {2853 * self.pointer_size()286}287288/// The offset of the base of the `runtime_reallocs` field289#[inline]290pub fn runtime_reallocs(&self) -> u32 {291self.reallocs292}293294/// The offset of the `*mut VMFuncRef` for the runtime index295/// provided.296#[inline]297pub fn runtime_realloc(&self, index: RuntimeReallocIndex) -> u32 {298assert!(index.as_u32() < self.num_runtime_reallocs);299self.runtime_reallocs() + index.as_u32() * u32::from(self.ptr.size())300}301302/// The offset of the base of the `runtime_callbacks` field303#[inline]304pub fn runtime_callbacks(&self) -> u32 {305self.callbacks306}307308/// The offset of the `*mut VMFuncRef` for the runtime index309/// provided.310#[inline]311pub fn runtime_callback(&self, index: RuntimeCallbackIndex) -> u32 {312assert!(index.as_u32() < self.num_runtime_callbacks);313self.runtime_callbacks() + index.as_u32() * u32::from(self.ptr.size())314}315316/// The offset of the base of the `runtime_post_returns` field317#[inline]318pub fn runtime_post_returns(&self) -> u32 {319self.post_returns320}321322/// The offset of the `*mut VMFuncRef` for the runtime index323/// provided.324#[inline]325pub fn runtime_post_return(&self, index: RuntimePostReturnIndex) -> u32 {326assert!(index.as_u32() < self.num_runtime_post_returns);327self.runtime_post_returns() + index.as_u32() * u32::from(self.ptr.size())328}329330/// The offset of the base of the `resource_destructors` field331#[inline]332pub fn resource_destructors(&self) -> u32 {333self.resource_destructors334}335336/// The offset of the `*mut VMFuncRef` for the runtime index337/// provided.338#[inline]339pub fn resource_destructor(&self, index: ResourceIndex) -> u32 {340assert!(index.as_u32() < self.num_resources);341self.resource_destructors() + index.as_u32() * u32::from(self.ptr.size())342}343344/// Return the size of the `VMComponentContext` allocation.345#[inline]346pub fn size_of_vmctx(&self) -> u32 {347self.size348}349}350351352