wasmtime/compile/
runtime.rs1use crate::compile::HashedEngineCompileEnv;
2#[cfg(feature = "component-model")]
3use crate::component::Component;
4use crate::prelude::*;
5use crate::runtime::vm::MmapVec;
6use crate::{CodeBuilder, CodeMemory, Engine, Module};
7use object::write::WritableBuffer;
8use std::sync::Arc;
9use wasmtime_environ::{FinishedObject, ObjectBuilder, ObjectKind};
10
11impl<'a> CodeBuilder<'a> {
12 fn compile_cached<T>(
13 &self,
14 build_artifacts: fn(&Engine, &[u8], Option<&[u8]>) -> Result<(MmapVecWrapper, Option<T>)>,
15 ) -> Result<(Arc<CodeMemory>, Option<T>)> {
16 let wasm = self.get_wasm()?;
17 let dwarf_package = self.get_dwarf_package();
18
19 self.engine
20 .check_compatible_with_native_host()
21 .context("compilation settings are not compatible with the native host")?;
22
23 #[cfg(feature = "cache")]
24 {
25 let state = (
26 HashedEngineCompileEnv(self.engine),
27 &wasm,
28 &dwarf_package,
29 NotHashed(build_artifacts),
31 );
32 let (code, info_and_types) =
33 wasmtime_cache::ModuleCacheEntry::new("wasmtime", self.engine.cache_config())
34 .get_data_raw(
35 &state,
36 |(engine, wasm, dwarf_package, build_artifacts)| -> Result<_> {
38 let (mmap, info) =
39 (build_artifacts.0)(engine.0, wasm, dwarf_package.as_deref())?;
40 let code = publish_mmap(mmap.0)?;
41 Ok((code, info))
42 },
43 |(_engine, _wasm, _, _), (code, _info_and_types)| {
45 Some(code.mmap().to_vec())
46 },
47 |(engine, wasm, _, _), serialized_bytes| {
49 let kind = if wasmparser::Parser::is_component(&wasm) {
50 ObjectKind::Component
51 } else {
52 ObjectKind::Module
53 };
54 let code = engine.0.load_code_bytes(&serialized_bytes, kind).ok()?;
55 Some((code, None))
56 },
57 )?;
58 return Ok((code, info_and_types));
59 }
60
61 #[cfg(not(feature = "cache"))]
62 {
63 let (mmap, info_and_types) =
64 build_artifacts(self.engine, &wasm, dwarf_package.as_deref())?;
65 let code = publish_mmap(mmap.0)?;
66 return Ok((code, info_and_types));
67 }
68
69 struct NotHashed<T>(T);
70
71 impl<T> std::hash::Hash for NotHashed<T> {
72 fn hash<H: std::hash::Hasher>(&self, _hasher: &mut H) {}
73 }
74 }
75
76 pub fn compile_module(&self) -> Result<Module> {
82 let (code, info_and_types) = self.compile_cached(super::build_artifacts)?;
83 Module::from_parts(self.engine, code, info_and_types)
84 }
85
86 #[cfg(feature = "component-model")]
89 pub fn compile_component(&self) -> Result<Component> {
90 let (code, artifacts) = self.compile_cached(super::build_component_artifacts)?;
91 Component::from_parts(self.engine, code, artifacts)
92 }
93}
94
95fn publish_mmap(mmap: MmapVec) -> Result<Arc<CodeMemory>> {
96 let mut code = CodeMemory::new(mmap)?;
97 code.publish()?;
98 Ok(Arc::new(code))
99}
100
101pub(crate) struct MmapVecWrapper(pub MmapVec);
102
103impl FinishedObject for MmapVecWrapper {
104 fn finish_object(obj: ObjectBuilder<'_>) -> Result<Self> {
105 let mut result = ObjectMmap::default();
106 return match obj.finish(&mut result) {
107 Ok(()) => {
108 assert!(result.mmap.is_some(), "no reserve");
109 let mmap = result.mmap.expect("reserve not called");
110 assert_eq!(mmap.len(), result.len);
111 Ok(MmapVecWrapper(mmap))
112 }
113 Err(e) => match result.err.take() {
114 Some(original) => Err(original.context(e)),
115 None => Err(e.into()),
116 },
117 };
118
119 #[derive(Default)]
127 struct ObjectMmap {
128 mmap: Option<MmapVec>,
129 len: usize,
130 err: Option<Error>,
131 }
132
133 impl WritableBuffer for ObjectMmap {
134 fn len(&self) -> usize {
135 self.len
136 }
137
138 fn reserve(&mut self, additional: usize) -> Result<(), ()> {
139 assert!(self.mmap.is_none(), "cannot reserve twice");
140 self.mmap = match MmapVec::with_capacity(additional) {
141 Ok(mmap) => Some(mmap),
142 Err(e) => {
143 self.err = Some(e);
144 return Err(());
145 }
146 };
147 Ok(())
148 }
149
150 fn resize(&mut self, new_len: usize) {
151 if new_len <= self.len {
155 return;
156 }
157 self.len = new_len;
158 }
159
160 fn write_bytes(&mut self, val: &[u8]) {
161 let mmap = self.mmap.as_mut().expect("write before reserve");
162 mmap[self.len..][..val.len()].copy_from_slice(val);
163 self.len += val.len();
164 }
165 }
166 }
167}