Update wasmtime to 0.29.0 (#9552)

* Start

* Move to ctx

* Make it compile for now

* More work

* Get rid off state-holder

* Use less Refcells

* 🤦

* Don't use RefCell

* Use names for parameters

* Fixes after merge

* Fixes after merge

* Review feedback

* FMT
This commit is contained in:
Bastian Köcher
2021-09-29 14:30:46 +02:00
committed by GitHub
parent e64693933f
commit 2deed49706
19 changed files with 451 additions and 430 deletions
+56 -27
View File
@@ -19,7 +19,7 @@
//! This module defines `HostState` and `HostContext` structs which provide logic and state
//! required for execution of host.
use crate::instance_wrapper::InstanceWrapper;
use crate::{instance_wrapper::InstanceWrapper, runtime::StoreData};
use codec::{Decode, Encode};
use log::trace;
use sc_allocator::FreeingBumpHeapAllocator;
@@ -31,7 +31,7 @@ use sc_executor_common::{
use sp_core::sandbox as sandbox_primitives;
use sp_wasm_interface::{FunctionContext, MemoryId, Pointer, Sandbox, WordSize};
use std::{cell::RefCell, rc::Rc};
use wasmtime::{Func, Val};
use wasmtime::{Caller, Func, Val};
/// The state required to construct a HostContext context. The context only lasts for one host
/// call, whereas the state is maintained for the duration of a Wasm runtime call, which may make
@@ -64,45 +64,67 @@ impl HostState {
}
/// Materialize `HostContext` that can be used to invoke a substrate host `dyn Function`.
pub fn materialize<'a>(&'a self) -> HostContext<'a> {
HostContext(self)
pub(crate) fn materialize<'a, 'b, 'c>(
&'a self,
caller: &'b mut Caller<'c, StoreData>,
) -> HostContext<'a, 'b, 'c> {
HostContext { host_state: self, caller }
}
}
/// A `HostContext` implements `FunctionContext` for making host calls from a Wasmtime
/// runtime. The `HostContext` exists only for the lifetime of the call and borrows state from
/// a longer-living `HostState`.
pub struct HostContext<'a>(&'a HostState);
pub(crate) struct HostContext<'a, 'b, 'c> {
host_state: &'a HostState,
caller: &'b mut Caller<'c, StoreData>,
}
impl<'a> std::ops::Deref for HostContext<'a> {
impl<'a, 'b, 'c> std::ops::Deref for HostContext<'a, 'b, 'c> {
type Target = HostState;
fn deref(&self) -> &HostState {
self.0
self.host_state
}
}
impl<'a> sp_wasm_interface::FunctionContext for HostContext<'a> {
impl<'a, 'b, 'c> sp_wasm_interface::FunctionContext for HostContext<'a, 'b, 'c> {
fn read_memory_into(
&self,
address: Pointer<u8>,
dest: &mut [u8],
) -> sp_wasm_interface::Result<()> {
self.instance.read_memory_into(address, dest).map_err(|e| e.to_string())
let ctx = &self.caller;
self.host_state
.instance
.read_memory_into(ctx, address, dest)
.map_err(|e| e.to_string())
}
fn write_memory(&mut self, address: Pointer<u8>, data: &[u8]) -> sp_wasm_interface::Result<()> {
self.instance.write_memory_from(address, data).map_err(|e| e.to_string())
let ctx = &mut self.caller;
self.host_state
.instance
.write_memory_from(ctx, address, data)
.map_err(|e| e.to_string())
}
fn allocate_memory(&mut self, size: WordSize) -> sp_wasm_interface::Result<Pointer<u8>> {
self.instance
.allocate(&mut *self.allocator.borrow_mut(), size)
let ctx = &mut self.caller;
let allocator = &self.host_state.allocator;
self.host_state
.instance
.allocate(ctx, &mut *allocator.borrow_mut(), size)
.map_err(|e| e.to_string())
}
fn deallocate_memory(&mut self, ptr: Pointer<u8>) -> sp_wasm_interface::Result<()> {
self.instance
.deallocate(&mut *self.allocator.borrow_mut(), ptr)
let ctx = &mut self.caller;
let allocator = &self.host_state.allocator;
self.host_state
.instance
.deallocate(ctx, &mut *allocator.borrow_mut(), ptr)
.map_err(|e| e.to_string())
}
@@ -111,7 +133,7 @@ impl<'a> sp_wasm_interface::FunctionContext for HostContext<'a> {
}
}
impl<'a> Sandbox for HostContext<'a> {
impl<'a, 'b, 'c> Sandbox for HostContext<'a, 'b, 'c> {
fn memory_get(
&mut self,
memory_id: MemoryId,
@@ -129,7 +151,8 @@ impl<'a> Sandbox for HostContext<'a> {
Ok(buffer) => buffer,
};
if let Err(_) = self.instance.write_memory_from(buf_ptr, &buffer) {
let instance = self.instance.clone();
if let Err(_) = instance.write_memory_from(&mut self.caller, buf_ptr, &buffer) {
return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS)
}
@@ -148,7 +171,7 @@ impl<'a> Sandbox for HostContext<'a> {
let len = val_len as usize;
let buffer = match self.instance.read_memory(val_ptr, len) {
let buffer = match self.instance.read_memory(&self.caller, val_ptr, len) {
Err(_) => return Ok(sandbox_primitives::ERR_OUT_OF_BOUNDS),
Ok(buffer) => buffer,
};
@@ -241,12 +264,14 @@ impl<'a> Sandbox for HostContext<'a> {
) -> sp_wasm_interface::Result<u32> {
// Extract a dispatch thunk from the instance's table by the specified index.
let dispatch_thunk = {
let ctx = &mut self.caller;
let table_item = self
.host_state
.instance
.table()
.as_ref()
.ok_or_else(|| "Runtime doesn't have a table; sandbox is unavailable")?
.get(dispatch_thunk_id);
.get(ctx, dispatch_thunk_id);
table_item
.ok_or_else(|| "dispatch_thunk_id is out of bounds")?
@@ -295,12 +320,12 @@ impl<'a> Sandbox for HostContext<'a> {
}
}
struct SandboxContext<'a, 'b> {
host_context: &'a mut HostContext<'b>,
struct SandboxContext<'a, 'b, 'c, 'd> {
host_context: &'a mut HostContext<'b, 'c, 'd>,
dispatch_thunk: Func,
}
impl<'a, 'b> sandbox::SandboxContext for SandboxContext<'a, 'b> {
impl<'a, 'b, 'c, 'd> sandbox::SandboxContext for SandboxContext<'a, 'b, 'c, 'd> {
fn invoke(
&mut self,
invoke_args_ptr: Pointer<u8>,
@@ -308,12 +333,16 @@ impl<'a, 'b> sandbox::SandboxContext for SandboxContext<'a, 'b> {
state: u32,
func_idx: SupervisorFuncIndex,
) -> Result<i64> {
let result = self.dispatch_thunk.call(&[
Val::I32(u32::from(invoke_args_ptr) as i32),
Val::I32(invoke_args_len as i32),
Val::I32(state as i32),
Val::I32(usize::from(func_idx) as i32),
]);
let result = self.dispatch_thunk.call(
&mut self.host_context.caller,
&[
Val::I32(u32::from(invoke_args_ptr) as i32),
Val::I32(invoke_args_len as i32),
Val::I32(state as i32),
Val::I32(usize::from(func_idx) as i32),
],
);
match result {
Ok(ret_vals) => {
let ret_val = if ret_vals.len() != 1 {