ontio_bump_alloc/
lib.rs

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
18//contract execution is single thread
19unsafe 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}