Merge branch 'concept/memory-safety' into concept/ast-design

This commit is contained in:
servostar 2024-05-08 19:19:32 +00:00 committed by GitHub
commit 2d411e3b7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 143 additions and 1 deletions

View File

@ -4,6 +4,7 @@
#include <stdlib.h>
#include <sys/log.h>
#include <assert.h>
#include <gc/gc.h>
AST_NODE_PTR AST_new_node(enum AST_SyntaxElement_t kind, const char* value) {
DEBUG("creating new AST node: %d \"%s\"", kind, value);

113
src/gc/gc.c Normal file
View File

@ -0,0 +1,113 @@
//
// Created by servostar on 5/7/24.
//
#include <gc/gc.h>
#include <sys/log.h>
#include <string.h>
#undef malloc
#undef free
#undef realloc
#define GC_HEAP_PREALLOC_CNT 10
typedef struct GC_Heap_Statistics_t {
size_t bytes;
} GC_Heap_Statistics;
static struct GC_Heap_t {
RAW_PTR* blocks;
size_t cap;
size_t len;
GC_Heap_Statistics statistics;
} GC_GLOBAL_HEAP;
static void __GC_teardown(void) {
INFO("Used %ld bytes in total", GC_GLOBAL_HEAP.statistics.bytes);
if (GC_GLOBAL_HEAP.blocks == NULL) {
return;
}
for (size_t i = 0; i < GC_GLOBAL_HEAP.len; i++) {
free(GC_GLOBAL_HEAP.blocks[i]);
}
free(GC_GLOBAL_HEAP.blocks);
GC_GLOBAL_HEAP.blocks = NULL;
}
static void __GC_check_init(void) {
if (GC_GLOBAL_HEAP.blocks == NULL) {
GC_GLOBAL_HEAP.cap = GC_HEAP_PREALLOC_CNT;
const size_t bytes = sizeof(RAW_PTR) * GC_GLOBAL_HEAP.cap;
GC_GLOBAL_HEAP.blocks = malloc(bytes);
GC_GLOBAL_HEAP.len = 0;
}
}
void GC_init(void) {
atexit(__GC_teardown);
}
static void __GC_check_overflow(void) {
if (GC_GLOBAL_HEAP.len >= GC_GLOBAL_HEAP.cap) {
GC_GLOBAL_HEAP.cap += GC_HEAP_PREALLOC_CNT;
const size_t bytes = sizeof(RAW_PTR) * GC_GLOBAL_HEAP.cap;
GC_GLOBAL_HEAP.blocks = realloc(GC_GLOBAL_HEAP.blocks, bytes);
}
}
RAW_PTR GC_malloc(const size_t bytes) {
const RAW_PTR ptr = malloc(bytes);
if (ptr == NULL) {
FATAL("unable to allocate memory");
}
__GC_check_init();
__GC_check_overflow();
GC_GLOBAL_HEAP.blocks[GC_GLOBAL_HEAP.len++] = ptr;
GC_GLOBAL_HEAP.statistics.bytes += bytes;
return ptr;
}
static void __GC_swap_ptr(RAW_PTR old, RAW_PTR new) {
for (size_t i = 0; i < GC_GLOBAL_HEAP.len; i++) {
if (GC_GLOBAL_HEAP.blocks[i] == old) {
GC_GLOBAL_HEAP.blocks[i] = new;
}
}
}
RAW_PTR GC_realloc(RAW_PTR ptr, size_t bytes) {
const RAW_PTR new_ptr = (RAW_PTR) realloc(ptr, bytes);
if (new_ptr == NULL) {
FATAL("unable to reallocate memory");
}
__GC_swap_ptr(ptr, new_ptr);
return new_ptr;
}
void GC_free(RAW_PTR ptr) {
DEBUG("freeing memory: %p", ptr);
for (size_t i = 0; i < GC_GLOBAL_HEAP.len; i++) {
if (ptr == GC_GLOBAL_HEAP.blocks[i]) {
free(GC_GLOBAL_HEAP.blocks[i]);
GC_GLOBAL_HEAP.len--;
memcpy(&GC_GLOBAL_HEAP.blocks[i], &GC_GLOBAL_HEAP.blocks[i + 1], GC_GLOBAL_HEAP.len - i);
}
}
}

24
src/gc/gc.h Normal file
View File

@ -0,0 +1,24 @@
//
// Created by servostar on 5/7/24.
//
#ifndef GC_H
#define GC_H
#include <stdlib.h>
#define malloc GC_malloc
#define free GC_free
#define realloc GC_realloc
typedef void* RAW_PTR;
void GC_init(void);
RAW_PTR GC_malloc(size_t bytes);
RAW_PTR GC_realloc(RAW_PTR ptr, size_t bytes);
void GC_free(RAW_PTR ptr);
#endif //GC_H

View File

@ -2,6 +2,7 @@
%{
#include <yacc/parser.tab.h>
#include <sys/log.h>
#include <gc/gc.h>
int yyLineNumber = 1;
int yylex();

View File

@ -2,6 +2,7 @@
#include <sys/log.h>
#include <yacc/parser.tab.h>
#include <ast/ast.h>
#include <gc/gc.h>
#define LOG_LEVEL LOG_LEVEL_DEBUG
@ -47,6 +48,8 @@ void setup(void)
// actual setup
AST_init();
GC_init();
DEBUG("finished starting up gemstone...");
}

View File

@ -2,7 +2,7 @@
#define _SYS_ERR_H_
#include <stdio.h>
#include <string.h>
#include <gc/gc.h>
#define LOG_DEFAULT_STREAM stderr