sc_executor_wasmtime/
host.rs1use wasmtime::Caller;
23
24use sc_allocator::{AllocationStats, FreeingBumpHeapAllocator};
25use sp_wasm_interface::{Pointer, WordSize};
26
27use crate::{instance_wrapper::MemoryWrapper, runtime::StoreData, util};
28
29pub struct HostState {
33 allocator: Option<FreeingBumpHeapAllocator>,
39 panic_message: Option<String>,
40}
41
42impl HostState {
43 pub fn new(allocator: FreeingBumpHeapAllocator) -> Self {
45 HostState { allocator: Some(allocator), panic_message: None }
46 }
47
48 pub fn take_panic_message(&mut self) -> Option<String> {
50 self.panic_message.take()
51 }
52
53 pub(crate) fn allocation_stats(&self) -> AllocationStats {
54 self.allocator.as_ref()
55 .expect("Allocator is always set and only unavailable when doing an allocation/deallocation; qed")
56 .stats()
57 }
58}
59
60pub(crate) struct HostContext<'a> {
64 pub(crate) caller: Caller<'a, StoreData>,
65}
66
67impl<'a> HostContext<'a> {
68 fn host_state_mut(&mut self) -> &mut HostState {
69 self.caller
70 .data_mut()
71 .host_state_mut()
72 .expect("host state is not empty when calling a function in wasm; qed")
73 }
74}
75
76impl<'a> sp_wasm_interface::FunctionContext for HostContext<'a> {
77 fn read_memory_into(
78 &self,
79 address: Pointer<u8>,
80 dest: &mut [u8],
81 ) -> sp_wasm_interface::Result<()> {
82 util::read_memory_into(&self.caller, address, dest).map_err(|e| e.to_string())
83 }
84
85 fn write_memory(&mut self, address: Pointer<u8>, data: &[u8]) -> sp_wasm_interface::Result<()> {
86 util::write_memory_from(&mut self.caller, address, data).map_err(|e| e.to_string())
87 }
88
89 fn allocate_memory(&mut self, size: WordSize) -> sp_wasm_interface::Result<Pointer<u8>> {
90 let memory = self.caller.data().memory();
91 let mut allocator = self
92 .host_state_mut()
93 .allocator
94 .take()
95 .expect("allocator is not empty when calling a function in wasm; qed");
96
97 let res = allocator
99 .allocate(&mut MemoryWrapper(&memory, &mut self.caller), size)
100 .map_err(|e| e.to_string());
101
102 self.host_state_mut().allocator = Some(allocator);
103
104 res
105 }
106
107 fn deallocate_memory(&mut self, ptr: Pointer<u8>) -> sp_wasm_interface::Result<()> {
108 let memory = self.caller.data().memory();
109 let mut allocator = self
110 .host_state_mut()
111 .allocator
112 .take()
113 .expect("allocator is not empty when calling a function in wasm; qed");
114
115 let res = allocator
117 .deallocate(&mut MemoryWrapper(&memory, &mut self.caller), ptr)
118 .map_err(|e| e.to_string());
119
120 self.host_state_mut().allocator = Some(allocator);
121
122 res
123 }
124
125 fn register_panic_error_message(&mut self, message: &str) {
126 self.host_state_mut().panic_message = Some(message.to_owned());
127 }
128}