-
Notifications
You must be signed in to change notification settings - Fork 824
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
481: Added context trampoline into runtime r=losfair a=syrusakbary Based on #450 Co-authored-by: losfair <[email protected]>
- Loading branch information
Showing
8 changed files
with
587 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
//! Trampoline emitter for transforming function calls. | ||
use std::ffi::c_void; | ||
use std::mem; | ||
use wasmer_runtime_core::trampoline::*; | ||
|
||
#[repr(C)] | ||
pub struct wasmer_trampoline_buffer_builder_t; | ||
|
||
#[repr(C)] | ||
pub struct wasmer_trampoline_buffer_t; | ||
|
||
#[repr(C)] | ||
pub struct wasmer_trampoline_callable_t; | ||
|
||
/// Creates a new trampoline builder. | ||
#[no_mangle] | ||
#[allow(clippy::cast_ptr_alignment)] | ||
pub extern "C" fn wasmer_trampoline_buffer_builder_new() -> *mut wasmer_trampoline_buffer_builder_t | ||
{ | ||
Box::into_raw(Box::new(TrampolineBufferBuilder::new())) as *mut _ | ||
} | ||
|
||
/// Adds a context trampoline to the builder. | ||
#[no_mangle] | ||
#[allow(clippy::cast_ptr_alignment)] | ||
pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_add_context_trampoline( | ||
builder: *mut wasmer_trampoline_buffer_builder_t, | ||
func: *const wasmer_trampoline_callable_t, | ||
ctx: *const c_void, | ||
) -> usize { | ||
let builder = &mut *(builder as *mut TrampolineBufferBuilder); | ||
builder.add_context_trampoline(func as *const CallTarget, ctx as *const CallContext) | ||
} | ||
|
||
/// Adds a callinfo trampoline to the builder. | ||
#[no_mangle] | ||
#[allow(clippy::cast_ptr_alignment)] | ||
pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_add_callinfo_trampoline( | ||
builder: *mut wasmer_trampoline_buffer_builder_t, | ||
func: *const wasmer_trampoline_callable_t, | ||
ctx: *const c_void, | ||
num_params: u32, | ||
) -> usize { | ||
let builder = &mut *(builder as *mut TrampolineBufferBuilder); | ||
builder.add_callinfo_trampoline(mem::transmute(func), ctx as *const CallContext, num_params) | ||
} | ||
|
||
/// Finalizes the trampoline builder into an executable buffer. | ||
#[no_mangle] | ||
#[allow(clippy::cast_ptr_alignment)] | ||
pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_build( | ||
builder: *mut wasmer_trampoline_buffer_builder_t, | ||
) -> *mut wasmer_trampoline_buffer_t { | ||
let builder = Box::from_raw(builder as *mut TrampolineBufferBuilder); | ||
Box::into_raw(Box::new(builder.build())) as *mut _ | ||
} | ||
|
||
/// Destroys the trampoline buffer if not null. | ||
#[no_mangle] | ||
#[allow(clippy::cast_ptr_alignment)] | ||
pub unsafe extern "C" fn wasmer_trampoline_buffer_destroy(buffer: *mut wasmer_trampoline_buffer_t) { | ||
if !buffer.is_null() { | ||
Box::from_raw(buffer); | ||
} | ||
} | ||
|
||
/// Returns the callable pointer for the trampoline with index `idx`. | ||
#[no_mangle] | ||
#[allow(clippy::cast_ptr_alignment)] | ||
pub unsafe extern "C" fn wasmer_trampoline_buffer_get_trampoline( | ||
buffer: *const wasmer_trampoline_buffer_t, | ||
idx: usize, | ||
) -> *const wasmer_trampoline_callable_t { | ||
let buffer = &*(buffer as *const TrampolineBuffer); | ||
buffer.get_trampoline(idx) as _ | ||
} | ||
|
||
/// Returns the context added by `add_context_trampoline`, from within the callee function. | ||
#[no_mangle] | ||
#[allow(clippy::cast_ptr_alignment)] | ||
pub unsafe extern "C" fn wasmer_trampoline_get_context() -> *mut c_void { | ||
get_context() as *const c_void as *mut c_void | ||
} |
132 changes: 132 additions & 0 deletions
132
lib/runtime-c-api/tests/test-import-function-callinfo.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
#include <stdio.h> | ||
#include "../wasmer.h" | ||
#include <assert.h> | ||
#include <stdint.h> | ||
#include <string.h> | ||
|
||
static bool print_str_called = false; | ||
static int memory_len = 0; | ||
static int ptr_len = 0; | ||
static char actual_str[14] = {}; | ||
static int actual_context_data_value = 0; | ||
|
||
typedef struct { | ||
int value; | ||
} context_data; | ||
|
||
struct print_str_context { | ||
int call_count; | ||
}; | ||
|
||
void print_str(struct print_str_context *local_context, uint64_t *args) | ||
{ | ||
local_context->call_count++; | ||
|
||
wasmer_instance_context_t *ctx = (void *) args[0]; | ||
int32_t ptr = args[1]; | ||
int32_t len = args[2]; | ||
|
||
const wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0); | ||
uint32_t mem_len = wasmer_memory_length(memory); | ||
uint8_t *mem_bytes = wasmer_memory_data(memory); | ||
for (int32_t idx = 0; idx < len; idx++) | ||
{ | ||
actual_str[idx] = mem_bytes[ptr + idx]; | ||
} | ||
actual_str[13] = '\0'; | ||
printf("In print_str, memory len: %d, ptr_len: %d\n, str %s", mem_len, len, actual_str); | ||
print_str_called = true; | ||
memory_len = mem_len; | ||
ptr_len = len; | ||
|
||
actual_context_data_value = ((context_data *) wasmer_instance_context_data_get(ctx))->value; | ||
} | ||
|
||
int main() | ||
{ | ||
wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32}; | ||
wasmer_value_tag returns_sig[] = {}; | ||
struct print_str_context local_context = { | ||
.call_count = 0 | ||
}; | ||
|
||
printf("Creating trampoline buffer\n"); | ||
wasmer_trampoline_buffer_builder_t *tbb = wasmer_trampoline_buffer_builder_new(); | ||
unsigned long print_str_idx = wasmer_trampoline_buffer_builder_add_callinfo_trampoline( | ||
tbb, | ||
(wasmer_trampoline_callable_t *) print_str, | ||
(void *) &local_context, | ||
3 | ||
); | ||
wasmer_trampoline_buffer_t *tb = wasmer_trampoline_buffer_builder_build(tbb); | ||
const wasmer_trampoline_callable_t *print_str_callable = wasmer_trampoline_buffer_get_trampoline(tb, print_str_idx); | ||
|
||
printf("Creating new func\n"); | ||
wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str_callable, params_sig, 2, returns_sig, 0); | ||
wasmer_import_t import; | ||
|
||
char *module_name = "env"; | ||
wasmer_byte_array module_name_bytes; | ||
module_name_bytes.bytes = (const uint8_t *) module_name; | ||
module_name_bytes.bytes_len = strlen(module_name); | ||
char *import_name = "print_str"; | ||
wasmer_byte_array import_name_bytes; | ||
import_name_bytes.bytes = (const uint8_t *) import_name; | ||
import_name_bytes.bytes_len = strlen(import_name); | ||
|
||
import.module_name = module_name_bytes; | ||
import.import_name = import_name_bytes; | ||
import.tag = WASM_FUNCTION; | ||
import.value.func = func; | ||
wasmer_import_t imports[] = {import}; | ||
|
||
// Read the wasm file bytes | ||
FILE *file = fopen("assets/wasm_sample_app.wasm", "r"); | ||
fseek(file, 0, SEEK_END); | ||
long len = ftell(file); | ||
uint8_t *bytes = malloc(len); | ||
fseek(file, 0, SEEK_SET); | ||
fread(bytes, 1, len, file); | ||
fclose(file); | ||
|
||
printf("Instantiating\n"); | ||
wasmer_instance_t *instance = NULL; | ||
wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 1); | ||
printf("Compile result: %d\n", compile_result); | ||
|
||
assert(compile_result == WASMER_OK); | ||
|
||
context_data* context_data = malloc(sizeof(context_data)); | ||
int context_data_value = 42; | ||
context_data->value = context_data_value; | ||
wasmer_instance_context_data_set(instance, context_data); | ||
|
||
wasmer_value_t params[] = {}; | ||
wasmer_value_t results[] = {}; | ||
wasmer_result_t call_result = wasmer_instance_call(instance, "hello_wasm", params, 0, results, 0); | ||
printf("Call result: %d\n", call_result); | ||
|
||
int error_len = wasmer_last_error_length(); | ||
printf("Error len: `%d`\n", error_len); | ||
char *error_str = malloc(error_len); | ||
wasmer_last_error_message(error_str, error_len); | ||
printf("Error str: `%s`\n", error_str); | ||
|
||
assert(call_result == WASMER_OK); | ||
|
||
assert(print_str_called); | ||
assert(memory_len == 17); | ||
assert(ptr_len == 13); | ||
assert(0 == strcmp(actual_str, "Hello, World!")); | ||
assert(context_data_value == actual_context_data_value); | ||
assert(local_context.call_count == 1); | ||
|
||
printf("Destroying trampoline buffer\n"); | ||
wasmer_trampoline_buffer_destroy(tb); | ||
printf("Destroying func\n"); | ||
wasmer_import_func_destroy(func); | ||
printf("Destroy instance\n"); | ||
wasmer_instance_destroy(instance); | ||
free(context_data); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.