Fix issue where heap was not marked

This commit is contained in:
nub31
2025-02-02 22:35:31 +01:00
parent 1db0aefc55
commit d318c99792
3 changed files with 42 additions and 35 deletions

View File

@@ -41,10 +41,10 @@ public class Generator
public string Generate() public string Generate()
{ {
_builder.AppendLine("global _start"); _builder.AppendLine("global _start");
_builder.AppendLine("extern gc_init"); _builder.AppendLine("extern gc_init");
_builder.AppendLine("extern gc_alloc"); _builder.AppendLine("extern gc_alloc");
_builder.AppendLine("extern str_cmp"); _builder.AppendLine("extern str_cmp");
foreach (var externFuncDefinition in _definitions.OfType<ExternFuncDefinitionNode>()) foreach (var externFuncDefinition in _definitions.OfType<ExternFuncDefinitionNode>())
{ {
_builder.AppendLine($"extern {externFuncDefinition.Name}"); _builder.AppendLine($"extern {externFuncDefinition.Name}");
@@ -143,7 +143,7 @@ public class Generator
} }
default: default:
{ {
throw new InvalidOperationException("Global variables must have the ability yo be evaluated at compile time"); throw new InvalidOperationException("Global variables must be compile time consistant");
} }
} }
} }

View File

@@ -377,10 +377,8 @@ public class Parser
case Symbol.New: case Symbol.New:
{ {
var type = ParseType(); var type = ParseType();
switch (type) switch (type)
{ {
// TODO: Parse arrays differently
case ArrayType: case ArrayType:
{ {
ExpectSymbol(Symbol.OpenParen); ExpectSymbol(Symbol.OpenParen);

View File

@@ -1,12 +1,14 @@
global gc_init, gc_alloc global gc_init, gc_alloc
section .bss section .bss
alloc_list: resq 1 alloc_list: resq 1
stack_start: resq 1 stack_start: resq 1
total_alloc: resq 1
section .data section .data
gc_threshold: dq 4096 ; default of 4096 bytes, this will scale when gc_collect is ran gc_threshold_b: dq 4096 ; default of 4096 bytes, this will scale when gc_collect is ran
gc_threshold_c: dq 1024 ; default of 1024 allocations
total_alloc_b: dq 0 ; counts the allocated bytes
total_alloc_c: dq 0 ; count the amount of allocations
section .text section .text
gc_init: gc_init:
@@ -15,14 +17,20 @@ gc_init:
gc_alloc: gc_alloc:
add rdi, 17 ; add space for metadata add rdi, 17 ; add space for metadata
mov rdx, [total_alloc] ; load total allocation mov rdx, [total_alloc_b] ; load total allocations in bytes
cmp rdx, [gc_threshold] ; has total exceeded threshold? cmp rdx, [gc_threshold_b] ; has total exceeded threshold?
jb .no_collect ; no? skip jae .collect ; yes? run gc
mov rdx, [total_alloc_c] ; load total allocation count
cmp rdx, [gc_threshold_c] ; has count exceeded threshold?
jae .collect ; yes? run gc
jmp .collect_end
.collect:
push rdi push rdi
call gc_collect call gc_collect
pop rdi pop rdi
.no_collect: .collect_end:
add [total_alloc], rdi ; save total allocation add [total_alloc_b], rdi ; update total allocated bytes
inc qword [total_alloc_c] ; update total allocation count
push rdi push rdi
call sys_mmap ; allocate size + metadata call sys_mmap ; allocate size + metadata
pop rdi pop rdi
@@ -37,11 +45,12 @@ gc_alloc:
gc_collect: gc_collect:
call gc_mark_stack call gc_mark_stack
call gc_sweep call gc_sweep
mov rdi, [total_alloc] ; since we just swept, all the memory is in use mov qword [total_alloc_c], 0 ; reset allocation count
shl rdi, 1 ; double the currently used memory mov rdi, [total_alloc_b] ; since we just swept, all the memory is in use
shl rdi, 1 ; double the currently used memory
mov rsi, 4096 mov rsi, 4096
call max ; get the largest of total_alloc * 2 and 4096 call max ; get the largest of total_alloc_b * 2 and 4096
mov qword [gc_threshold], rax ; update threshold to new value mov qword [gc_threshold_b], rax ; update threshold to new value
ret ret
gc_mark_stack: gc_mark_stack:
@@ -80,7 +89,7 @@ gc_mark:
.scan_object: .scan_object:
cmp rdx, rcx ; done scanning? cmp rdx, rcx ; done scanning?
jae .done ; yes? return jae .done ; yes? return
mov rdi, [rbx] ; load value mov rdi, [rdx] ; load value
call gc_mark call gc_mark
add rdx, 8 ; next object add rdx, 8 ; next object
jmp .scan_object jmp .scan_object
@@ -91,31 +100,31 @@ gc_sweep:
mov rdi, [alloc_list] mov rdi, [alloc_list]
xor rsi, rsi xor rsi, rsi
.loop: .loop:
test rdi, rdi ; reached end of list? test rdi, rdi ; reached end of list?
jz .done ; yes? return jz .done ; yes? return
mov al, [rdi] mov al, [rdi]
test al, al ; is object marked? test al, al ; is object marked?
jz .free ; no? free it jz .free ; no? free it
mov byte [rdi], 0 ; yes? clear mark for next marking mov byte [rdi], 0 ; yes? clear mark for next marking
mov rsi, rdi mov rsi, rdi
mov rdi, [rdi + 9] ; load the next object in the list mov rdi, [rdi + 9] ; load the next object in the list
jmp .loop ; repeat jmp .loop ; repeat
.free: .free:
mov rdx, [rdi + 9] ; save address of next object in list mov rdx, [rdi + 9] ; save address of next object in list
test rsi, rsi test rsi, rsi
jz .remove_head jz .remove_head
mov [rsi + 9], rdx ; unlink the current node by setting the previous node's next to the next node's address mov [rsi + 9], rdx ; unlink the current node by setting the previous node's next to the next node's address
jmp .free_memory jmp .free_memory
.remove_head: .remove_head:
mov [alloc_list], rdx ; update head node to be the next node mov [alloc_list], rdx ; update head node to be the next node
.free_memory: .free_memory:
push rsi ; save previous node since it will also be the previous node for the next item push rsi ; save previous node since it will also be the previous node for the next item
push rdx ; save next node push rdx ; save next node
mov rsi, [rdi + 1] ; get length of the object mov rsi, [rdi + 1] ; get length of the object
sub [total_alloc], rsi ; remove this allocation from total allocations sub [total_alloc_b], rsi ; remove this allocation from total allocations
call sys_munmap ; free the memory call sys_munmap ; free the memory
pop rdi ; input for next iteration pop rdi ; input for next iteration
pop rsi ; prev node for next iteration pop rsi ; prev node for next iteration
jmp .loop jmp .loop
.done: .done:
ret ret