Document gc better
This commit is contained in:
@@ -34,46 +34,14 @@ gc_alloc:
|
||||
add rax, 17 ; skip metadata for return value
|
||||
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:
|
||||
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 rdi, [total_alloc] ; since we just swept, all the memory is in use
|
||||
shl rdi, 1 ; double the currently used memory
|
||||
mov rsi, 4096
|
||||
call max
|
||||
mov qword [gc_threshold], rax
|
||||
call max ; get the largest of total_alloc * 2 and 4096
|
||||
mov qword [gc_threshold], rax ; update threshold to new value
|
||||
ret
|
||||
|
||||
gc_mark_stack:
|
||||
@@ -121,20 +89,33 @@ gc_mark:
|
||||
|
||||
gc_sweep:
|
||||
mov rdi, [alloc_list]
|
||||
xor rsi, rsi
|
||||
.loop:
|
||||
test rdi, rdi ; reached end of list?
|
||||
jz .done ; yes? return
|
||||
mov al, [rdi]
|
||||
test al, al ; is object marked?
|
||||
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 rsi, rdi
|
||||
mov rdi, [rdi + 9] ; load the next object in the list
|
||||
jmp .loop ; repeat
|
||||
.free:
|
||||
mov rcx, [rdi + 9] ; save address of next object in list
|
||||
push rcx
|
||||
call gc_free
|
||||
pop rdi ; [rdi + 9] is deallocated now, and would throw a segfault unless we used the stack
|
||||
mov rdx, [rdi + 9] ; save address of next object in list
|
||||
test rsi, rsi
|
||||
jz .remove_head
|
||||
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
|
||||
.done:
|
||||
ret
|
||||
|
||||
Reference in New Issue
Block a user