Document gc better
This commit is contained in:
@@ -6,7 +6,7 @@ section .bss
|
|||||||
total_alloc: 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: dq 4096 ; default of 4096 bytes, this will scale when gc_collect is ran
|
||||||
|
|
||||||
section .text
|
section .text
|
||||||
gc_init:
|
gc_init:
|
||||||
@@ -34,46 +34,14 @@ gc_alloc:
|
|||||||
add rax, 17 ; skip metadata for return value
|
add rax, 17 ; skip metadata for return value
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Generated by chatgpt. Rewrite this later
|
|
||||||
; TODO: refactor to unlink easier
|
|
||||||
gc_free:
|
|
||||||
mov rsi, [alloc_list] ; Load head of allocation list
|
|
||||||
test rsi, rsi ; Check if list is empty
|
|
||||||
jz .not_found ; If empty, nothing to free
|
|
||||||
cmp rsi, rdi ; Is the first item the one to free?
|
|
||||||
je .remove_head ; If so, update head directly
|
|
||||||
.loop:
|
|
||||||
mov rdx, [rsi + 9] ; Load next item in list
|
|
||||||
test rdx, rdx ; Check if end of list
|
|
||||||
jz .not_found ; If not found, return
|
|
||||||
cmp rdx, rdi ; Is this the item to remove?
|
|
||||||
je .remove_item ; If so, unlink it
|
|
||||||
mov rsi, rdx ; Move to next item
|
|
||||||
jmp .loop ; Repeat
|
|
||||||
.remove_head:
|
|
||||||
mov rdx, [rdi + 9] ; Get next item
|
|
||||||
mov [alloc_list], rdx ; Update head of list
|
|
||||||
jmp .free_memory ; Free the object
|
|
||||||
.remove_item:
|
|
||||||
mov rdx, [rdi + 9] ; Get next item
|
|
||||||
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:
|
|
||||||
ret ; Item not found, do nothing
|
|
||||||
|
|
||||||
gc_collect:
|
gc_collect:
|
||||||
call gc_mark_stack
|
call gc_mark_stack
|
||||||
call gc_sweep
|
call gc_sweep
|
||||||
; next threshold will be double of used memory or 4096, whichever is higher
|
mov rdi, [total_alloc] ; since we just swept, all the memory is in use
|
||||||
mov rdi, [total_alloc]
|
shl rdi, 1 ; double the currently used memory
|
||||||
shl rdi, 1
|
|
||||||
mov rsi, 4096
|
mov rsi, 4096
|
||||||
call max
|
call max ; get the largest of total_alloc * 2 and 4096
|
||||||
mov qword [gc_threshold], rax
|
mov qword [gc_threshold], rax ; update threshold to new value
|
||||||
ret
|
ret
|
||||||
|
|
||||||
gc_mark_stack:
|
gc_mark_stack:
|
||||||
@@ -121,20 +89,33 @@ gc_mark:
|
|||||||
|
|
||||||
gc_sweep:
|
gc_sweep:
|
||||||
mov rdi, [alloc_list]
|
mov rdi, [alloc_list]
|
||||||
|
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 scan
|
mov byte [rdi], 0 ; yes? clear mark for next marking
|
||||||
mov rdi, [rdi + 9] ; load the next object in the list
|
mov rsi, rdi
|
||||||
jmp .loop ; repeat
|
mov rdi, [rdi + 9] ; load the next object in the list
|
||||||
|
jmp .loop ; repeat
|
||||||
.free:
|
.free:
|
||||||
mov rcx, [rdi + 9] ; save address of next object in list
|
mov rdx, [rdi + 9] ; save address of next object in list
|
||||||
push rcx
|
test rsi, rsi
|
||||||
call gc_free
|
jz .remove_head
|
||||||
pop rdi ; [rdi + 9] is deallocated now, and would throw a segfault unless we used the stack
|
mov [rsi + 9], rdx ; unlink the current node by setting the previous node's next to the next node's address
|
||||||
|
jmp .free_memory
|
||||||
|
.remove_head:
|
||||||
|
mov [alloc_list], rdx ; update head node to be the next node
|
||||||
|
.free_memory
|
||||||
|
push rsi ; save previous node since it will also be the previous node for the next item
|
||||||
|
push rdx ; save next node
|
||||||
|
mov rsi, [rdi + 1] ; get length of the object
|
||||||
|
sub [total_alloc], rsi ; remove this allocation from total allocations
|
||||||
|
call sys_munmap ; free the memory
|
||||||
|
pop rdi ; input for next iteration
|
||||||
|
pop rsi ; prev node for next iteration
|
||||||
jmp .loop
|
jmp .loop
|
||||||
.done:
|
.done:
|
||||||
ret
|
ret
|
||||||
|
|||||||
Reference in New Issue
Block a user