Skip to content

Commit

Permalink
gc and fixes and better syscall stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
cetio committed May 15, 2024
1 parent 9fbebc9 commit 6b293d8
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 16 deletions.
24 changes: 11 additions & 13 deletions rt/aso.fn
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module rt.aso;
* Open addressing, with tuple key value bucket array,
* a void string means no key and thus no value may exist there.
*
* Will prod 5 times until deciding that a key doesn't exist or there is no space,
* Will probe 5 times until deciding that a key doesn't exist or there is no space,
* will resize to double the current bucket size if there is no space available.
*/
public struct AsoArray(K, V)
Expand Down Expand Up @@ -54,8 +54,8 @@ public struct AsoArray(K, V)
nuint head;
while (buckets[index][0] != key)
{
if (head++ > 5)
rehash(buffer.length * 2);
if (++head > 5)
rehash(buckets.length * 2);
index = index.__hash();
}
return = buckets[index][1];
Expand All @@ -67,8 +67,8 @@ public struct AsoArray(K, V)
nuint head;
while (buckets[index][0] != key)
{
if (head++ > 5)
rehash(buffer.length * 2);
if (++head > 5)
rehash(buckets.length * 2);
index = index.__hash();
}
buckets[index] = [key, val];
Expand All @@ -79,7 +79,7 @@ public struct AsoArray(K, V)
if (op == "in")
{
nuint index = key.__hash() % buckets.length;
foreach (i; 0..6)
foreach (i; 0..5)
{
if (buckets[index][0] == key)
return => true;
Expand All @@ -89,17 +89,15 @@ public struct AsoArray(K, V)
}
}

nuint __hash(uint SEED, T)(const T val)
nuint __hash(T)(const T val)
{
ubyte[nuint->size] buffer;
ubyte* ptr = &val |> ubyte*;
foreach (i; 0..buffer.length)
foreach (i; 0..nuint->size)
foreach (j; 0..val->size)
{
foreach (j; 0..val->size)
{
buffer[i] ^= buffer[j] += ptr[j] ^ SEED;
buffer[(j + i) % 8] += buffer[i] ^= ptr[i] ^ SEED;
}
buffer[i] ^= buffer[j] += ptr[j];
buffer[(j + i) % nuint->size] += buffer[i] ^= ptr[i];
}
return = buffer |> nuint;
}
114 changes: 113 additions & 1 deletion rt/gc.fn
Original file line number Diff line number Diff line change
@@ -1 +1,113 @@
module rt.gc;
module rt.gc;

import rt.sys;

private struct Object
{
void* ptr;
nuint size;
Object* prev;
atomic bool free;
// byte[size] data follows this.
}

public struct Root
{
// TODO: Definitely need some atomics here.
void* base;
void* tail;
nuint size;
nuint free;
}

/**
* The Fern garbage collector and allocator.
*
* Stores a root of the current allocation and a tree of all allocated objects.
* The tree is stored in reverse with bytes directly following the object struct with allocation info.
*/
public struct GC
{
// 4MB per sector page.
alias pageSize = 1024 * 1024 * 4;

// This will store a count of all living, GC-owned objects.
atomic uint living;
// Only one root exists at a time but many root allocations may have happened,
// we simply don't care about those previous allocations and keep track of all of the
// objects that were allocated in them instead.
//
// An object should NEVER be completely freed or have its prev pointer invalidated,
// as this would lead to potentially all memory being leaked.
Root root;
Object* tail;

void bump(Object* obj)
{
obj.prev = tail;
tail = obj;
}

void create(size_t size = pageSize)
{
// TODO: Not cross platform!
void* ptr = __syscall!(void*)(mmap, void, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
root.base = ptr;
root.size = size;
}

// TODO: Alignment
void* alloc(nuint size) trusted;
{
// A freed object is available for allocation.
while (true)
{
Object* obj;
if (obj.free && obj.size >= size)
{
obj.free = false;
bump(obj);
return => obj.ptr;
}
obj = tail.prev;
}

// The root currently has enough space to allocate anew.
if (root.free >= size)
{
Object* ptr = root.tail |> Object*;
return = ptr + 1;

*ptr = Object(return, size);
bump(ptr);

root.free -= size;
root.tail = return + size;
}

// The root neither has space nor available objects but is not completely full,
// by doing this allocation we avoid potentially leaking a stupidly large amount of memory,
// or at least preserve bytes that might end up being useful later.
if (root.free != 0)
{
Object* ptr = root.tail |> Object*;
*ptr = Object(ptr, root.free);
bump(ptr);
}

// The root neither has space nor available objects, we need to allocate a new root.
if (size > pageSize)
create(size);
else
create();

Object* ptr = root.base |> Object*;
return = ptr + 1;

*ptr = Object(return, size);
bump(ptr);

root.free -= size;
root.tail = return + size;
}
}
53 changes: 51 additions & 2 deletions rt/sys.fn
Original file line number Diff line number Diff line change
Expand Up @@ -341,10 +341,59 @@ public const tagged SCID
pkey_mprotect2;
}

void __syscall(ARGS...)(SCID id, ARGS args) trusted;
public:
alias PMUTEX_INIT = 0;
alias PMUTEX_LOCK = 1;
alias PMUTEX_UNLOCK = 2;
alias PMUTEX_DESTROY = 3;

alias MAP_SHARED = 0x01;
alias MAP_PRIVATE = 0x02;
alias MAP_SHARED_VALIDATE = 0x03;
alias MAP_TYPE = 0x0f;
alias MAP_FIXED = 0x10;
alias MAP_ANONYMOUS = 0x20;
alias MAP_NORESERVE = 0x4000;
alias MAP_GROWSDOWN = 0x0100;
alias MAP_DENYWRITE = 0x0800;
alias MAP_EXECUTABLE = 0x1000;
alias MAP_LOCKED = 0x2000;
alias MAP_POPULATE = 0x8000;
alias MAP_NONBLOCK = 0x10000;
alias MAP_STACK = 0x20000;
alias MAP_HUGETLB = 0x40000;
alias MAP_SYNC = 0x80000;
alias MAP_FIXED_NOREPLACE = 0x100000;
alias MAP_FILE = 0;
alias MAP_UNINITIALIZED = 0x4000000;

alias MAP_HUGE_SHIFT = 26
alias MAP_HUGE_MASK = 0x3f
alias MAP_HUGE_16KB = (14 << 26)
alias MAP_HUGE_64KB = (16 << 26)
alias MAP_HUGE_512KB = (19 << 26)
alias MAP_HUGE_1MB = (20 << 26)
alias MAP_HUGE_2MB = (21 << 26)
alias MAP_HUGE_8MB = (23 << 26)
alias MAP_HUGE_16MB = (24 << 26)
alias MAP_HUGE_32MB = (25 << 26)
alias MAP_HUGE_256MB = (28 << 26)
alias MAP_HUGE_512MB = (29 << 26)
alias MAP_HUGE_1GB = (30 << 26)
alias MAP_HUGE_2GB = (31 << 26)
alias MAP_HUGE_16GB = (34U << 26)

alias PROT_NONE = 0;
alias PROT_READ = 1;
alias PROT_WRITE = 2;
alias PROT_EXEC = 4;
alias PROT_GROWSDOWN = 0x01000000;
alias PROT_GROWSUP = 0x02000000;

R __syscall(R = void, ARGS...)(SCID id, ARGS args) trusted;
{
__asm(
syscall(none, id, unroll args);
syscall(return, id, unroll args)
);
return;
}

0 comments on commit 6b293d8

Please sign in to comment.