aboutsummaryrefslogtreecommitdiff
path: root/include/gc.s
diff options
context:
space:
mode:
authorMirek Kratochvil <exa.exa@gmail.com>2023-10-29 23:03:33 +0100
committerMirek Kratochvil <exa.exa@gmail.com>2023-10-29 23:03:33 +0100
commit8504d72bda94c3a1668ebbdd262ae8a4963a23c1 (patch)
tree87a73fdf2813663b5aeee9039601afb86f650aa7 /include/gc.s
parent9209d53449082cb6a5c3fb2ccb15d2448f1b55bf (diff)
downloaduskel-8504d72bda94c3a1668ebbdd262ae8a4963a23c1.tar.gz
uskel-8504d72bda94c3a1668ebbdd262ae8a4963a23c1.tar.bz2
gc attempt 1 (to be cont'd)
Diffstat (limited to 'include/gc.s')
-rw-r--r--include/gc.s74
1 files changed, 74 insertions, 0 deletions
diff --git a/include/gc.s b/include/gc.s
new file mode 100644
index 0000000..bb32240
--- /dev/null
+++ b/include/gc.s
@@ -0,0 +1,74 @@
+
+.ifndef _gc_s_file
+_gc_s_file:
+
+.macro prealloc name amount
+ mov %rsp,%rax
+ sub _write_region_start, %rax
+ cmp $amount, %rax #TODO check direction
+ jb _uskel_gc
+.endm
+
+_uskel_alloc:
+ mov %rsi, %r15 # %rsi is the return address; back it up
+
+ # calculate the desired size to %r14
+ mov _gc_min_alloc, %r14
+
+ # check if the desired size isn't greater because of the last gc use
+ mov _gc_last_size, %rax
+ mul _gc_min_expect_ratio, %rax
+ shr 8, %rax
+ cmp %r14, %rax #TODO check direction
+ cmova %rax, %r14
+
+ # check if we don't need even more space because we need to evacuate stuff
+ mov _gc_region_end, %rax
+ sub %rsp, %rax # trick -- if we counted from gc region start, allocated memory could never shrink
+ cmp %r14, %rax #TODO direction
+ cmova %rax, %r14
+ #TODO add functionality to trigger the gc's a bit earlier than when
+ # they hit _write_region_start, to allow for faster compaction.
+ # maybe _write_region_trigger = 25%ish between _write_region_start and %rsp ?
+
+ mov $9, %rax # mmap
+ mov $0, %rdi # addr = NULL
+ mov %r14, %rsi # len = %r14
+ mov $0b11, %rdx # prot = PROT_READ 0b1 | PROT_WRITE 0b10
+ mov $0x22, %r10 # flags = MAP_PRIVATE 0x2 | MAP_ANONYMOUS 0x20
+ mov $-1, %r8 # fd = -1
+ mov $0, %r9 # off = 0
+ syscall
+
+ # store the results
+ mov %rax, _write_region_start
+ add %r14, %rax
+ mov %rax, _write_region_end
+ mov %rax, %rsp # initialize writing into the new region
+
+ jmp *%r15
+
+_uskel_gc:
+ mov %rbp, _gc_backup_thunk
+ mov %rsi, _gc_backup_cont
+ # first we need a new memory area
+ mov _write_region_start, _gc_region_start
+ mov _write_region_end, _gc_region_end
+ mov $_uskel_gc_evacuate, %r15
+ jmp _uskel_alloc
+ _uskel_gc_evacuate:
+ # we may also need a scavenging queue! Or can that be solved by walking the write region?
+ # plan:
+ # evacuate thunk and cont, save them right away in _gc_backup_thunk and _cont
+ # scavenge from the top of the gc region, evacuating stuff en route
+ # (this is a little more complex because we grow down, so we have to
+ # scavenge up from %rsp to the last known scavenged position)
+ # finish when scavenge doesn't have anything more to scavenge
+
+ # save how much data we actually had at this point
+ mov _write_region_end, _gc_last_size
+ sub %rsp, _gc_last_size
+
+ enter_rbp # restart the thunk for simplicity
+
+.endif #_gc_s_file