From bfc3aad51631aba4a933836ca27a03f22aaa4603 Mon Sep 17 00:00:00 2001 From: nub31 Date: Sat, 3 May 2025 16:32:51 +0200 Subject: [PATCH] convert gc to c --- .clang-format | 3 + Nub.Lang/Nub.Core/Nub.Core.csproj | 9 + Nub.Lang/Nub.Lang.sln | 6 + Nub.Lang/Nub.Lang/Nub.Lang.csproj | 2 +- input/baseline/alloc.asm | 160 --------------- input/baseline/gc.asm | 311 ------------------------------ input/baseline/gc.c | 277 ++++++++++++++++++++++++++ input/baseline/gc/gc.c | 0 input/baseline/gc/gc.h | 6 - output/build.sh | 12 +- output/clean.sh | 8 + 11 files changed, 306 insertions(+), 488 deletions(-) create mode 100644 .clang-format create mode 100644 Nub.Lang/Nub.Core/Nub.Core.csproj delete mode 100644 input/baseline/alloc.asm delete mode 100644 input/baseline/gc.asm create mode 100644 input/baseline/gc.c delete mode 100644 input/baseline/gc/gc.c delete mode 100644 input/baseline/gc/gc.h create mode 100755 output/clean.sh diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..f9641b6 --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +BasedOnStyle: Chromium +IndentWidth: 4 +ColumnLimit: 120 \ No newline at end of file diff --git a/Nub.Lang/Nub.Core/Nub.Core.csproj b/Nub.Lang/Nub.Core/Nub.Core.csproj new file mode 100644 index 0000000..3a63532 --- /dev/null +++ b/Nub.Lang/Nub.Core/Nub.Core.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/Nub.Lang/Nub.Lang.sln b/Nub.Lang/Nub.Lang.sln index c5692ff..fb016f5 100644 --- a/Nub.Lang/Nub.Lang.sln +++ b/Nub.Lang/Nub.Lang.sln @@ -2,6 +2,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nub.Lang", "Nub.Lang\Nub.Lang.csproj", "{5047E21F-590D-4CB3-AFF3-064316485009}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nub.Core", "Nub.Core\Nub.Core.csproj", "{903F2D49-4F69-4287-A709-EFC68BDD9654}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -12,5 +14,9 @@ Global {5047E21F-590D-4CB3-AFF3-064316485009}.Debug|Any CPU.Build.0 = Debug|Any CPU {5047E21F-590D-4CB3-AFF3-064316485009}.Release|Any CPU.ActiveCfg = Release|Any CPU {5047E21F-590D-4CB3-AFF3-064316485009}.Release|Any CPU.Build.0 = Release|Any CPU + {903F2D49-4F69-4287-A709-EFC68BDD9654}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {903F2D49-4F69-4287-A709-EFC68BDD9654}.Debug|Any CPU.Build.0 = Debug|Any CPU + {903F2D49-4F69-4287-A709-EFC68BDD9654}.Release|Any CPU.ActiveCfg = Release|Any CPU + {903F2D49-4F69-4287-A709-EFC68BDD9654}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/Nub.Lang/Nub.Lang/Nub.Lang.csproj b/Nub.Lang/Nub.Lang/Nub.Lang.csproj index 4832d7a..51d1bc4 100644 --- a/Nub.Lang/Nub.Lang/Nub.Lang.csproj +++ b/Nub.Lang/Nub.Lang/Nub.Lang.csproj @@ -8,7 +8,7 @@ - + diff --git a/input/baseline/alloc.asm b/input/baseline/alloc.asm deleted file mode 100644 index 080190c..0000000 --- a/input/baseline/alloc.asm +++ /dev/null @@ -1,160 +0,0 @@ -global alloc, free - -section .bss - free_list_head: resq 1 ; head of free list - alloc_list_head: resq 1 ; head of allocation list - -section .text -alloc: - add rdi, 16 ; reserve 16 bytes for metadata - mov rsi, [free_list_head] - xor r8, r8 -.loop: - test rsi, rsi ; allocate new block if end of list is reached - jz .new_block - mov rdx, [rsi] - cmp rdx, rdi ; is there enough space for allocation? - ja .use_block ; yes? allocate - add rdx, 16 - cmp rdx, rdi ; no? is there enough space if we include metadata - je .use_block ; if we include metadata, the sizes has to match exactly, or partial metadata will persist - mov r8, rsi ; r8 contains the node from the last iteration - mov rsi, [rsi + 8] ; next node - jmp .loop -.new_block: - push rdi - push r8 - add rdi, 16 - mov rsi, 4096 - call max - push rax - mov rdi, rax - call sys_mmap - pop rsi - sub rsi, 16 - mov qword [rax], rsi ; update metadata to page size - metadata - push rax - mov rdi, rax - call insert_into_free - pop rsi - pop r8 - pop rdi -.use_block: - cmp [rsi], rdi ; check if the block will be empty after allocation - ja .unlink_done ; if not, do not unlink - test r8, r8 ; r8 is null if node is also head - jz .unlink_head - mov rdx, [rsi + 8] ; load next node - mov [r8 + 8], rdx ; link next node to last node's next - jmp .unlink_done -.unlink_head: - mov rdx, [free_list_head] ; load head - mov rdx, [rdx + 8] ; load head.next - mov [free_list_head], rdx ; mov head.next into head -.unlink_done: - sub [rsi], rdi ; reduce available space of block by the 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 - sub rdi, 16 - mov [rax], rdi ; update metadata to allocation size - metadata - mov rdx, [alloc_list_head] - mov [rax + 8], rdx ; move head to nex item in this alloc - mov [alloc_list_head], rax ; update head to point to this node - lea rax, [rax + 16] ; skip past metadata for return value - ret - -free: - lea rdi, [rdi - 16] ; adjust for metadata - mov rsi, [alloc_list_head] - xor r8, r8 -.loop: - test rsi, rsi - jz .not_found - cmp rdi, rsi - je .found - mov r8, rsi - mov rsi, [rsi + 8] ; next node - jmp .loop -.not_found: - mov rax, 60 - mov rdi, 1 - syscall -.found: - test r8, r8 ; r8 is null if node is also head - jz .unlink_head - mov rdx, [rsi + 8] ; load next node - mov [r8 + 8], rdx ; link next node to last node's next - jmp .unlink_done -.unlink_head: - mov rdx, [alloc_list_head] ; load head - mov rdx, [rdx + 8] ; load head.next - mov [alloc_list_head], rdx ; mov head.next into head -.unlink_done: - mov rdi, rsi - call insert_into_free - ret - -insert_into_free: - mov rsi, [free_list_head] ; load head - test rsi, rsi ; is list empty - jz .insert_head ; if empty, insert at head - cmp rdi, rsi ; is input smaller then head - jl .insert_head ; if smaller, insert at head - xor r8, r8 ; r9 will track the previous node -.loop: - test rsi, rsi - jz .insert_end ; if at end of list, insert at end - cmp rdi, [rsi + 8] ; compare input to next node - jg .next ; if larger, skip to next node - mov [rsi + 8], rdi ; if smaller, insert at this position - mov [rdi + 8], rdx - ret -.next: - mov r8, rsi ; update r8 to current node - mov rsi, [rsi + 8] ; update rsi to next node - jmp .loop -.insert_head: - mov rdx, [free_list_head] - mov [rdi + 8], rdx - mov [free_list_head], rdi - ret -.insert_end: - mov [r8 + 8], rdi ; update last node's next to point at rdi - ret - -sys_mmap: - mov rax, 9 - mov rsi, rdi - mov rdi, 0 - mov rdx, 3 - mov r10, 34 - mov r8, -1 - mov r9, 0 - syscall - cmp rax, -1 - je .error - ret -.error: - mov rax, 60 - mov rdi, 1 - syscall - -sys_munmap: - mov rax, 11 - syscall - cmp rax, -1 - je .error - ret -.error: - mov rax, 60 - mov rdi, 1 - syscall - -max: - cmp rdi, rsi - jae .left - mov rax, rsi - ret -.left: - mov rax, rdi - ret diff --git a/input/baseline/gc.asm b/input/baseline/gc.asm deleted file mode 100644 index d89627e..0000000 --- a/input/baseline/gc.asm +++ /dev/null @@ -1,311 +0,0 @@ -global gc_init, gc_alloc -extern printint, printstr, endl - -section .bss - alloc_list_head: resq 1 ; metadata size: 24 - free_list_head: resq 1 ; metadata size: 16 - stack_start: resq 1 - free_list_size: resq 1 - mark_count: resq 1 - -section .data - 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) - txt_start_collect: db "Running gc after ", 0 - txt_sweep_done: db " Sweep done. We now have ", 0 - txt_next_threshold: db " The next threshold is ", 0 - txt_allocated_bytes: db " allocated bytes", 0 - txt_marking_done: db " Marking done. Objects marked is ", 0 - txt_free_list_size: db " Free list size is ", 0 - -section .text -gc_init: - mov [stack_start], rsp - ret - -gc_alloc: - add rdi, 24 ; adjust for metadata size - mov rdx, [gc_bytes_allocated] - cmp rdx, [gc_trigger_threshold] - jbe .alloc ; if allocated bytes since last collect has exceeded threshold, trigger collect - push rdi - call gc_collect - pop rdi -.alloc: - add [gc_bytes_allocated], rdi ; adjust allocated bytes list - mov rsi, [free_list_head] - xor r8, r8 -.loop: - test rsi, rsi - jz .new_block ; allocate new block if at end of list - mov rdx, [rsi] - cmp rdi, rdx - jbe .use_block ; use block if object fits within block - mov r8, rsi ; load r8 with current node - mov rsi, [rsi + 8] ; load next node - jmp .loop -.new_block: - push rdi - push r8 - mov rsi, 4096 - call max ; calculate size of allocation (max(input, 4096)) - mov rdi, rax - push rdi - call sys_mmap - pop rsi - sub rsi, 16 - 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 - mov rdi, rax - call insert_into_free - pop rsi - pop r8 - pop rdi -.use_block: - cmp [rsi], rdi ; check if the block will be empty after allocation - ja .unlink_done ; if not, do not unlink - test r8, r8 ; r8 is null if node is also head - jz .unlink_head - mov rdx, [rsi + 8] ; load next node - mov [r8 + 8], rdx ; link next node to last node's next - jmp .unlink_done - dec qword [free_list_size] -.unlink_head: - mov rdx, [free_list_head] ; load head - mov rdx, [rdx + 8] ; load head.next - mov [free_list_head], rdx ; mov head.next into head - dec qword [free_list_size] -.unlink_done: - sub [rsi], rdi ; reduce available space of block by the 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 - mov byte [rax], 0 ; update mark to 0 - sub rdi, 24 - mov [rax + 8], rdi ; update metadata size to allocation size - metadata - mov rdx, [alloc_list_head] - mov [rax + 16], rdx - mov [alloc_list_head], rax ; append this allocation to the head of allocation list - lea rax, [rax + 24] ; skip past metadata for return value - ret - -gc_collect: - mov rdi, txt_start_collect - call printstr - mov rdi, [gc_bytes_allocated] - call printint - mov rdi, txt_allocated_bytes - call printstr - call endl - - call gc_mark_stack - call gc_sweep - - mov rdi, txt_sweep_done - call printstr - mov rdi, [gc_bytes_allocated] - call printint - mov rdi, txt_allocated_bytes - call printstr - call endl - - mov rdi, [gc_bytes_allocated] - shl rdi, 1 - mov rsi, 1024 * 1024 * 8 - call max - mov [gc_trigger_threshold], rax - mov qword [gc_bytes_allocated], 0 - - mov rdi, txt_next_threshold - call printstr - mov rdi, [gc_trigger_threshold] - call printint - mov rdi, txt_allocated_bytes - call printstr - call endl - - mov rdi, txt_free_list_size - call printstr - mov rdi, [free_list_size] - call printint - call endl - ret - -gc_mark_stack: - mov qword [mark_count], 0 - mov r8, rsp ; load current stack pointer - mov r9, [stack_start] ; load start of stack -.loop: - cmp r8, r9 ; have we reached end of stack? - jae .done ; yes? return - mov rdi, [r8] ; no? load the value - call gc_mark ; this might be an allocation, check - lea r8, [r8 + 8] ; next item in stack - jmp .loop -.done: - mov rdi, txt_marking_done - call printstr - mov rdi, [mark_count] - call printint - call endl - ret - -gc_mark: - test rdi, rdi - jz .done ; if stack item is null, return - mov rsi, [alloc_list_head] -.loop: - test rsi, rsi - jz .done ; return if end of list is reached - lea rdx, [rsi + 24] ; input value does not include metadata - cmp rdx, rdi - je .mark_object ; if match is found, mark the object - mov rsi, [rsi + 16] ; load next item and repeat - jmp .loop -.mark_object: - inc qword [mark_count] - mov al, [rdi] ; load mark - test al, al ; already marked? - jnz .done ; yes? return - mov byte [rdi - 24], 1 ; mark object - mov rcx, [rdi - 16] ; load object size - lea rcx, [rdi + rcx] ; end of object -.scan_object: - cmp rdi, rcx - jge .done - push rdi - mov rdi, [rdi] - call gc_mark - pop rdi - lea rdi, [rdi + 8] - jmp .scan_object -.done: - ret - -gc_sweep: - mov rdi, [alloc_list_head] - xor r8, r8 -.loop: - test rdi, rdi ; reached end of list? - jz .done ; yes? return - mov al, [rdi] - test al, al - jz .unmarked ; if unmarked, free object - mov byte [rdi], 0 ; unmark object - mov r8, rdi - mov rdi, [rdi + 16] ; next item - jmp .loop -.done: - ret -.unmarked: - mov r9, [rdi + 16] ; save address of next object in list - test r8, r8 - jz .unlink_head ; if current is head, unlink head - mov [r8 + 16], r9 ; unlink the current node by setting the previous node's next to the next node's address - jmp .unlink_done -.unlink_head: - mov [alloc_list_head], r9 ; update head node to be the next node -.unlink_done: - push r8 ; save previous node since it will also be the previous node for the next item - push r9 ; save next node - mov rdx, [rdi + 8] ; load current size - add rdx, 24 ; add metadata size back - 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 - pop rdi ; input for next iteration - pop r8 ; prev node for next iteration - jmp .loop - -insert_into_free: - mov rsi, [free_list_head] ; rsi will track the current node - test rsi, rsi - jz .insert_head ; if list is empty, insert at head - cmp rdi, rsi - jb .insert_head ; is input is smaller than head, insert at head -.loop: - mov r9, [rsi + 8] ; load next node - test r9, r9 - jz .insert_tail ; if at end of the list, insert at tail - cmp rdi, r9 - 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 [rsi + 8], rdi ; current.next = input - inc qword [free_list_size] - mov rdi, rsi - call merge - ret -.insert_head: - mov [rdi + 8], rsi - mov [free_list_head], rdi - inc qword [free_list_size] - call merge - ret -.insert_tail: - mov qword [rdi + 8], 0 ; set input.tail to null - mov [rsi + 8], rdi ; add input to current.next - inc qword [free_list_size] - mov rdi, rsi - call merge - ret - -merge: - mov rsi, [rdi + 8] - test rsi, rsi - jz .return - mov rdx, [rdi] - lea rdx, [rdi + rdx + 16] - cmp rdx, rsi - jne .return - dec qword [free_list_size] - mov rdx, [rsi] - add rdx, 16 - add [rdi], rdx - mov rdx, [rsi + 8] - mov [rdi + 8], rdx - jmp merge -.return: - ret - -sys_mmap: - mov rax, 9 - mov rsi, rdi - mov rdi, 0 - mov rdx, 3 - mov r10, 34 - mov r8, -1 - mov r9, 0 - syscall - cmp rax, -1 - je .error - ret -.error: - mov rax, 60 - mov rdi, 1 - syscall - -sys_munmap: - mov rax, 11 - syscall - cmp rax, -1 - je .error - ret -.error: - mov rax, 60 - mov rdi, 1 - syscall - -max: - cmp rdi, rsi - jae .left - mov rax, rsi - ret -.left: - mov rax, rdi - ret diff --git a/input/baseline/gc.c b/input/baseline/gc.c new file mode 100644 index 0000000..d53d6ea --- /dev/null +++ b/input/baseline/gc.c @@ -0,0 +1,277 @@ +#include +#include +#include +#include + +/* 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**)¤t; // 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; +} \ No newline at end of file diff --git a/input/baseline/gc/gc.c b/input/baseline/gc/gc.c deleted file mode 100644 index e69de29..0000000 diff --git a/input/baseline/gc/gc.h b/input/baseline/gc/gc.h deleted file mode 100644 index c5db541..0000000 --- a/input/baseline/gc/gc.h +++ /dev/null @@ -1,6 +0,0 @@ -namespace DefaultNamespace; - -public class gc_h -{ - -} \ No newline at end of file diff --git a/output/build.sh b/output/build.sh index 6055ffe..8f84c8d 100755 --- a/output/build.sh +++ b/output/build.sh @@ -1,19 +1,11 @@ #!/bin/sh - -# baseline -nasm -g -felf64 ../input/baseline/gc.asm -o gc.o -nasm -g -felf64 ../input/baseline/alloc.asm -o alloc.o +gcc -c -g -O2 -fno-stack-protector -fno-builtin ../input/baseline/gc.c -o gc.o nasm -g -felf64 ../input/baseline/str_cmp.asm -o str_cmp.o -# core nasm -g -felf64 ../input/core/str_len.asm -o str_len.o nasm -g -felf64 ../input/core/arr_size.asm -o arr_size.o nasm -g -felf64 ../input/core/itoa.asm -o itoa.o -# program nasm -g -felf64 out.asm -o out.o -# tmp -nasm -g -felf64 ../input/util.asm -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 +gcc -no-pie -nostartfiles -o out gc.o str_cmp.o str_len.o arr_size.o itoa.o out.o diff --git a/output/clean.sh b/output/clean.sh new file mode 100755 index 0000000..c81472a --- /dev/null +++ b/output/clean.sh @@ -0,0 +1,8 @@ +#!/bin/sh +rm ./arr_size.o +rm ./gc.o +rm ./itoa.o +rm ./out.o +rm ./str_cmp.o +rm ./str_len.o +rm out \ No newline at end of file