diff --git a/lang/src/alloc.asm b/lang/src/alloc.asm index 35a327f..50f8892 100644 --- a/lang/src/alloc.asm +++ b/lang/src/alloc.asm @@ -15,6 +15,7 @@ extern allocate extern vec_init extern vec_push extern vec_get +extern vec_try_grow_with global bump_init @@ -29,14 +30,21 @@ mmap_alloc: pop rbp ret +;; define-fn: fn bump_init() bump_init: push rbp mov rbp, rsp - lea rdi, [rel free_list] - mov rsi, 16 - mov rdx, 0 - call vec_init + mov rdi, 0x1000 + call mmap_alloc + lea rdx, [rel free_list] + mov [rdx], rax + mov qword [rdx + 8], 0 ; size 0 + mov rax, 0x1000 + shr rax, 4 ; capacity in blocks of 16 bytes + mov qword [rdx + 16], rax ; capacity + mov qword [rdx + 24], 16 ; elem_size = 16 + mov qword [rdx + 32], 0 ; drop = None pop rbp ret @@ -50,6 +58,20 @@ bump_new_block: ja .mmap mov rdi, 4096 .mmap: + + push rdi + + lea rdi, [rel free_list] + mov rsi, [rdi + 8] + mov rax, rsi + shr rax, 1 + add rax, 1 + add rsi, rax + mov rdx, mmap_alloc + call vec_try_grow_with + + pop rdi + ; next power of 2 lea rax, [rdi - 1] lzcnt rax, rax @@ -75,8 +97,38 @@ bump_new_block: pop rbp ret +;; rdi: num +;; rsi: multiple +next_multiple_of: + test rsi, rsi + je .l1 + mov rax, rdi + or rax, rsi + shr rax, 32 + je .l2 + mov rax, rdi + xor edx, edx + div rsi + jmp .l3 +.l2: + mov eax, edi + xor edx, edx + div esi +.l3: + sub rsi, rdx + test rdx, rdx + cmove rsi, rdx + add rsi, rdi + mov rax, rsi + ret +.l1: + mov rax, rdi + ret + + ;; rdi: number of bytes to allocate ;; rsi: alignment +;; define-fn: fn bump_alloc(size: usize, alignment: usize) -> *mut u8 bump_alloc: push rbp mov rbp, rsp @@ -104,25 +156,21 @@ bump_alloc: ; 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 + mov rdi, rdx + mov rsi, [rsp + 8] ; alignment + call next_multiple_of + ; rax = aligned_ptr + + mov rdx, rax + add rdx, qword [rsp] ; ptr + size + ; rdx = new_end + + mov rcx, [rsp + 16] ; block_ptr + add rcx, [rsp + 24] ; block_size + + cmp rdx, rcx jle .found_space + ; else try next block inc r13 jmp .alloc_loop @@ -136,13 +184,17 @@ bump_alloc: 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] + mov r12, [rsp + 32] ; block entry ptr + mov rcx, [r12] ; block_ptr + mov [r12], rdx ; update block_ptr + + ; new_end - old_ptr + sub rdx, rcx + + mov rcx, [r12 + 8] ; block_size + sub rcx, rdx + mov [r12 + 8], rcx + add rsp, 0x28 pop r13 pop r12 diff --git a/lang/src/vec.asm b/lang/src/vec.asm index 5caa61d..ede801d 100644 --- a/lang/src/vec.asm +++ b/lang/src/vec.asm @@ -8,7 +8,7 @@ extern memswap extern oom extern panic extern eprint_str -extern allocate +extern bump_alloc global vec_init global vec_init_with @@ -26,6 +26,8 @@ global vec_insert global vec_insert_many global vec_insert_sorted global vec_binary_search_by +global vec_try_grow +global vec_try_grow_with global vec_tests @@ -57,7 +59,8 @@ vec_init: push rdi ; (*vec).data = allocate(INIT_CAPACITY); mov rdi, INIT_CAPACITY - call allocate + mov rsi, 8 + call bump_alloc pop r15 mov [r15], rax ; (*vec).len = 0; @@ -94,7 +97,8 @@ vec_init_with: mov rax, rcx mul rsi ; capacity * item_size mov rdi, rax - call allocate + mov rsi, 8 + call bump_alloc pop r15 mov [r15], rax ; (*vec).len = 0; @@ -339,6 +343,16 @@ vec_remove: ;; rsi: desired size ;; fn vec_try_grow(vec: *mut Vec, new_size: usize) -> bool vec_try_grow: + mov rdx, bump_alloc + call vec_try_grow_with + ret + +;; essentially a reserve() function +;; rdi: pointer to Vec struct +;; rsi: desired size +;; rdx: allocate function pointer +;; fn vec_try_grow(vec: *mut Vec, new_size: usize) -> bool +vec_try_grow_with: push rbp mov rbp, rsp push rbx @@ -366,7 +380,8 @@ vec_try_grow: mul qword [rdi + 24] ; new_capacity * item_size ; new_data = allocate(new_capacity); mov rdi, rax - call allocate + mov rsi, 8 + call rdx mov [rsp + 16], rax mov rdi, [rsp] ; memcpy(new_data, old_data, len * vec.item_size); diff --git a/lang/tests/shared/defs.rs b/lang/tests/shared/defs.rs index fb5b9c6..cd498d2 100644 --- a/lang/tests/shared/defs.rs +++ b/lang/tests/shared/defs.rs @@ -2,6 +2,8 @@ // Auto-generated Rust bindings from assembly source unsafe extern "C" { + pub unsafe fn bump_init(); + pub unsafe fn bump_alloc(size: usize, alignment: usize) -> *mut u8; pub unsafe fn parse_func(ast: *mut Ast) -> u64; pub unsafe fn parse_args(ast: *mut Ast) -> (*const u64, usize); pub unsafe fn parse_postfix_expr(ast: *mut Ast) -> (u64, bool); diff --git a/lang/tests/vec.rs b/lang/tests/vec.rs index 7159f07..a09011c 100644 --- a/lang/tests/vec.rs +++ b/lang/tests/vec.rs @@ -4,6 +4,9 @@ mod util; use util::{ffi::*, vec::Vec, BlobVec}; fn main() { + unsafe { + util::defs::bump_init(); + } static mut DROPS: usize = 1; fn get_drops() -> usize { unsafe { (&raw const DROPS).read() }