This commit is contained in:
nub31
2025-02-04 18:53:35 +01:00
parent ee643771c8
commit d787cd4acc
2 changed files with 69 additions and 61 deletions

View File

@@ -6,16 +6,17 @@ section .bss
free_list_head: resq 1 ; metadata size: 16 free_list_head: resq 1 ; metadata size: 16
stack_start: resq 1 stack_start: resq 1
free_list_size: resq 1 free_list_size: resq 1
mark_count: resq 1
section .data section .data
gc_bytes_allocated: dq 0 ; bytes allocated since the last gc cycle 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_trigger_threshold: dq 1024 * 1024 * 8 ; initial gc trigger threshold in bytes (adjusts dynamically)
gc_start_text: db "Running gc after ", 0 txt_start_collect: db "Running gc after ", 0
gc_sweep_done_text: db " Sweep done. We no have ", 0 txt_sweep_done: db " Sweep done. We now have ", 0
gc_next_threshold: db " The next threshold is ", 0 txt_next_threshold: db " The next threshold is ", 0
gc_allocated_bytes: db " allocated bytes", 0 txt_allocated_bytes: db " allocated bytes", 0
gc_mark_done_text: db " Marking done", 0 txt_marking_done: db " Marking done. Objects marked is ", 0
free_list_size_text: db "free has a size of ", 0 txt_free_list_size: db " Free list size is ", 0
section .text section .text
gc_init: gc_init:
@@ -53,7 +54,8 @@ gc_alloc:
call sys_mmap call sys_mmap
pop rsi pop rsi
sub rsi, 16 sub rsi, 16
mov qword [rax], rsi ; update metadata to page size - metadata mov qword [rax], rsi ; set size of object to page size - metadata
mov qword [rax + 8], 0 ; ensure that next pointer is null
push rax push rax
mov rdi, rax mov rdi, rax
call insert_into_free call insert_into_free
@@ -68,12 +70,13 @@ gc_alloc:
mov rdx, [rsi + 8] ; load next node mov rdx, [rsi + 8] ; load next node
mov [r8 + 8], rdx ; link next node to last node's next mov [r8 + 8], rdx ; link next node to last node's next
jmp .unlink_done jmp .unlink_done
dec qword [free_list_size]
.unlink_head: .unlink_head:
mov rdx, [free_list_head] ; load head mov rdx, [free_list_head] ; load head
mov rdx, [rdx + 8] ; load head.next mov rdx, [rdx + 8] ; load head.next
mov [free_list_head], rdx ; mov head.next into head mov [free_list_head], rdx ; mov head.next into head
.unlink_done:
dec qword [free_list_size] dec qword [free_list_size]
.unlink_done:
sub [rsi], rdi ; reduce available space of block by the allocated space sub [rsi], rdi ; reduce available space of block by the allocated space
mov rdx, [rsi] ; load the available space excluding the newly allocated space mov rdx, [rsi] ; load the available space excluding the newly allocated space
lea rax, [rsi + rdx + 16] ; load the address of the newly allocated space lea rax, [rsi + rdx + 16] ; load the address of the newly allocated space
@@ -87,27 +90,22 @@ gc_alloc:
ret ret
gc_collect: gc_collect:
mov rdi, gc_start_text mov rdi, txt_start_collect
call printstr call printstr
mov rdi, [gc_bytes_allocated] mov rdi, [gc_bytes_allocated]
call printint call printint
mov rdi, gc_allocated_bytes mov rdi, txt_allocated_bytes
call printstr call printstr
call endl call endl
call gc_mark_stack call gc_mark_stack
mov rdi, gc_mark_done_text
call printstr
call endl
call gc_sweep call gc_sweep
mov rdi, gc_sweep_done_text mov rdi, txt_sweep_done
call printstr call printstr
mov rdi, [gc_bytes_allocated] mov rdi, [gc_bytes_allocated]
call printint call printint
mov rdi, gc_allocated_bytes mov rdi, txt_allocated_bytes
call printstr call printstr
call endl call endl
@@ -118,16 +116,23 @@ gc_collect:
mov [gc_trigger_threshold], rax mov [gc_trigger_threshold], rax
mov qword [gc_bytes_allocated], 0 mov qword [gc_bytes_allocated], 0
mov rdi, gc_next_threshold mov rdi, txt_next_threshold
call printstr call printstr
mov rdi, [gc_trigger_threshold] mov rdi, [gc_trigger_threshold]
call printint call printint
mov rdi, gc_allocated_bytes mov rdi, txt_allocated_bytes
call printstr call printstr
call endl call endl
mov rdi, txt_free_list_size
call printstr
mov rdi, [free_list_size]
call printint
call endl
ret ret
gc_mark_stack: gc_mark_stack:
mov qword [mark_count], 0
mov r8, rsp ; load current stack pointer mov r8, rsp ; load current stack pointer
mov r9, [stack_start] ; load start of stack mov r9, [stack_start] ; load start of stack
.loop: .loop:
@@ -138,34 +143,41 @@ gc_mark_stack:
lea r8, [r8 + 8] ; next item in stack lea r8, [r8 + 8] ; next item in stack
jmp .loop jmp .loop
.done: .done:
mov rdi, txt_marking_done
call printstr
mov rdi, [mark_count]
call printint
call endl
ret ret
gc_mark: gc_mark:
test rdi, rdi ; is input null? test rdi, rdi
jz .done ; yes? return jz .done ; if stack item is null, return
mov rsi, [alloc_list_head] ; load start of allocation list mov rsi, [alloc_list_head]
.loop: .loop:
test rsi, rsi ; reached end of list? test rsi, rsi
jz .done ; yes? return jz .done ; return if end of list is reached
lea rdx, [rsi + 24] lea rdx, [rsi + 24] ; input value does not include metadata
cmp rdx, rdi ; no? is this the input object? cmp rdx, rdi
je .mark_object ; yes? mark it je .mark_object ; if match is found, mark the object
mov rsi, [rsi + 16] ; no? next item mov rsi, [rsi + 16] ; load next item and repeat
jmp .loop jmp .loop
.mark_object: .mark_object:
inc qword [mark_count]
mov al, [rdi] ; load mark mov al, [rdi] ; load mark
test al, al ; already marked? test al, al ; already marked?
jnz .done ; yes? return jnz .done ; yes? return
mov byte [rdi - 24], 1 ; mark object mov byte [rdi - 24], 1 ; mark object
mov rcx, [rdi + 8] ; load object size mov rcx, [rdi - 16] ; load object size
mov rdx, rdi ; start of data lea rcx, [rdi + rcx] ; end of object
add rcx, rdx ; end of data
.scan_object: .scan_object:
cmp rdx, rcx ; done scanning? cmp rdi, rcx
jae .done ; yes? return jge .done
mov rdi, [rdx] ; load value push rdi
mov rdi, [rdi]
call gc_mark call gc_mark
add rdx, 8 ; next object pop rdi
lea rdi, [rdi + 8]
jmp .scan_object jmp .scan_object
.done: .done:
ret ret
@@ -196,9 +208,13 @@ gc_sweep:
.unlink_done: .unlink_done:
push r8 ; save previous node since it will also be the previous node for the next item push r8 ; save previous node since it will also be the previous node for the next item
push r9 ; save next node push r9 ; save next node
mov rdx, [rdi + 8] ; load the size of the object mov rdx, [rdi + 8] ; load current size
add rdx, 24 ; adjust for metadata size add rdx, 24 ; add metadata size back
sub [gc_bytes_allocated], rdx ; adjust allocated bytes sub [gc_bytes_allocated], rdx ; adjust allocated bytes
mov rdx, [rdi + 8] ; load current size
add rdx, 8 ; adjust for smaller metadata in free list
mov [rdi], rdx ; save new size in correct position
mov qword [rdi + 8], 0 ; set next to null
call insert_into_free call insert_into_free
pop rdi ; input for next iteration pop rdi ; input for next iteration
pop r8 ; prev node for next iteration pop r8 ; prev node for next iteration
@@ -215,17 +231,19 @@ insert_into_free:
test r9, r9 test r9, r9
jz .insert_tail ; if at end of the list, insert at tail jz .insert_tail ; if at end of the list, insert at tail
cmp rdi, r9 cmp rdi, r9
ja .next ; if input > next continue jbe .insert_between ; if input < next insert between current and next
mov rsi, r9
jmp .loop
.insert_between:
mov [rdi + 8], r9 ; input.next = next mov [rdi + 8], r9 ; input.next = next
mov [rsi + 8], rdi ; current.next = input mov [rsi + 8], rdi ; current.next = input
mov rdi, rsi
inc qword [free_list_size] inc qword [free_list_size]
mov rdi, rsi
call merge call merge
ret ret
.insert_head: .insert_head:
mov [rdi + 8], rsi ; set old head to input.next mov [rdi + 8], rsi
mov [free_list_head], rdi ; set head to input mov [free_list_head], rdi
mov rdi, [free_list_head]
inc qword [free_list_size] inc qword [free_list_size]
call merge call merge
ret ret
@@ -233,36 +251,26 @@ insert_into_free:
mov qword [rdi + 8], 0 ; set input.tail to null mov qword [rdi + 8], 0 ; set input.tail to null
mov [rsi + 8], rdi ; add input to current.next mov [rsi + 8], rdi ; add input to current.next
inc qword [free_list_size] inc qword [free_list_size]
mov rdi, rsi
call merge
ret ret
.next:
mov rsi, r9
jmp .loop
; rdi: current
merge: merge:
mov rsi, [rdi + 8] mov rsi, [rdi + 8]
test rsi, rsi test rsi, rsi
jz .skip jz .return
mov rdx, [rdi] mov rdx, [rdi]
lea rdx, [rdi + rdx + 16] lea rdx, [rdi + rdx + 16]
cmp rdx, rsi cmp rdx, rsi
jne .skip jne .return
push rdi dec qword [free_list_size]
mov rdi, free_list_size_text
call printstr
mov rdi, [free_list_size]
call printint
call endl
pop rdi
mov rdx, [rsi] mov rdx, [rsi]
add rsi, 16 add rdx, 16
add [rdi], rdx add [rdi], rdx
mov rdx, [rsi + 8] mov rdx, [rsi + 8]
mov [rdi + 8], rdx mov [rdi + 8], rdx
mov rsi, rdx jmp merge
call merge .return:
.skip:
ret ret
sys_mmap: sys_mmap:

View File

@@ -16,4 +16,4 @@ nasm -g -felf64 out.asm -o out.o
# tmp # tmp
nasm -g -felf64 ../input/util.asm -o util.o nasm -g -felf64 ../input/util.asm -o util.o
ld -o out out.o gc.o alloc.o str_cmp.o str_len.o arr_size.o itoa.o util.o ld -o out gc.o alloc.o str_cmp.o str_len.o arr_size.o itoa.o util.o out.o