lite_alloc/
lib.rs

1#![no_std]
2
3#[cfg(not(target_arch = "wasm32"))]
4extern crate std;
5
6#[cfg(not(target_arch = "wasm32"))]
7extern crate alloc;
8
9/// WebAssembly memory page count.
10///
11/// WebAssembly 内存页数量。
12#[derive(Eq, PartialEq, Debug, Clone, Copy)]
13pub struct PageCount(pub usize);
14
15impl PageCount {
16    pub fn size_in_bytes(self) -> usize {
17        self.0 * PAGE_SIZE
18    }
19}
20
21/// WebAssembly page size, in bytes (64KB).
22///
23/// WebAssembly 页大小,单位字节(64KB)。
24pub const PAGE_SIZE: usize = 65536;
25
26// Remove MemoryGrower trait, use function directly
27// 移除 trait MemoryGrower,直接写成函数
28#[cfg(target_arch = "wasm32")]
29#[inline(always)]
30pub unsafe fn grow_memory(pages: usize) -> usize {
31    core::arch::wasm32::memory_grow(0, pages)
32}
33
34#[cfg(not(target_arch = "wasm32"))]
35mod host_memory {
36    use super::PAGE_SIZE;
37    use std::alloc::{Layout, alloc, dealloc};
38    use std::cell::RefCell;
39    use std::ptr;
40
41    // Simulate 128MB of addressable WASM memory space per thread
42    // 模拟每线程 128MB 的可寻址 WASM 内存空间
43    const MOCK_MEMORY_SIZE: usize = 128 * 1024 * 1024;
44
45    struct MockMemory {
46        base_ptr: *mut u8,
47        current_pages: usize,
48    }
49
50    impl MockMemory {
51        fn new() -> Self {
52            unsafe {
53                let layout = Layout::from_size_align(MOCK_MEMORY_SIZE, PAGE_SIZE).unwrap();
54                let ptr = alloc(layout);
55                if ptr.is_null() {
56                    // Panic immediately if we can't allocate the mock heap
57                    // 如果无法分配模拟堆,立即 Panic
58                    panic!("Failed to allocate mock WASM memory");
59                }
60                // Initialize memory to zero, similar to WASM behavior
61                // 将内存初始化为零,类似于 WASM 行为
62                ptr::write_bytes(ptr, 0, MOCK_MEMORY_SIZE);
63                Self {
64                    base_ptr: ptr,
65                    current_pages: 0,
66                }
67            }
68        }
69    }
70
71    impl Drop for MockMemory {
72        fn drop(&mut self) {
73            unsafe {
74                let layout = Layout::from_size_align(MOCK_MEMORY_SIZE, PAGE_SIZE).unwrap();
75                dealloc(self.base_ptr, layout);
76            }
77        }
78    }
79
80    // Thread local storage for the mock memory
81    // 模拟内存的线程局部存储
82    std::thread_local! {
83        static MEMORY: RefCell<MockMemory> = RefCell::new(MockMemory::new());
84    }
85
86    pub unsafe fn grow_memory_impl(pages: usize) -> usize {
87        MEMORY.with(|mem| {
88            let mut mem = mem.borrow_mut();
89
90            // Check if we have enough space in our pre-allocated buffer
91            // 检查预分配缓冲区中是否有足够的空间
92            if (mem.current_pages + pages) * PAGE_SIZE > MOCK_MEMORY_SIZE {
93                return usize::MAX;
94            }
95
96            // Calculate the start of the new memory block as an absolute address
97            // 计算新内存块的起始绝对地址
98            let start_addr = mem.base_ptr as usize + mem.current_pages * PAGE_SIZE;
99
100            // Since our allocators expect the return value to be (Address / PAGE_SIZE),
101            // and they will reconstruct the address by (RetVal * PAGE_SIZE),
102            // we must return the absolute page index.
103            // 由于我们的分配器期望返回值为 (Address / PAGE_SIZE),
104            // 并且它们将通过 (RetVal * PAGE_SIZE) 重建地址,
105            // 我们必须返回绝对页索引。
106            let ret_page_index = start_addr / PAGE_SIZE;
107
108            // Advance the usage counter
109            // 增加使用计数
110            mem.current_pages += pages;
111
112            // Zero out the newly allocated pages (emulate WASM grow behavior)
113            // Note: We zeroed the whole block on init, but reset_memory might not zero everything
114            // if we optimize it. Let's ensure it's zeroed here if we change reset policy.
115            // For now, init zeros everything and reset zeros used, so it's fine.
116            // 将新分配的页面清零(模拟 WASM 增长行为)
117            // 注意:我们在初始化时将整个块清零,但如果进行优化,reset_memory 可能不会清零所有内容。
118            // 如果我们要更改重置策略,请确保在此处清零。
119            // 目前,初始化会清零所有内容,重置会清零已使用的内容,所以没问题。
120
121            ret_page_index
122        })
123    }
124
125    pub unsafe fn reset_memory() {
126        MEMORY.with(|mem| {
127            let mut mem = mem.borrow_mut();
128            // Zero out the used memory so the next test starts clean
129            // 将已使用的内存清零,以便下一个测试从干净的状态开始
130            let used_bytes = mem.current_pages * PAGE_SIZE;
131            if used_bytes > 0 {
132                unsafe {
133                    ptr::write_bytes(mem.base_ptr, 0, used_bytes);
134                }
135            }
136            mem.current_pages = 0;
137        });
138    }
139}
140
141#[cfg(not(target_arch = "wasm32"))]
142pub unsafe fn grow_memory(pages: usize) -> usize {
143    unsafe { host_memory::grow_memory_impl(pages) }
144}
145
146/// For Test/Bench only: Reset the mock heap memory of the current thread
147///
148/// 仅用于测试/Bench:重置当前线程的模拟堆内存
149#[cfg(not(target_arch = "wasm32"))]
150pub fn reset_heap() {
151    unsafe {
152        host_memory::reset_memory();
153    }
154}
155
156pub mod single_threaded {
157    mod bump_freelist;
158    mod freelist;
159    mod segregated_bump;
160
161    pub use bump_freelist::BumpFreeListAllocator;
162    pub use freelist::FreeListAllocator;
163    pub use segregated_bump::SegregatedBumpAllocator;
164}