Implement canon lower of a canon lift function in the same component (#4347)

* Implement `canon lower` of a `canon lift` function in the same component

This commit implements the "degenerate" logic for implementing a
function within a component that is lifted and then immediately lowered
again. In this situation the lowered function will immediately generate
a trap and doesn't need to implement anything else.

The implementation in this commit is somewhat heavyweight but I think is
probably justified moreso in future additions to the component model
rather than what exactly is here right now. It's not expected that this
"always trap" functionality will really be used all that often since it
would generally mean a buggy component, but the functionality plumbed
through here is hopefully going to be useful for implementing
component-to-component adapter trampolines.

Specifically this commit implements a strategy where the `canon.lower`'d
function is generated by Cranelift and simply has a single trap
instruction when called, doing nothing else. The main complexity comes
from juggling around all the data associated with these functions,
primarily plumbing through the traps into the `ModuleRegistry` to
ensure that the global `is_wasm_trap_pc` function returns `true` and at
runtime when we lookup information about the trap it's all readily
available (e.g. translating the trapping pc to a `TrapCode`).

* Fix non-component build

* Fix some offset calculations

* Only create one "always trap" per signature

Use an internal map to deduplicate during compilation.
This commit is contained in:
Alex Crichton
2022-06-29 11:35:37 -05:00
committed by GitHub
parent 22fb3ecbbf
commit f0278c5db7
16 changed files with 664 additions and 164 deletions

View File

@@ -17,10 +17,10 @@ use std::mem;
use std::ops::Deref;
use std::ptr::{self, NonNull};
use wasmtime_environ::component::{
Component, LoweredIndex, RuntimeComponentInstanceIndex, RuntimeMemoryIndex,
RuntimePostReturnIndex, RuntimeReallocIndex, StringEncoding, VMComponentOffsets,
VMCOMPONENT_FLAG_MAY_ENTER, VMCOMPONENT_FLAG_MAY_LEAVE, VMCOMPONENT_FLAG_NEEDS_POST_RETURN,
VMCOMPONENT_MAGIC,
Component, LoweredIndex, RuntimeAlwaysTrapIndex, RuntimeComponentInstanceIndex,
RuntimeMemoryIndex, RuntimePostReturnIndex, RuntimeReallocIndex, StringEncoding,
VMComponentOffsets, VMCOMPONENT_FLAG_MAY_ENTER, VMCOMPONENT_FLAG_MAY_LEAVE,
VMCOMPONENT_FLAG_NEEDS_POST_RETURN, VMCOMPONENT_MAGIC,
};
use wasmtime_environ::HostPtr;
@@ -259,6 +259,20 @@ impl ComponentInstance {
}
}
/// Same as `lowering_anyfunc` except for the functions that always trap.
pub fn always_trap_anyfunc(
&self,
idx: RuntimeAlwaysTrapIndex,
) -> NonNull<VMCallerCheckedAnyfunc> {
unsafe {
let ret = self
.vmctx_plus_offset::<VMCallerCheckedAnyfunc>(self.offsets.always_trap_anyfunc(idx));
debug_assert!((*ret).func_ptr.as_ptr() as usize != INVALID_PTR);
debug_assert!((*ret).vmctx as usize != INVALID_PTR);
NonNull::new(ret).unwrap()
}
}
/// Stores the runtime memory pointer at the index specified.
///
/// This is intended to be called during the instantiation process of a
@@ -340,6 +354,28 @@ impl ComponentInstance {
}
}
/// Same as `set_lowering` but for the "always trap" functions.
pub fn set_always_trap(
&mut self,
idx: RuntimeAlwaysTrapIndex,
func_ptr: NonNull<VMFunctionBody>,
type_index: VMSharedSignatureIndex,
) {
unsafe {
debug_assert!(
*self.vmctx_plus_offset::<usize>(self.offsets.always_trap_anyfunc(idx))
== INVALID_PTR
);
let vmctx = self.vmctx();
*self.vmctx_plus_offset(self.offsets.always_trap_anyfunc(idx)) =
VMCallerCheckedAnyfunc {
func_ptr,
type_index,
vmctx: VMOpaqueContext::from_vmcomponent(vmctx),
};
}
}
unsafe fn initialize_vmctx(&mut self, store: *mut dyn Store) {
*self.vmctx_plus_offset(self.offsets.magic()) = VMCOMPONENT_MAGIC;
*self.vmctx_plus_offset(self.offsets.store()) = store;
@@ -362,6 +398,11 @@ impl ComponentInstance {
let offset = self.offsets.lowering_anyfunc(i);
*self.vmctx_plus_offset(offset) = INVALID_PTR;
}
for i in 0..self.offsets.num_always_trap {
let i = RuntimeAlwaysTrapIndex::from_u32(i);
let offset = self.offsets.always_trap_anyfunc(i);
*self.vmctx_plus_offset(offset) = INVALID_PTR;
}
for i in 0..self.offsets.num_runtime_memories {
let i = RuntimeMemoryIndex::from_u32(i);
let offset = self.offsets.runtime_memory(i);
@@ -476,6 +517,19 @@ impl OwnedComponentInstance {
.set_lowering(idx, lowering, anyfunc_func_ptr, anyfunc_type_index)
}
}
/// See `ComponentInstance::set_always_trap`
pub fn set_always_trap(
&mut self,
idx: RuntimeAlwaysTrapIndex,
func_ptr: NonNull<VMFunctionBody>,
type_index: VMSharedSignatureIndex,
) {
unsafe {
self.instance_mut()
.set_always_trap(idx, func_ptr, type_index)
}
}
}
impl Deref for OwnedComponentInstance {