11use crate :: types:: { ExportType , ExternType , ImportType } ;
22use crate :: { Engine , ModuleType } ;
33use anyhow:: { bail, Context , Result } ;
4- use bincode:: Options ;
54use std:: fs;
6- use std:: io:: Write ;
75use std:: path:: Path ;
86use std:: sync:: Arc ;
97use wasmparser:: Validator ;
@@ -15,9 +13,7 @@ use wasmtime_jit::{CompilationArtifacts, CompiledModule, TypeTables};
1513
1614mod serialization;
1715
18- use serialization:: SerializedModule ;
19-
20- const COMPILED_MODULE_HEADER : & [ u8 ] = b"\0 wasmtime-aot" ;
16+ pub use serialization:: SerializedModule ;
2117
2218/// A compiled WebAssembly module, ready to be instantiated.
2319///
@@ -111,14 +107,16 @@ struct ModuleInner {
111107impl Module {
112108 /// Creates a new WebAssembly `Module` from the given in-memory `bytes`.
113109 ///
114- /// The `bytes` provided must be in one of three formats:
110+ /// The `bytes` provided must be in one of the following formats:
115111 ///
116112 /// * A [binary-encoded][binary] WebAssembly module. This is always supported.
117113 /// * A [text-encoded][text] instance of the WebAssembly text format.
118114 /// This is only supported when the `wat` feature of this crate is enabled.
119115 /// If this is supplied then the text format will be parsed before validation.
120116 /// Note that the `wat` feature is enabled by default.
121- /// * A module compiled with [`Module::compile`] or the `wasmtime compile` command.
117+ /// * A module serialized with [`Module::serialize`].
118+ /// * A module compiled with [`Engine::precompile_module`] or the
119+ /// `wasmtime compile` command.
122120 ///
123121 /// The data for the wasm module must be loaded in-memory if it's present
124122 /// elsewhere, for example on disk. This requires that the entire binary is
@@ -177,8 +175,9 @@ impl Module {
177175 /// ```
178176 pub fn new ( engine : & Engine , bytes : impl AsRef < [ u8 ] > ) -> Result < Module > {
179177 let bytes = bytes. as_ref ( ) ;
180- if bytes. starts_with ( COMPILED_MODULE_HEADER ) {
181- return Self :: deserialize ( engine, & bytes[ COMPILED_MODULE_HEADER . len ( ) ..] ) ;
178+
179+ if let Some ( module) = SerializedModule :: from_bytes ( bytes) ? {
180+ return module. into_module ( engine) ;
182181 }
183182
184183 #[ cfg( feature = "wat" ) ]
@@ -267,8 +266,8 @@ impl Module {
267266 /// # }
268267 /// ```
269268 pub fn from_binary ( engine : & Engine , binary : & [ u8 ] ) -> Result < Module > {
270- if binary . starts_with ( COMPILED_MODULE_HEADER ) {
271- return Self :: deserialize ( engine , & binary [ COMPILED_MODULE_HEADER . len ( ) .. ] ) ;
269+ if let Some ( module ) = SerializedModule :: from_bytes ( binary ) ? {
270+ return module . into_module ( engine ) ;
272271 }
273272
274273 // Check to see that the config's target matches the host
@@ -344,41 +343,6 @@ impl Module {
344343 Ok ( ( ) )
345344 }
346345
347- /// Ahead-of-time (AOT) compiles a WebAssembly module.
348- ///
349- /// The `bytes` provided must be in one of two formats:
350- ///
351- /// * A [binary-encoded][binary] WebAssembly module. This is always supported.
352- /// * A [text-encoded][text] instance of the WebAssembly text format.
353- /// This is only supported when the `wat` feature of this crate is enabled.
354- /// If this is supplied then the text format will be parsed before validation.
355- /// Note that the `wat` feature is enabled by default.
356- ///
357- /// See [`Module::new`] for errors that may be returned by this function.
358- ///
359- /// [binary]: https://webassembly.github.io/spec/core/binary/index.html
360- /// [text]: https://webassembly.github.io/spec/core/text/index.html
361- pub fn compile ( engine : & Engine , bytes : & [ u8 ] , mut output : impl Write ) -> Result < ( ) > {
362- const USE_PAGED_MEM_INIT : bool = cfg ! ( all( feature = "uffd" , target_os = "linux" ) ) ;
363-
364- if bytes. starts_with ( COMPILED_MODULE_HEADER ) {
365- bail ! ( "input is already a compiled module" ) ;
366- }
367-
368- #[ cfg( feature = "wat" ) ]
369- let bytes = wat:: parse_bytes ( & bytes) ?;
370-
371- let ( _, artifacts, types) =
372- CompilationArtifacts :: build ( engine. compiler ( ) , & bytes, USE_PAGED_MEM_INIT ) ?;
373-
374- // Write a header that marks this as a compiled module
375- output. write_all ( COMPILED_MODULE_HEADER ) ?;
376- Self :: serialize_module (
377- & SerializedModule :: from_artifacts ( engine. compiler ( ) , & artifacts, & types) ,
378- output,
379- )
380- }
381-
382346 /// Returns the type signature of this module.
383347 pub fn ty ( & self ) -> ModuleType {
384348 let mut sig = ModuleType :: new ( ) ;
@@ -396,58 +360,12 @@ impl Module {
396360 sig
397361 }
398362
399- /// Serialize compilation artifacts to the buffer. See also `deserialize`.
363+ /// Serialize the module to a vector of bytes.
364+ ///
365+ /// Use `Module::new` or `Module::from_binary` to create the module
366+ /// from the bytes.
400367 pub fn serialize ( & self ) -> Result < Vec < u8 > > {
401- let mut buffer = Vec :: new ( ) ;
402- Self :: serialize_module ( & SerializedModule :: new ( self ) , & mut buffer) ?;
403- Ok ( buffer)
404- }
405-
406- fn serialize_module ( module : & SerializedModule , mut output : impl Write ) -> Result < ( ) > {
407- // Preface the data with a version so we can do a version check independent
408- // of the serialized data.
409- let version = env ! ( "CARGO_PKG_VERSION" ) ;
410- assert ! (
411- version. len( ) < 256 ,
412- "package version must be less than 256 bytes"
413- ) ;
414- output. write ( & [ version. len ( ) as u8 ] ) ?;
415- output. write_all ( version. as_bytes ( ) ) ?;
416- bincode_options ( ) . serialize_into ( output, module) ?;
417- Ok ( ( ) )
418- }
419-
420- /// Deserializes and creates a module from the compilation artifacts.
421- /// The `serialize` saves the compilation artifacts along with the host
422- /// fingerprint, which consists of target, compiler flags, and wasmtime
423- /// package version.
424- ///
425- /// The method will fail if fingerprints of current host and serialized
426- /// one are different. The method does not verify the serialized artifacts
427- /// for modifications or corruptions. All responsibly of signing and its
428- /// verification falls on the embedder.
429- pub fn deserialize ( engine : & Engine , serialized : & [ u8 ] ) -> Result < Module > {
430- if serialized. is_empty ( ) {
431- bail ! ( "serialized data data is empty" ) ;
432- }
433-
434- let version_len = serialized[ 0 ] as usize ;
435- if serialized. len ( ) < version_len + 1 {
436- bail ! ( "serialized data is malformed" ) ;
437- }
438-
439- let version = std:: str:: from_utf8 ( & serialized[ 1 ..1 + version_len] ) ?;
440- if version != env ! ( "CARGO_PKG_VERSION" ) {
441- bail ! (
442- "Module was compiled with incompatible Wasmtime version '{}'" ,
443- version
444- ) ;
445- }
446-
447- bincode_options ( )
448- . deserialize :: < SerializedModule < ' _ > > ( & serialized[ 1 + version_len..] )
449- . context ( "Deserialize compilation artifacts" ) ?
450- . into_module ( engine)
368+ SerializedModule :: new ( self ) . to_bytes ( )
451369 }
452370
453371 /// Creates a submodule `Module` value from the specified parameters.
@@ -732,17 +650,6 @@ impl Module {
732650 }
733651}
734652
735- fn bincode_options ( ) -> impl Options {
736- // Use a variable-length integer encoding instead of fixed length. The
737- // module shown on #2318 gets compressed from ~160MB to ~110MB simply using
738- // this, presumably because there's a lot of 8-byte integers which generally
739- // have small values. Local testing shows that the deserialization
740- // performance, while higher, is in the few-percent range. For huge size
741- // savings this seems worthwhile to lose a small percentage of
742- // deserialization performance.
743- bincode:: DefaultOptions :: new ( ) . with_varint_encoding ( )
744- }
745-
746653fn _assert_send_sync ( ) {
747654 fn _assert < T : Send + Sync > ( ) { }
748655 _assert :: < Module > ( ) ;
0 commit comments