From 006fedba3779a3f23dbebe6f28f441f0f07835e2 Mon Sep 17 00:00:00 2001 From: nub31 Date: Sun, 2 Feb 2025 21:18:20 +0100 Subject: [PATCH] ... --- Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs | 4 +- input/baseline/gc.asm | 97 +++++++------------ 2 files changed, 36 insertions(+), 65 deletions(-) diff --git a/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs b/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs index 91fcb2a..36965b6 100644 --- a/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs +++ b/Nub.Lang/Nub.Lang/Backend/Custom/Generator.cs @@ -42,6 +42,7 @@ public class Generator { _builder.AppendLine("global _start"); + _builder.AppendLine("extern gc_init"); _builder.AppendLine("extern gc_alloc"); _builder.AppendLine("extern str_cmp"); foreach (var externFuncDefinition in _definitions.OfType()) @@ -51,11 +52,12 @@ public class Generator _builder.AppendLine(); _builder.AppendLine("section .text"); - + // TODO: Only add start label if entrypoint is present, otherwise assume library var main = _symbolTable.ResolveLocalFunc(Entrypoint, []); _builder.AppendLine("_start:"); + _builder.AppendLine(" call gc_init"); _builder.AppendLine($" call {main.StartLabel}"); _builder.AppendLine(main.ReturnType.HasValue diff --git a/input/baseline/gc.asm b/input/baseline/gc.asm index 8b62d7b..f1c14a9 100644 --- a/input/baseline/gc.asm +++ b/input/baseline/gc.asm @@ -1,75 +1,28 @@ -global gc_init, gc_alloc, gc_free, gc_collect -extern itoa -extern str_len +global gc_init, gc_alloc section .bss alloc_list: resq 1 stack_start: resq 1 - -; TMP + total_alloc: resq 1 section .data - newline: db 10, 0 - start_mark: db "Starting to mark", 0 - marked: db "Marked object", 0 - -; /TMP + gc_threshold: dq 4096 ; default of 4096 bytes, this will scale when gc_collect is ran section .text - -; TMP - -print_int: - push rbp - mov rbp, rsp - sub rsp, 8 - mov [rbp - 8], rdi - mov rax, [rbp - 8] - push rax - pop rdi - call itoa - push rax - pop rdi - call print - mov rdi, newline - call print - mov rsp, rbp - pop rbp - ret - -print: - push rbp - mov rbp, rsp - sub rsp, 8 - mov [rbp - 8], rdi - mov rax, 1 - push rax - mov rax, 1 - push rax - mov rax, [rbp - 8] - push rax - mov rax, [rbp - 8] - push rax - pop rdi - call str_len - push rax - pop rdx - pop rsi - pop rdi - pop rax - syscall - mov rsp, rbp - pop rbp - ret - -; /TMP - gc_init: mov [stack_start], rsp ret gc_alloc: add rdi, 17 ; add space for metadata + mov rdx, [total_alloc] ; load total allocation + cmp rdx, [gc_threshold] ; has total exceeded threshold? + jb .no_collect ; no? skip + push rdi + call gc_collect + pop rdi +.no_collect: + add [total_alloc], rdi ; save total allocation push rdi call sys_mmap ; allocate size + metadata pop rdi @@ -106,6 +59,7 @@ gc_free: mov [rsi + 9], rdx ; Bypass rdi in the list .free_memory: mov rsi, [rdi + 1] ; Get object size + sub [total_alloc], rsi ; save total allocation call sys_munmap ; Free memory ret .not_found: @@ -114,6 +68,12 @@ gc_free: gc_collect: call gc_mark_stack call gc_sweep + ; next threshold will be double of used memory or 4096, whichever is higher + mov rdi, [total_alloc] + shl rdi, 1 + mov rsi, 4096 + call max + mov qword [gc_threshold], rax ret gc_mark_stack: @@ -147,7 +107,7 @@ gc_mark: jnz .done ; yes? return mov byte [rdi - 17], 1 ; mark object mov rcx, [rdi + 1] ; load object size - lea rdx, [rdi + 17] ; start of data + mov rdx, rdi ; start of data add rcx, rdx ; end of data .scan_object: cmp rdx, rcx ; done scanning? @@ -168,13 +128,13 @@ gc_sweep: test al, al ; is object marked? jz .free ; no? free it mov byte [rdi], 0 ; yes? clear mark for next scan - mov rdi, [rdi + 9] - jmp .loop + mov rdi, [rdi + 9] ; load the next object in the list + jmp .loop ; repeat .free: - mov rcx, [rdi + 9] + mov rcx, [rdi + 9] ; save address of next object in list push rcx call gc_free - pop rdi + pop rdi ; [rdi + 9] is deallocated now, and would throw a segfault unless we used the stack jmp .loop .done: ret @@ -205,4 +165,13 @@ sys_munmap: .error: mov rax, 60 mov rdi, 1 - syscall \ No newline at end of file + syscall + +max: + cmp rdi, rsi + jae .left + mov rax, rsi + ret +.left: + mov rax, rdi + ret \ No newline at end of file