feat(runtime-c-api) Introduce the wasmer_serialized_module_t struct type.

The `wasmer_module_serialize` function now computes a
`wasmer_serialized_module_t` value. The `wasmer_module_deserialize`
function takes this value as an input. Same for
`wasmer_serialized_module_destroy`.

The new function `wasmer_serialized_module_bytes` allows to read the
bytes inside the `wasmer_serialized_mdule_t` structure.
This commit is contained in:
Ivan Enderlin
2019-03-19 10:04:31 +01:00
parent f049e9b0b3
commit 5e31a1b6d1
4 changed files with 78 additions and 53 deletions

View File

@ -7,7 +7,6 @@ use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::ffi::CStr; use std::ffi::CStr;
use std::fmt; use std::fmt;
use std::mem;
use std::slice; use std::slice;
use std::sync::Arc; use std::sync::Arc;
use std::{ffi::c_void, ptr}; use std::{ffi::c_void, ptr};
@ -25,6 +24,9 @@ use wasmer_runtime_core::units::{Bytes, Pages};
#[repr(C)] #[repr(C)]
pub struct wasmer_module_t; pub struct wasmer_module_t;
#[repr(C)]
pub struct wasmer_serialized_module_t;
#[repr(C)] #[repr(C)]
pub struct wasmer_instance_t; pub struct wasmer_instance_t;
@ -574,7 +576,7 @@ pub unsafe extern "C" fn wasmer_export_descriptor_kind(
/// Serialize the given Module. /// Serialize the given Module.
/// ///
/// The caller owns the object and should call `wasmer_memory_serialization_destroy` to free it. /// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it.
/// ///
/// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_OK` upon success.
/// ///
@ -583,7 +585,7 @@ pub unsafe extern "C" fn wasmer_export_descriptor_kind(
#[allow(clippy::cast_ptr_alignment)] #[allow(clippy::cast_ptr_alignment)]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasmer_module_serialize( pub unsafe extern "C" fn wasmer_module_serialize(
serialized_module: *mut *mut wasmer_byte_array, serialized_module: *mut *mut wasmer_serialized_module_t,
module: *const wasmer_module_t, module: *const wasmer_module_t,
) -> wasmer_result_t { ) -> wasmer_result_t {
let module = &*(module as *const Module); let module = &*(module as *const Module);
@ -591,12 +593,7 @@ pub unsafe extern "C" fn wasmer_module_serialize(
match module.cache() { match module.cache() {
Ok(artifact) => match artifact.serialize() { Ok(artifact) => match artifact.serialize() {
Ok(serialized_artifact) => { Ok(serialized_artifact) => {
*serialized_module = Box::into_raw(Box::new(wasmer_byte_array { *serialized_module = Box::into_raw(Box::new(serialized_artifact)) as _;
bytes: serialized_artifact.as_ptr(),
bytes_len: serialized_artifact.len() as u32,
})) as *mut wasmer_byte_array;
mem::forget(serialized_artifact);
wasmer_result_t::WASMER_OK wasmer_result_t::WASMER_OK
} }
@ -616,16 +613,21 @@ pub unsafe extern "C" fn wasmer_module_serialize(
} }
} }
/// Frees memory for the given serialized Module. /// Get bytes of the serialized module.
#[allow(clippy::cast_ptr_alignment)] #[allow(clippy::cast_ptr_alignment)]
#[no_mangle] #[no_mangle]
pub extern "C" fn wasmer_module_serialization_destroy(serialized_module: *mut wasmer_byte_array) { pub unsafe extern "C" fn wasmer_serialized_module_bytes(
if !serialized_module.is_null() { serialized_module: *const wasmer_serialized_module_t,
unsafe { Box::from_raw(serialized_module as *mut wasmer_byte_array) }; ) -> wasmer_byte_array {
let serialized_module = &*(serialized_module as *const &[u8]);
wasmer_byte_array {
bytes: serialized_module.as_ptr(),
bytes_len: serialized_module.len() as u32,
} }
} }
/// Deserialize the given bytes into a Module. /// Deserialize the given serialized module.
/// ///
/// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_OK` upon success.
/// ///
@ -635,20 +637,16 @@ pub extern "C" fn wasmer_module_serialization_destroy(serialized_module: *mut wa
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn wasmer_module_deserialize( pub unsafe extern "C" fn wasmer_module_deserialize(
module: *mut *mut wasmer_module_t, module: *mut *mut wasmer_module_t,
serialized_module_bytes: *const uint8_t, serialized_module: *const wasmer_serialized_module_t,
serialized_module_bytes_len: uint32_t,
) -> wasmer_result_t { ) -> wasmer_result_t {
if serialized_module_bytes.is_null() { if serialized_module.is_null() {
update_last_error(CApiError { update_last_error(CApiError {
msg: "`serialized_module_bytes` pointer is null".to_string(), msg: "`serialized_module` pointer is null".to_string(),
}); });
return wasmer_result_t::WASMER_ERROR; return wasmer_result_t::WASMER_ERROR;
} }
let serialized_module: &[u8] = slice::from_raw_parts( let serialized_module: &[u8] = &*(serialized_module as *const &[u8]);
serialized_module_bytes,
serialized_module_bytes_len as usize,
);
match Artifact::deserialize(serialized_module) { match Artifact::deserialize(serialized_module) {
Ok(artifact) => match load_cache_with(artifact, default_compiler()) { Ok(artifact) => match load_cache_with(artifact, default_compiler()) {
@ -672,6 +670,17 @@ pub unsafe extern "C" fn wasmer_module_deserialize(
} }
} }
/// Frees memory for the given serialized Module.
#[allow(clippy::cast_ptr_alignment)]
#[no_mangle]
pub extern "C" fn wasmer_serialized_module_destroy(
serialized_module: *mut wasmer_serialized_module_t,
) {
if !serialized_module.is_null() {
unsafe { Box::from_raw(serialized_module as *mut &[u8]) };
}
}
/// Frees memory for the given Module /// Frees memory for the given Module
#[allow(clippy::cast_ptr_alignment)] #[allow(clippy::cast_ptr_alignment)]
#[no_mangle] #[no_mangle]

View File

@ -19,23 +19,25 @@ int main()
printf("Compile result: %d\n", compile_result); printf("Compile result: %d\n", compile_result);
assert(compile_result == WASMER_OK); assert(compile_result == WASMER_OK);
wasmer_byte_array *serialized_module = NULL; wasmer_serialized_module_t *serialized_module = NULL;
wasmer_result_t serialize_result = wasmer_module_serialize(&serialized_module, module_one); wasmer_result_t serialize_result = wasmer_module_serialize(&serialized_module, module_one);
printf("Serialize result: %d\n", serialize_result); printf("Serialize result: %d\n", serialize_result);
printf("Serialized module pointer: %p\n", serialized_module->bytes);
printf("Serialized module length: %d\n", serialized_module->bytes_len);
assert(serialize_result == WASMER_OK); assert(serialize_result == WASMER_OK);
assert(serialized_module->bytes != NULL);
assert(serialized_module->bytes_len > 8); wasmer_byte_array serialized_module_bytes = wasmer_serialized_module_bytes(serialized_module);
assert(serialized_module->bytes[0] == 'W'); printf("Serialized module pointer: %p\n", serialized_module_bytes.bytes);
assert(serialized_module->bytes[1] == 'A'); printf("Serialized module length: %d\n", serialized_module_bytes.bytes_len);
assert(serialized_module->bytes[2] == 'S'); assert(serialized_module_bytes.bytes != NULL);
assert(serialized_module->bytes[3] == 'M'); assert(serialized_module_bytes.bytes_len > 8);
assert(serialized_module->bytes[4] == 'E'); assert(serialized_module_bytes.bytes[0] == 'W');
assert(serialized_module->bytes[5] == 'R'); assert(serialized_module_bytes.bytes[1] == 'A');
assert(serialized_module_bytes.bytes[2] == 'S');
assert(serialized_module_bytes.bytes[3] == 'M');
assert(serialized_module_bytes.bytes[4] == 'E');
assert(serialized_module_bytes.bytes[5] == 'R');
wasmer_module_t *module_two = NULL; wasmer_module_t *module_two = NULL;
wasmer_result_t unserialize_result = wasmer_module_deserialize(&module_two, serialized_module->bytes, serialized_module->bytes_len); wasmer_result_t unserialize_result = wasmer_module_deserialize(&module_two, serialized_module);
assert(unserialize_result == WASMER_OK); assert(unserialize_result == WASMER_OK);
wasmer_import_t imports[] = {}; wasmer_import_t imports[] = {};
@ -62,7 +64,7 @@ int main()
assert(call_result == WASMER_OK); assert(call_result == WASMER_OK);
printf("Destroy the serialized module\n"); printf("Destroy the serialized module\n");
wasmer_module_serialization_destroy(serialized_module); wasmer_serialized_module_destroy(serialized_module);
printf("Destroy instance\n"); printf("Destroy instance\n");
wasmer_instance_destroy(instance); wasmer_instance_destroy(instance);

View File

@ -129,6 +129,10 @@ typedef struct {
wasmer_limit_option_t max; wasmer_limit_option_t max;
} wasmer_limits_t; } wasmer_limits_t;
typedef struct {
} wasmer_serialized_module_t;
/** /**
* Creates a new Module from the given wasm bytes. * Creates a new Module from the given wasm bytes.
* Returns `wasmer_result_t::WASMER_OK` upon success. * Returns `wasmer_result_t::WASMER_OK` upon success.
@ -489,14 +493,13 @@ uint32_t wasmer_memory_length(const wasmer_memory_t *memory);
wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits);
/** /**
* Deserialize the given bytes into a Module. * Deserialize the given serialized module.
* Returns `wasmer_result_t::WASMER_OK` upon success. * Returns `wasmer_result_t::WASMER_OK` upon success.
* Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
* and `wasmer_last_error_message` to get an error message. * and `wasmer_last_error_message` to get an error message.
*/ */
wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module, wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module,
const uint8_t *serialized_module_bytes, const wasmer_serialized_module_t *serialized_module);
uint32_t serialized_module_bytes_len);
/** /**
* Frees memory for the given Module * Frees memory for the given Module
@ -514,21 +517,26 @@ wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module,
wasmer_import_t *imports, wasmer_import_t *imports,
int imports_len); int imports_len);
/**
* Frees memory for the given serialized Module.
*/
void wasmer_module_serialization_destroy(wasmer_byte_array *serialized_module);
/** /**
* Serialize the given Module. * Serialize the given Module.
* The caller owns the object and should call `wasmer_memory_serialization_destroy` to free it. * The caller owns the object and should call `wasmer_serialized_module_destroy` to free it.
* Returns `wasmer_result_t::WASMER_OK` upon success. * Returns `wasmer_result_t::WASMER_OK` upon success.
* Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` * Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
* and `wasmer_last_error_message` to get an error message. * and `wasmer_last_error_message` to get an error message.
*/ */
wasmer_result_t wasmer_module_serialize(wasmer_byte_array **serialized_module, wasmer_result_t wasmer_module_serialize(wasmer_serialized_module_t **serialized_module,
const wasmer_module_t *module); const wasmer_module_t *module);
/**
* Get bytes of the serialized module.
*/
wasmer_byte_array wasmer_serialized_module_bytes(const wasmer_serialized_module_t *serialized_module);
/**
* Frees memory for the given serialized Module.
*/
void wasmer_serialized_module_destroy(wasmer_serialized_module_t *serialized_module);
/** /**
* Frees memory for the given Table * Frees memory for the given Table
*/ */

View File

@ -126,6 +126,10 @@ struct wasmer_limits_t {
wasmer_limit_option_t max; wasmer_limit_option_t max;
}; };
struct wasmer_serialized_module_t {
};
extern "C" { extern "C" {
/// Creates a new Module from the given wasm bytes. /// Creates a new Module from the given wasm bytes.
@ -385,13 +389,12 @@ uint32_t wasmer_memory_length(const wasmer_memory_t *memory);
/// and `wasmer_last_error_message` to get an error message. /// and `wasmer_last_error_message` to get an error message.
wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits);
/// Deserialize the given bytes into a Module. /// Deserialize the given serialized module.
/// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_OK` upon success.
/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
/// and `wasmer_last_error_message` to get an error message. /// and `wasmer_last_error_message` to get an error message.
wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module, wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module,
const uint8_t *serialized_module_bytes, const wasmer_serialized_module_t *serialized_module);
uint32_t serialized_module_bytes_len);
/// Frees memory for the given Module /// Frees memory for the given Module
void wasmer_module_destroy(wasmer_module_t *module); void wasmer_module_destroy(wasmer_module_t *module);
@ -405,17 +408,20 @@ wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module,
wasmer_import_t *imports, wasmer_import_t *imports,
int imports_len); int imports_len);
/// Frees memory for the given serialized Module.
void wasmer_module_serialization_destroy(wasmer_byte_array *serialized_module);
/// Serialize the given Module. /// Serialize the given Module.
/// The caller owns the object and should call `wasmer_memory_serialization_destroy` to free it. /// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it.
/// Returns `wasmer_result_t::WASMER_OK` upon success. /// Returns `wasmer_result_t::WASMER_OK` upon success.
/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length`
/// and `wasmer_last_error_message` to get an error message. /// and `wasmer_last_error_message` to get an error message.
wasmer_result_t wasmer_module_serialize(wasmer_byte_array **serialized_module, wasmer_result_t wasmer_module_serialize(wasmer_serialized_module_t **serialized_module,
const wasmer_module_t *module); const wasmer_module_t *module);
/// Get bytes of the serialized module.
wasmer_byte_array wasmer_serialized_module_bytes(const wasmer_serialized_module_t *serialized_module);
/// Frees memory for the given serialized Module.
void wasmer_serialized_module_destroy(wasmer_serialized_module_t *serialized_module);
/// Frees memory for the given Table /// Frees memory for the given Table
void wasmer_table_destroy(wasmer_table_t *table); void wasmer_table_destroy(wasmer_table_t *table);