restructure fs

This commit is contained in:
nub31
2025-05-03 16:55:06 +02:00
parent bfc3aad516
commit 3b142b2453
75 changed files with 38 additions and 387 deletions

View File

@@ -1,277 +0,0 @@
#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
/* Constants */
#define GC_INITIAL_THRESHOLD (1024 * 1024 * 8) // 8MB initial threshold
#define GC_MIN_ALLOC 4096 // Minimum allocation size
/* Allocation metadata structures */
typedef struct alloc_block {
uint8_t mark; // Mark bit for GC
uint8_t padding[7]; // Padding for alignment
int64_t size; // Size of the allocation
struct alloc_block* next; // Next allocation in the list
} alloc_block_t;
typedef struct free_block {
int64_t size; // Size of the free block
struct free_block* next; // Next free block in the list
} free_block_t;
/* Global variables */
static alloc_block_t* alloc_list_head = NULL;
static free_block_t* free_list_head = NULL;
static void* stack_start = NULL;
static int64_t free_list_size = 0;
static int64_t mark_count = 0;
/* GC metrics */
static int64_t gc_bytes_allocated = 0;
static int64_t gc_trigger_threshold = GC_INITIAL_THRESHOLD;
/* Forward declarations */
static void* sys_mmap(size_t size);
static void gc_collect(void);
static void gc_mark(void* ptr);
static void gc_mark_stack(void);
static void gc_sweep(void);
static int64_t max(int64_t a, int64_t b);
static void insert_into_free(free_block_t* block);
static void merge(free_block_t* block);
/* Initialize the garbage collector */
void gc_init(void) {
// Save the current stack pointer as the start of the stack
volatile unsigned long var = 0;
stack_start = (void*)((unsigned long)&var + 4);
}
/* Allocate memory with garbage collection */
void* gc_alloc(int64_t size) {
size += sizeof(alloc_block_t); // Adjust for metadata size
// Check if we need to trigger garbage collection
if (gc_bytes_allocated > gc_trigger_threshold) {
gc_collect();
}
gc_bytes_allocated += size; // Adjust allocation counter
// Search free list for a suitable block
free_block_t* current = free_list_head;
free_block_t* prev = NULL;
while (current != NULL) {
if (current->size >= size) {
// Found a suitable block
break;
}
prev = current;
current = current->next;
}
if (current == NULL) {
// No suitable block found, allocate a new one
int64_t alloc_size = max(size, GC_MIN_ALLOC);
void* memory = sys_mmap(alloc_size);
free_block_t* new_block = (free_block_t*)memory;
new_block->size = alloc_size - sizeof(free_block_t);
new_block->next = NULL;
insert_into_free(new_block);
current = new_block;
// Recalculate prev
if (current == free_list_head) {
prev = NULL;
} else {
prev = free_list_head;
while (prev->next != current) {
prev = prev->next;
}
}
}
// Use the block
alloc_block_t* result;
if (current->size > size) {
// Block is larger than needed, split it
result = (alloc_block_t*)((char*)current + current->size + sizeof(free_block_t) - size);
current->size -= size;
} else {
// Use the entire block
result = (alloc_block_t*)current;
// Remove block from free list
if (prev == NULL) {
free_list_head = current->next;
} else {
prev->next = current->next;
}
free_list_size--;
}
// Initialize metadata
result->mark = 0;
result->size = size - sizeof(alloc_block_t);
result->next = alloc_list_head;
alloc_list_head = result;
// Return pointer to usable memory
return (void*)(result + 1);
}
/* Run garbage collection */
static void gc_collect(void) {
printf("Reached threshold of %ld bytes. Starting GC\n", gc_bytes_allocated);
gc_mark_stack();
printf("\tMarking done. Objects marked is %ld\n", mark_count);
gc_sweep();
printf("\tSweep done. We now have %ld allocated bytes\n", gc_bytes_allocated);
gc_trigger_threshold = max(gc_bytes_allocated * 2, GC_INITIAL_THRESHOLD);
gc_bytes_allocated = 0;
printf("\tThe next threshold is %ld allocated bytes\n", gc_trigger_threshold);
printf("\tFree list size is %ld\n", free_list_size);
}
/* Mark phase of GC - scan stack for pointers */
static void gc_mark_stack(void) {
mark_count = 0;
void** current = (void**)&current; // Approximate current stack position
void** end = (void**)stack_start;
while (current < end) {
gc_mark(*current);
current++;
}
}
/* Mark a single object and recursively mark its contents */
static void gc_mark(void* ptr) {
if (ptr == NULL)
return;
// Check if ptr points to a valid allocation
alloc_block_t* block = alloc_list_head;
while (block != NULL) {
void* block_data = (void*)(block + 1);
if (block_data == ptr) {
// Found the block, mark it if not already marked
if (block->mark == 0) {
mark_count++;
block->mark = 1;
// Recursively mark all pointers in the object
void** p = (void**)block_data;
void** end = (void**)((char*)block_data + block->size);
while (p < end) {
gc_mark(*p);
p++;
}
}
return;
}
block = block->next;
}
}
/* Sweep phase of GC - free unmarked objects */
static void gc_sweep(void) {
alloc_block_t* current = alloc_list_head;
alloc_block_t* prev = NULL;
while (current != NULL) {
if (current->mark == 0) {
// Unmarked object, remove it from the allocation list
alloc_block_t* next = current->next;
if (prev == NULL) {
alloc_list_head = next;
} else {
prev->next = next;
}
// Adjust allocated bytes counter
gc_bytes_allocated -= (current->size + sizeof(alloc_block_t));
// Add to free list
free_block_t* free_block = (free_block_t*)current;
free_block->size = current->size + sizeof(alloc_block_t) - sizeof(free_block_t);
free_block->next = NULL;
insert_into_free(free_block);
current = next;
} else {
// Marked object, unmark it for next GC cycle
current->mark = 0;
prev = current;
current = current->next;
}
}
}
/* Insert a block into the free list, maintaining address order */
static void insert_into_free(free_block_t* block) {
if (free_list_head == NULL || block < free_list_head) {
// Insert at head
block->next = free_list_head;
free_list_head = block;
free_list_size++;
merge(block);
return;
}
// Find insertion point
free_block_t* current = free_list_head;
while (current->next != NULL && current->next < block) {
current = current->next;
}
// Insert after current
block->next = current->next;
current->next = block;
free_list_size++;
// Try to merge adjacent blocks
merge(current);
}
/* Merge a block with any adjacent blocks */
static void merge(free_block_t* block) {
while (block->next != NULL) {
char* block_end = (char*)block + block->size + sizeof(free_block_t);
if (block_end == (char*)block->next) {
// Blocks are adjacent, merge them
free_list_size--;
block->size += block->next->size + sizeof(free_block_t);
block->next = block->next->next;
} else {
// No more adjacent blocks
break;
}
}
}
/* Helper to map memory from the system */
static void* sys_mmap(size_t size) {
void* result = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (result == MAP_FAILED) {
_exit(1); // Exit on failure
}
return result;
}
/* Return maximum of two values */
static int64_t max(int64_t a, int64_t b) {
return (a > b) ? a : b;
}

View File

@@ -1,20 +0,0 @@
global str_cmp
section .text
str_cmp:
xor rdx, rdx
.loop:
mov al, [rsi + rdx]
mov bl, [rdi + rdx]
inc rdx
cmp al, bl
jne .not_equal
cmp al, 0
je .equal
jmp .loop
.not_equal:
mov rax, 0
ret
.equal:
mov rax, 1
ret

View File

@@ -1,6 +0,0 @@
global arr_size
section .text
arr_size:
mov rax, [rdi]
ret

View File

@@ -1 +0,0 @@
extern func arr_size(array: Array<Any>): int64;

View File

@@ -1,23 +0,0 @@
section .bss
buffer resb 20
section .text
global itoa
itoa:
mov rax, rdi
mov rsi, buffer + 19
mov byte [rsi], 0
dec rsi
.loop:
xor rdx, rdx
mov rcx, 10
div rcx
add dl, '0'
mov [rsi], dl
dec rsi
test rax, rax
jnz .loop
inc rsi
mov rax, rsi
ret

View File

@@ -1,38 +0,0 @@
let SYS_WRITE = 1;
let STD_OUT = 1;
let STD_ERR = 2;
func print(msg: String) {
syscall(SYS_WRITE, STD_OUT, msg, str_len(msg));
}
func print(value1: int64) {
print(itoa(value1));
}
func print(value2: bool) {
if value2 {
print("true");
} else {
print("false");
}
}
func println() {
print("\n");
}
func println(msg: String) {
print(msg);
println();
}
func println(value3: bool) {
print(value3);
println();
}
func println(value4: int64) {
print(value4);
println();
}

View File

@@ -1,13 +0,0 @@
global str_len
section .text
str_len:
xor rax, rax
.loop:
cmp byte [rdi], 0
jz .done
inc rax
inc rdi
jmp .loop
.done:
ret

View File

@@ -1,2 +0,0 @@
extern func str_len(msg: String): int64;
extern func itoa(value: int64): String;

View File

@@ -1,19 +0,0 @@
import "core";
func main() {
let i = 1;
while true {
let x = new Human
{
name = "test",
age = 34958743
};
i = i + 1;
}
}
struct Human {
let name: String;
let age: int64;
}

View File

@@ -1,311 +0,0 @@
;*********************************************************************
; util.asm
; Version: 1.2
; Author: mjbrusso
; Contributors: AlessandroFonseca
; Licensed under the MIT license (see "license.txt").
;*********************************************************************
global exit, exit0, strlen, atoi, endl, printstr, printint, readstr, readint
SYS_READ: equ 0
SYS_WRITE: equ 1
SYS_EXIT: equ 60
STDIN: equ 0
STDOUT: equ 1
LINEFEED: equ 0x0A
section .text
;*********************************************************************
; void exit(int64 code)
;
; Description:
; Quit program
;
; Arguments:
; rdi: int64 code: Exit code (0=Success, >0=Error)
;
; Returns:
; This function does not return
;
;*********************************************************************
exit:
mov rax, SYS_EXIT ; rax: system call number
syscall
;*********************************************************************
;*********************************************************************
; void exit0()
;
; Description:
; Quit program with status code = 0
;
; Arguments:
; None
;
; Returns:
; This function does not return
;
;*********************************************************************
exit0:
xor rdi, rdi ; rdi = 0
jmp exit ; TCO: tail call optimization
;*********************************************************************
;*********************************************************************
; int64 strlen(char *s)
;
; Description:
; Calculates the length of string ( excluding the terminating null)
;
; Arguments:
; rdi: char *s: address of a null-terminated string (array of chars terminated by 0)
;
; Returns:
; rax: int64: string size
;
;*********************************************************************
strlen:
xor rax, rax ; rax=0; // reset counter
.loop: ; do{
cmp byte [rdi], 0 ; if (*s==0); // If zero, skip loop
je strlen.end ; break;
inc rax ; rax++; // increment counter
inc rdi ; s++; // advance to the next char
jmp strlen.loop ; }while(true);
.end:
ret ; return rax;
;*********************************************************************
;*********************************************************************
; void itoa(int64 value, char *s)
;
; Description:
; Converts an integer to a null-terminated string.
;
; Arguments:
; rdi: int64 value: Integer value to convert.
; rsi: char *s: Memory address where to store the resulting string.
;
; Returns:
; rax: int64: string size
;
;*********************************************************************
itoa:
test rdi, rdi ; value = rdi
jz itoa.iszero ; value==0 has a direct solution
jns itoa.notneg ; if(value <0 )
mov byte [rsi], '-' ; *s = '-'
neg rdi ; value = -value
inc rsi ; s++
.notneg:
mov r9b, 1 ; bool leftzero=true
mov r10, 10 ; base = 10
mov rcx, 1000000000000000000 ; divisor = 1000000000000000000
mov r8, 19 ; cont = 19 // Will repeat 19 times
.loop: ; do{
mov rax, rdi ; dividend[0..31] = value
xor rdx, rdx ; dividend[32..63] = 0
idiv rcx ; rax=(rdx:rax)/rcx ; rdx=(rdx:rax)%rcx
test al, al ; digit = rax[0..7]
jnz itoa.notdigit0 ; if(digit!=0)
test r9b, r9b ; if(leftzero)
jnz itoa.nextdigit ; continue
jmp itoa.digit0
.notdigit0:
xor r9b, r9b ; leftzero = false
.digit0:
add eax, 48 ; digit = '0' + digit
mov rdi, rdx ; value %= divisor
mov byte [rsi], al ; *p = digit
inc rsi ; p++
.nextdigit:
mov rax, rcx ; dividend[0..31] = value
xor rdx, rdx ; dividend[32..63] = 0
idiv r10 ; rax=(rdx:rax)/10 ; rdx=(rdx:rax)%10
mov rcx, rax ; divisor /= 10
dec r8 ; cont--
jne itoa.loop ; }while(cont!=0)
.end:
mov byte [rsi], 0 ; *p = '\0'
ret
.iszero:
mov word [rsi], 0x0030 ; *p = "0" (x86 is little endian)
ret
;*********************************************************************
;*********************************************************************
; int64 atoi(char *s)
;
; Description:
; Convert string to integer.
;
; Arguments:
; rdi: char *s: Address of a null-terminated string (array of chars terminated by 0)
;
; Returns:
; rax: int64: integer value
;*********************************************************************
atoi:
push r12 ; r12 is callee saved
mov r12, rdi ; rdi is caller saved
call strlen
lea rdi, [r12+rax-1] ; char *p = &s[strlen(string)]; //scans string backward
xor rax, rax ; result value
mov rdx, 1 ; multiplier
.beginloop:
cmp rdi, r12 ; while(p>=s){
jl atoi.end ;
xor rcx, rcx ;
mov cl, byte [rdi] ; cl = current char
cmp cl, '-' ; if(cl=='-')
jne atoi.notneg ;
neg rax ; rax=-rax
jmp atoi.end ;
.notneg:
cmp cl, '9' ; if(!isdigit(cl)) nextdigit
jg atoi.endloop ;
sub cl, '0' ;
jl atoi.endloop ;
imul rcx, rdx ; digit_value = current_char * multiplier
add rax, rcx ; result += digit_value
imul rdx, 10 ; multiplier *= 10
.endloop:
dec rdi ; previous char //scans string backward
jmp atoi.beginloop ; }
.end:
pop r12 ; restore r12
ret
;*********************************************************************
;*********************************************************************
; void endl()
;
; Description:
; Prints a newline (line break)
;
; Arguments:
; None
;
; Returns:
; Nothing
;
;*********************************************************************
endl:
lea rdi, [endl.str] ; print the string
call printstr
ret
;*********************************************************************
;*********************************************************************
; void printstr(char *s)
;
; Description:
; Print a string
;
; Arguments:
; rdi: char *s: address of a null-terminated string (array of chars terminated by 0)
;
; Returns:
; Nothing
;
;*********************************************************************
printstr:
push r15 ; r15 is callee saved
mov r15, rdi ; save copy (rdi should be caller saved)
call strlen
mov rdx, rax ; string size
mov rsi, r15 ; string
mov rax, SYS_WRITE ; system call number
mov rdi, STDOUT ; file descriptor
syscall ; system call
pop r15
ret
;*********************************************************************
;*********************************************************************
; void printint(int64 n)
;
; Description:
; Print integer number (decimal)
;
; Arguments:
; rdi: int64 n: Value to print
;
; Returns:
; Nothing
;
;*********************************************************************
printint:
sub rsp, 40 ; stack allocate a temp string
mov rsi, rsp ; rdi=value, rsi=&str[0]
call itoa
mov rdi, rsp ; rdi=&str[0]
call printstr ; print number
add rsp, 40 ; deallocate the string
ret
;*********************************************************************
;*********************************************************************
; int64 readstr(char *s, int64 maxsize)
;
; Description:
; Read up to *maxsize* chars from standard input into a string.
;
; Arguments:
; rdi: char *s: address of a string (array of chars)
; rsi: int64 maxsize: input size limit
;
; Returns:
; rax: int64: Number of characters read
;
;*********************************************************************
readstr:
mov r8, rdi ; copy of buffer address
mov rax, SYS_READ ; system call number
mov rdx, rsi ; pointer to buffer
mov rsi, rdi ; max size
mov rdi, STDIN ; file descriptor
syscall ; system call
dec rax ; removing trailing newline char
mov byte [r8+rax], 0 ; replace with '\0'
ret
;*********************************************************************
;*********************************************************************
; int64 readint()
;
; Description:
; Read int64 from standard input
;
; Arguments:
; None
;
; Returns:
; rax: int64: The value entered
;
;*********************************************************************
readint:
sub rsp, 40 ; char s[40]
mov rdi, rsp ; rdi = &s[0]
mov rsi, 21 ; max input size
call readstr ; read number as string
mov rdi, rsp ;
call atoi ; rax = atoi(s)
add rsp, 40 ; deallocate s from stack
ret
;*********************************************************************
section .data
endl.str: db LINEFEED, 0