#![no_std]
#[cfg(not(target_arch = "wasm32"))]
extern crate std;
#[cfg(not(target_arch = "wasm32"))]
extern crate alloc;
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub struct PageCount(pub usize);
impl PageCount {
pub fn size_in_bytes(self) -> usize {
self.0 * PAGE_SIZE
}
}
pub const PAGE_SIZE: usize = 65536;
#[cfg(target_arch = "wasm32")]
#[inline(always)]
pub unsafe fn grow_memory(pages: usize) -> usize {
core::arch::wasm32::memory_grow(0, pages)
}
#[cfg(not(target_arch = "wasm32"))]
mod host_memory {
use super::PAGE_SIZE;
use std::alloc::{Layout, alloc, dealloc};
use std::cell::RefCell;
use std::ptr;
const MOCK_MEMORY_SIZE: usize = 128 * 1024 * 1024;
struct MockMemory {
base_ptr: *mut u8,
current_pages: usize,
}
impl MockMemory {
fn new() -> Self {
unsafe {
let layout = Layout::from_size_align(MOCK_MEMORY_SIZE, PAGE_SIZE).unwrap();
let ptr = alloc(layout);
if ptr.is_null() {
panic!("Failed to allocate mock WASM memory");
}
ptr::write_bytes(ptr, 0, MOCK_MEMORY_SIZE);
Self {
base_ptr: ptr,
current_pages: 0,
}
}
}
}
impl Drop for MockMemory {
fn drop(&mut self) {
unsafe {
let layout = Layout::from_size_align(MOCK_MEMORY_SIZE, PAGE_SIZE).unwrap();
dealloc(self.base_ptr, layout);
}
}
}
std::thread_local! {
static MEMORY: RefCell<MockMemory> = RefCell::new(MockMemory::new());
}
pub unsafe fn grow_memory_impl(pages: usize) -> usize {
MEMORY.with(|mem| {
let mut mem = mem.borrow_mut();
if (mem.current_pages + pages) * PAGE_SIZE > MOCK_MEMORY_SIZE {
return usize::MAX;
}
let start_addr = mem.base_ptr as usize + mem.current_pages * PAGE_SIZE;
let ret_page_index = start_addr / PAGE_SIZE;
mem.current_pages += pages;
ret_page_index
})
}
pub unsafe fn reset_memory() {
MEMORY.with(|mem| {
let mut mem = mem.borrow_mut();
let used_bytes = mem.current_pages * PAGE_SIZE;
if used_bytes > 0 {
unsafe {
ptr::write_bytes(mem.base_ptr, 0, used_bytes);
}
}
mem.current_pages = 0;
});
}
}
#[cfg(not(target_arch = "wasm32"))]
pub unsafe fn grow_memory(pages: usize) -> usize {
unsafe { host_memory::grow_memory_impl(pages) }
}
#[cfg(not(target_arch = "wasm32"))]
pub fn reset_heap() {
unsafe {
host_memory::reset_memory();
}
}
pub mod single_threaded {
mod bump_freelist;
mod freelist;
mod segregated_bump;
pub use bump_freelist::BumpFreeListAllocator;
pub use freelist::FreeListAllocator;
pub use segregated_bump::SegregatedBumpAllocator;
}