gc
This commit is contained in:
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user