orca/src/runtime_memory.c

152 lines
4.2 KiB
C

/*************************************************************************
*
* Orca
* Copyright 2023 Martin Fouilleul and the Orca project contributors
* See LICENSE.txt for licensing information
*
**************************************************************************/
#include "runtime.h"
#include "runtime_memory.h"
void* oc_wasm_memory_resize_callback(void* p, unsigned long size, void* userData)
{
oc_wasm_memory* memory = (oc_wasm_memory*)userData;
if(memory->committed >= size)
{
return (memory->ptr);
}
else if(memory->committed < memory->reserved)
{
u32 commitSize = size - memory->committed;
oc_base_allocator* allocator = oc_base_allocator_default();
oc_base_commit(allocator, memory->ptr + memory->committed, commitSize);
memory->committed += commitSize;
return (memory->ptr);
}
else
{
OC_ABORT("Out of memory");
return (0);
}
}
void oc_wasm_memory_free_callback(void* p, void* userData)
{
oc_wasm_memory* memory = (oc_wasm_memory*)userData;
oc_base_allocator* allocator = oc_base_allocator_default();
oc_base_release(allocator, memory->ptr, memory->reserved);
memset(memory, 0, sizeof(oc_wasm_memory));
}
extern u32 oc_mem_grow(u64 size)
{
oc_wasm_env* env = oc_runtime_get_env();
oc_wasm_memory* memory = &env->wasmMemory;
size = oc_align_up_pow2(size, d_m3MemPageSize);
u64 totalSize = size + m3_GetMemorySize(env->m3Runtime);
u32 addr = memory->committed;
//NOTE: call resize memory, which will call our custom resize callback... this is a bit involved because
// wasm3 doesn't allow resizing the memory directly
M3Result res = ResizeMemory(env->m3Runtime, totalSize / d_m3MemPageSize);
return (addr);
}
void* oc_wasm_address_to_ptr(oc_wasm_addr addr, oc_wasm_size size)
{
oc_str8 mem = oc_runtime_get_wasm_memory();
OC_ASSERT(addr + size < mem.len, "Object overflows wasm memory");
void* ptr = (addr == 0) ? 0 : mem.ptr + addr;
return (ptr);
}
oc_wasm_addr oc_wasm_address_from_ptr(void* ptr, oc_wasm_size size)
{
oc_wasm_addr addr = 0;
if(ptr != 0)
{
oc_str8 mem = oc_runtime_get_wasm_memory();
OC_ASSERT((char*)ptr > mem.ptr && (((char*)ptr - mem.ptr) + size < mem.len), "Object overflows wasm memory");
addr = (char*)ptr - mem.ptr;
}
return (addr);
}
//------------------------------------------------------------------------------------
// oc_wasm_list helpers
//------------------------------------------------------------------------------------
void oc_wasm_list_push(oc_wasm_list* list, oc_wasm_list_elt* elt)
{
elt->next = list->first;
elt->prev = 0;
oc_wasm_addr eltAddr = oc_wasm_address_from_ptr(elt, sizeof(oc_wasm_list_elt));
if(list->first)
{
oc_wasm_list_elt* first = oc_wasm_address_to_ptr(list->first, sizeof(oc_wasm_list_elt));
first->prev = eltAddr;
}
else
{
list->last = eltAddr;
}
list->first = eltAddr;
}
void oc_wasm_list_push_back(oc_wasm_list* list, oc_wasm_list_elt* elt)
{
elt->prev = list->last;
elt->next = 0;
oc_wasm_addr eltAddr = oc_wasm_address_from_ptr(elt, sizeof(oc_wasm_list_elt));
if(list->last)
{
oc_wasm_list_elt* last = oc_wasm_address_to_ptr(list->last, sizeof(oc_wasm_list_elt));
last->next = eltAddr;
}
else
{
list->first = eltAddr;
}
list->last = eltAddr;
}
//------------------------------------------------------------------------------------
// Wasm arenas helpers
//------------------------------------------------------------------------------------
oc_wasm_addr oc_wasm_arena_push(oc_wasm_addr arena, u64 size)
{
oc_wasm_env* env = oc_runtime_get_env();
oc_wasm_addr retValues[1] = { 0 };
const void* retPointers[1] = { (void*)&retValues[0] };
const void* args[2] = { &arena, &size };
M3Result res = m3_Call(env->exports[OC_EXPORT_ARENA_PUSH], 2, args);
if(res)
{
ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error");
}
res = m3_GetResults(env->exports[OC_EXPORT_ARENA_PUSH], 1, retPointers);
if(res)
{
ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error");
}
return (retValues[0]);
}