bump allocator
This commit is contained in:
parent
5f63d4303e
commit
6a6af53667
|
|
@ -1,7 +1,7 @@
|
|||
# Makefile: Compile and link main.asm using nasm and mold, intermediate files in target/
|
||||
|
||||
TARGET_DIR := target
|
||||
SRC := src/lib.asm src/int_to_str.asm src/vec.asm src/tokeniser.asm src/file.asm
|
||||
SRC := src/lib.asm src/int_to_str.asm src/vec.asm src/tokeniser.asm src/file.asm src/alloc.asm
|
||||
OBJ := $(patsubst src/%.asm,$(TARGET_DIR)/%.o,$(SRC))
|
||||
|
||||
BIN_SRC := src/main.asm src/panic.asm
|
||||
|
|
|
|||
153
lang/src/alloc.asm
Normal file
153
lang/src/alloc.asm
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
default rel
|
||||
|
||||
section .bss
|
||||
align 8
|
||||
free_list: resb 40
|
||||
|
||||
section .text
|
||||
extern memcpy
|
||||
extern memswap
|
||||
extern oom
|
||||
extern panic
|
||||
extern eprint_error
|
||||
extern allocate
|
||||
|
||||
extern vec_init
|
||||
extern vec_push
|
||||
extern vec_get
|
||||
|
||||
|
||||
global bump_init
|
||||
global bump_alloc
|
||||
|
||||
;; rdi: number of bytes to allocate
|
||||
;; fn mmap(length: usize) -> *mut u8 {
|
||||
mmap_alloc:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
call allocate
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
bump_init:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
lea rdi, [rel free_list]
|
||||
mov rsi, 16
|
||||
mov rdx, 0
|
||||
call vec_init
|
||||
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
;; rdi: min_size
|
||||
bump_new_block:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
cmp rdi, 4096
|
||||
ja .mmap
|
||||
mov rdi, 4096
|
||||
.mmap:
|
||||
; next power of 2
|
||||
lea rax, [rdi - 1]
|
||||
lzcnt rax, rax
|
||||
mov rdx, -1
|
||||
shrx rdx, rdx, rax
|
||||
inc rdx
|
||||
mov rdi, rdx
|
||||
push rdi
|
||||
call mmap_alloc
|
||||
pop rdi
|
||||
|
||||
; Add to free list
|
||||
sub rsp, 0x10
|
||||
mov [rsp], rax
|
||||
mov [rsp + 8], rdi
|
||||
|
||||
lea rdi, [rel free_list]
|
||||
mov rsi, rsp
|
||||
mov rdx, 0x10
|
||||
call vec_push
|
||||
|
||||
add rsp, 0x10
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
;; rdi: number of bytes to allocate
|
||||
;; rsi: alignment
|
||||
bump_alloc:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
push r12
|
||||
push r13
|
||||
sub rsp, 0x28
|
||||
mov [rsp], rdi ; size
|
||||
mov [rsp + 8], rsi ; alignment
|
||||
|
||||
lea rdi, [rel free_list]
|
||||
mov r12, [rdi + 8]
|
||||
xor r13, r13
|
||||
.alloc_loop:
|
||||
cmp r13, r12
|
||||
jae .no_block
|
||||
|
||||
lea rdi, [rel free_list]
|
||||
mov rsi, r13
|
||||
call vec_get
|
||||
mov [rsp + 32], rax ; block entry ptr
|
||||
mov rdx, [rax]
|
||||
mov [rsp + 16], rdx ; block_ptr
|
||||
mov rax, [rax + 8] ; block_size
|
||||
mov [rsp + 24], rax
|
||||
|
||||
; check for space
|
||||
; block_ptr.next_multiple_of(alignment) + size <= block_ptr + block_size
|
||||
mov rcx, [rsp + 8] ; alignment
|
||||
; let ptr = block_ptr | alignment
|
||||
or rax, rcx ; align up
|
||||
xor rdx, rdx ; clear high qword
|
||||
; let rem = ptr % alignment
|
||||
div rcx
|
||||
; let diff = alignment - rem
|
||||
sub rcx, rdx
|
||||
mov rax, [rsp + 16] ; block+ptr
|
||||
; let aligned_ptr = block_ptr + diff
|
||||
add rax, rcx
|
||||
; let aligned_end = aligned_ptr + size
|
||||
add rax, [rsp] ; size
|
||||
; let block_end = block_ptr + block_size
|
||||
mov rdx, [rsp + 16] ; block_ptr
|
||||
add rdx, [rsp + 24] ; block_ptr + block_size
|
||||
; if aligned_end <= block_end
|
||||
cmp rax, rdx
|
||||
jle .found_space
|
||||
; else try next block
|
||||
inc r13
|
||||
jmp .alloc_loop
|
||||
.no_block:
|
||||
; allocate new block
|
||||
mov rdi, [rsp] ; size
|
||||
call bump_new_block
|
||||
lea r13, [rel free_list]
|
||||
mov r13, [r13 + 8] ; new block index
|
||||
mov r12, r13
|
||||
dec r13
|
||||
jmp .alloc_loop
|
||||
.found_space:
|
||||
sub rdx, rax ; remaining size in block
|
||||
mov r13, [rsp + 32] ; block entry ptr
|
||||
mov [r13], rax
|
||||
mov rax, [rsp + 24] ; block_size
|
||||
sub rax, rdx
|
||||
mov [r13 + 8], rax
|
||||
mov rax, [r13]
|
||||
add rsp, 0x28
|
||||
pop r13
|
||||
pop r12
|
||||
pop rbp
|
||||
ret
|
||||
|
||||
|
||||
|
||||
69
lang/tests/bump.rs
Normal file
69
lang/tests/bump.rs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#![feature(allocator_api, box_as_ptr)]
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn panic() -> ! {
|
||||
panic!("Called panic from external code.");
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
unsafe fn bump_init();
|
||||
unsafe fn bump_alloc(size: usize, align: usize) -> *mut u8;
|
||||
}
|
||||
|
||||
struct BumpAllocator;
|
||||
|
||||
unsafe impl std::alloc::Allocator for BumpAllocator {
|
||||
fn allocate(
|
||||
&self,
|
||||
layout: std::alloc::Layout,
|
||||
) -> Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError> {
|
||||
unsafe {
|
||||
let ptr = bump_alloc(layout.size(), layout.align());
|
||||
if ptr.is_null() {
|
||||
Err(std::alloc::AllocError)
|
||||
} else {
|
||||
Ok(std::ptr::NonNull::slice_from_raw_parts(
|
||||
std::ptr::NonNull::new_unchecked(ptr),
|
||||
layout.size(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn deallocate(&self, _ptr: std::ptr::NonNull<u8>, _layout: std::alloc::Layout) {
|
||||
// Bump allocator does not deallocate individual allocations
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
bump_init();
|
||||
}
|
||||
|
||||
let a = Box::new_in(42u32, BumpAllocator);
|
||||
let b = Box::new_in(42u32, BumpAllocator);
|
||||
let c = Box::new_in(52u32, BumpAllocator);
|
||||
eprintln!("a: {a}, b: {b}, c: {c}");
|
||||
assert_ne!(Box::as_ptr(&a), Box::as_ptr(&b));
|
||||
assert_eq!(*a, *b);
|
||||
|
||||
struct BigType {
|
||||
data: [u8; 0x1010],
|
||||
}
|
||||
|
||||
let mut big = Box::new_in(BigType { data: [0; 0x1010] }, BumpAllocator);
|
||||
assert_ne!(Box::as_ptr(&big) as *const (), Box::as_ptr(&a) as *const ());
|
||||
big.data[47] = 123;
|
||||
assert_eq!(big.data[47], 123);
|
||||
|
||||
#[repr(align(256))]
|
||||
struct AlignedType {
|
||||
data: [u8; 512],
|
||||
}
|
||||
let aligned = Box::new_in(AlignedType { data: [0; 512] }, BumpAllocator);
|
||||
assert_eq!(
|
||||
(Box::as_ptr(&aligned) as usize) % 256,
|
||||
0,
|
||||
"Aligned allocation should be aligned to 256 bytes"
|
||||
);
|
||||
}
|
||||
|
|
@ -215,13 +215,13 @@ fn main() {
|
|||
|
||||
assert_eq!(
|
||||
&collect_tokens()[..],
|
||||
&[[
|
||||
&[
|
||||
Lexeme(32, "\"this is a string\""),
|
||||
Lexeme(32, "\"another\nstring\nspanning multiple\n lines\""),
|
||||
Lexeme(32, "\"string with a \\\"quoted\\\" word\""),
|
||||
Lexeme(32, "\"a\""),
|
||||
Lexeme(32, "\"\"")
|
||||
],]
|
||||
],
|
||||
);
|
||||
|
||||
eprintln!("Finished tokenising.");
|
||||
|
|
|
|||
Loading…
Reference in a new issue