...
This commit is contained in:
@@ -1,13 +1,19 @@
|
||||
global gc_init, gc_alloc
|
||||
extern alloc, free
|
||||
extern alloc, free, printint, printstr, endl
|
||||
|
||||
section .bss
|
||||
alloc_list: resq 1 ; head of alloc list
|
||||
stack_start: resq 1 ; start of stack
|
||||
alloc_list_head: resq 1
|
||||
free_list_head: resq 1
|
||||
stack_start: resq 1
|
||||
|
||||
section .data
|
||||
gc_threshold_c: dq 1024 ; default of 1024 allocations
|
||||
total_alloc_c: dq 0 ; count the amount of allocations
|
||||
gc_bytes_allocated: dq 0 ; bytes allocated since the last gc cycle
|
||||
gc_trigger_threshold: dq 1024 * 1024 * 8 ; initial gc trigger threshold in bytes (adjusts dynamically)
|
||||
gc_start_text: db "Running gc after ", 0
|
||||
gc_sweep_done_text: db " Sweep done. We no have ", 0
|
||||
gc_next_threshold: db " The next threshold is ", 0
|
||||
gc_allocated_bytes: db " allocated bytes", 0
|
||||
gc_mark_done_text: db " Marking done", 0
|
||||
|
||||
section .text
|
||||
gc_init:
|
||||
@@ -15,30 +21,65 @@ gc_init:
|
||||
ret
|
||||
|
||||
gc_alloc:
|
||||
add rdi, 24 ; add space for metadata
|
||||
mov rdx, [total_alloc_c] ; load total allocation count
|
||||
cmp rdx, [gc_threshold_c] ; has count exceeded threshold?
|
||||
jb .skip_collect ; yes? run gc
|
||||
add rdi, 24
|
||||
mov rdx, [gc_bytes_allocated]
|
||||
cmp rdx, [gc_trigger_threshold]
|
||||
jb .skip_collect ; if allocated bytes since last collect has exceeded threshold, trigger collect
|
||||
push rdi
|
||||
call gc_collect
|
||||
pop rdi
|
||||
.skip_collect:
|
||||
inc qword [total_alloc_c] ; update total allocation count
|
||||
add [gc_bytes_allocated], rdi
|
||||
push rdi
|
||||
call alloc ; allocate size + metadata
|
||||
call alloc ; allocate size + metadata
|
||||
pop rdi
|
||||
mov byte [rax], 0 ; set mark to 0
|
||||
mov qword [rax + 8], rdi ; set total size of object (including metadata)
|
||||
mov rsi, [alloc_list] ; load first item in allocation list
|
||||
mov qword [rax + 16], rsi ; make current head of allocation list the next item in this object
|
||||
mov [alloc_list], rax ; update head of allocation list so it points to this object
|
||||
add rax, 24 ; skip metadata for return value
|
||||
mov byte [rax], 0 ; set mark to 0
|
||||
mov qword [rax + 8], rdi ; set total size of object (including metadata)
|
||||
mov rsi, [alloc_list_head] ; load first item in allocation list
|
||||
mov qword [rax + 16], rsi ; make current head of allocation list the next item in this object
|
||||
mov [alloc_list_head], rax ; update head of allocation list so it points to this object
|
||||
add rax, 24 ; skip metadata for return value
|
||||
ret
|
||||
|
||||
gc_collect:
|
||||
mov rdi, gc_start_text
|
||||
call printstr
|
||||
mov rdi, [gc_bytes_allocated]
|
||||
call printint
|
||||
mov rdi, gc_allocated_bytes
|
||||
call printstr
|
||||
call endl
|
||||
|
||||
call gc_mark_stack
|
||||
|
||||
mov rdi, gc_mark_done_text
|
||||
call printstr
|
||||
call endl
|
||||
|
||||
call gc_sweep
|
||||
mov qword [total_alloc_c], 0 ; reset allocation count
|
||||
|
||||
mov rdi, gc_sweep_done_text
|
||||
call printstr
|
||||
mov rdi, [gc_bytes_allocated]
|
||||
call printint
|
||||
mov rdi, gc_allocated_bytes
|
||||
call printstr
|
||||
call endl
|
||||
|
||||
mov rdi, [gc_bytes_allocated]
|
||||
shl rdi, 1
|
||||
mov rsi, 1024 * 1024 * 8
|
||||
call max
|
||||
mov [gc_trigger_threshold], rax
|
||||
mov qword [gc_bytes_allocated], 0
|
||||
|
||||
mov rdi, gc_next_threshold
|
||||
call printstr
|
||||
mov rdi, [gc_trigger_threshold]
|
||||
call printint
|
||||
mov rdi, gc_allocated_bytes
|
||||
call printstr
|
||||
call endl
|
||||
ret
|
||||
|
||||
gc_mark_stack:
|
||||
@@ -57,7 +98,7 @@ gc_mark_stack:
|
||||
gc_mark:
|
||||
test rdi, rdi ; is input null?
|
||||
jz .done ; yes? return
|
||||
mov rsi, [alloc_list] ; load start of allocation list
|
||||
mov rsi, [alloc_list_head] ; load start of allocation list
|
||||
.loop:
|
||||
test rsi, rsi ; reached end of list?
|
||||
jz .done ; yes? return
|
||||
@@ -85,32 +126,43 @@ gc_mark:
|
||||
ret
|
||||
|
||||
gc_sweep:
|
||||
mov rdi, [alloc_list]
|
||||
mov rdi, [alloc_list_head]
|
||||
xor rsi, rsi
|
||||
.loop:
|
||||
test rdi, rdi ; reached end of list?
|
||||
jz .done ; yes? return
|
||||
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 marking
|
||||
test al, al ; is object marked?
|
||||
jz .unmarked ; no? free it
|
||||
mov byte [rdi], 0 ; yes? clear mark for next marking
|
||||
mov rsi, rdi
|
||||
mov rdi, [rdi + 16] ; load the next object in the list
|
||||
jmp .loop ; repeat
|
||||
.free:
|
||||
mov rdx, [rdi + 16] ; save address of next object in list
|
||||
mov rdi, [rdi + 16] ; load the next object in the list
|
||||
jmp .loop ; repeat
|
||||
.unmarked:
|
||||
mov rdx, [rdi + 16] ; save address of next object in list
|
||||
test rsi, rsi
|
||||
jz .remove_head
|
||||
mov [rsi + 16], rdx ; unlink the current node by setting the previous node's next to the next node's address
|
||||
jmp .free_memory
|
||||
mov [rsi + 16], rdx ; unlink the current node by setting the previous node's next to the next node's address
|
||||
jmp .free
|
||||
.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
|
||||
call free ; free the memory
|
||||
pop rdi ; input for next iteration
|
||||
pop rsi ; prev node for next iteration
|
||||
mov [alloc_list_head], rdx ; update head node to be the next node
|
||||
.free:
|
||||
push rsi ; save previous node since it will also be the previous node for the next item
|
||||
push rdx ; save next node
|
||||
mov rdx, [rdi + 8] ; load the size of the object
|
||||
sub [gc_bytes_allocated], rdx ; adjust allocated bytes
|
||||
call free ; free the memory
|
||||
pop rdi ; input for next iteration
|
||||
pop rsi ; prev node for next iteration
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
ret
|
||||
|
||||
max:
|
||||
cmp rdi, rsi
|
||||
jae .left
|
||||
mov rax, rsi
|
||||
ret
|
||||
.left:
|
||||
mov rax, rdi
|
||||
ret
|
||||
|
||||
Reference in New Issue
Block a user