1#![no_std]
2use cfg_if::cfg_if;
3use core::alloc::{GlobalAlloc, Layout};
4use core::cell::RefCell;
5use core::ptr;
6
7const PAGE_SIZE: usize = 65536;
8
9struct Inner {
10 pos: *mut u8,
11 size: usize,
12}
13
14pub struct BumpAlloc {
15 inner: RefCell<Inner>,
16}
17
18unsafe impl Sync for BumpAlloc {}
20
21impl BumpAlloc {
22 pub const fn new() -> BumpAlloc {
23 BumpAlloc { inner: RefCell::new(Inner { pos: ptr::null_mut(), size: 0 }) }
24 }
25}
26
27fn align_to(size: usize, align: usize) -> usize {
28 (size + align - 1) & !(align - 1)
29}
30
31unsafe impl GlobalAlloc for BumpAlloc {
32 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
33 let mut inner = self.inner.borrow_mut();
34
35 let need_bytes = align_to(layout.size(), layout.align());
36 let pos = align_to(inner.pos as usize, layout.align());
37 if pos + need_bytes > inner.size {
38 let need_page = (pos + need_bytes - inner.size + PAGE_SIZE - 1) / PAGE_SIZE;
39 match alloc_pages(need_page) {
40 Some(p) => {
41 if inner.pos.is_null() {
42 inner.pos = p;
43 }
44 inner.size = (p as usize) + need_page * PAGE_SIZE;
45 }
46 None => return ptr::null_mut(),
47 }
48 }
49
50 let pos = align_to(inner.pos as usize, layout.align());
51 inner.pos = (pos + need_bytes) as *mut u8;
52
53 pos as *mut u8
54 }
55
56 unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
57}
58
59cfg_if! {
60if #[cfg(target_arch = "wasm32")] {
61 mod alloc_impl {
62 use core::arch::wasm32;
63 use super::PAGE_SIZE;
64
65 pub(crate) unsafe fn alloc_pages(num_page: usize) -> Option<*mut u8> {
66 let ptr = wasm32::memory_grow(0, num_page);
67 if ptr != usize::max_value() {
68 let ptr = (ptr * PAGE_SIZE) as *mut u8;
69 Some(ptr)
70 } else {
71 None
72 }
73 }
74 }
75 use alloc_impl::alloc_pages;
76} else {
77 mod imp_noop {
78 pub(crate) unsafe fn alloc_pages(_num_page: usize) -> Option<*mut u8> {
79 None
80 }
81 }
82 use imp_noop::alloc_pages;
83}
84}