From b7b8ad857e59f5b32c85e81c23ae0b4efa25d755 Mon Sep 17 00:00:00 2001 From: Mike Lowis Date: Thu, 20 Jun 2024 10:31:31 -0400 Subject: [PATCH] reworked memory allocations and error messaging --- .gitignore | 1 + build.sh | 9 +++++++-- cerise-c.rb | 22 ++++++---------------- runtime.h | 6 ++++++ runtime/Array.c | 8 ++++---- runtime/Dict.c | 4 ++-- runtime/Error.c | 6 +++++- runtime/GC.c | 21 +++++++++++++++++++++ runtime/Object.c | 4 ++-- runtime/OpAdd.c | 5 ++--- runtime/String.c | 4 ++-- 11 files changed, 58 insertions(+), 32 deletions(-) create mode 100644 runtime/GC.c diff --git a/.gitignore b/.gitignore index b11885c..6107d0b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ cerise-c cerise-c.c *.o *.a +tags diff --git a/build.sh b/build.sh index bf84302..06606ef 100755 --- a/build.sh +++ b/build.sh @@ -1,10 +1,12 @@ #!/bin/sh -rm libruntime.a runtime/*.o +OPTLEVEL=1 + +rm -f cerise-c libruntime.a runtime/*.o for f in runtime/*.c; do printf "CC %s\n" "$f" - gcc -c -I. -O2 -o "${f%.c}.o" "$f" & + gcc -c -I. -O$OPTLEVEL -o "${f%.c}.o" "$f" & done wait printf "LIB %s\n" libruntime.a @@ -13,4 +15,7 @@ ar rcs libruntime.a runtime/*.o printf "\n" ./cerise-c.rb > cerise-c.c \ && gcc -I. -O2 -o cerise-c cerise-c.c libruntime.a \ + && size cerise-c \ + && printf "\n" \ && ./cerise-c + diff --git a/cerise-c.rb b/cerise-c.rb index 9fec3fe..6408f0a 100755 --- a/cerise-c.rb +++ b/cerise-c.rb @@ -465,13 +465,11 @@ class Parser def make_binop(loc, op, left, right) node = IR::Op.new(loc, nil, op, left, right) -# checker.infer(syms, node) node end def make_unop(loc, op, value) node = IR::Op.new(loc, nil, op, value, nil) -# checker.infer(syms, node) node end @@ -509,20 +507,8 @@ class Parser key = expression() expect("]") make_binop(loc, "[", expr, key) - -# def make_binop(loc, op, left, right) - -# call = IR::Call.new(location, nil, expr, []) -# expect("(") -# while !matches(")") -# call.args << expression() -# expect(",") if !matches(")") -# end -# expect(")") -# call end - def const_or_ident() if matches("[") array_literal() @@ -1304,15 +1290,19 @@ end ## -# Emit the Code +# Parse and Analyze ## $parser = Parser.new("cerise-c.m") $checker = TypeChecker.new($parser) $state = Codegen.init($parser) -puts "#include \n\n" +## +# Emit the Code +## + +puts "#include \n\n" $parser.syms.each do |name, val| args = val.value.args.map{|e| "Value #{e.name}" }.join(", ") puts "Value #{name}(#{args});" diff --git a/runtime.h b/runtime.h index d6f9fca..609f0db 100644 --- a/runtime.h +++ b/runtime.h @@ -213,6 +213,7 @@ Value ToString(Value val); *************************************************/ void Error(Value val); +void RuntimeError(char* s); void Assert(char* file, int lineno, Value val); @@ -245,3 +246,8 @@ Value Dict_Get(Value hash, Value key); Value Object_Get(Value object, Value key); void Object_Set(Value object, Value key, Value value); + +/* Garbage Collection + *************************************************/ + +void* GC_Allocate(size_t nbytes); diff --git a/runtime/Array.c b/runtime/Array.c index 442fb33..c0f6997 100644 --- a/runtime/Array.c +++ b/runtime/Array.c @@ -13,10 +13,10 @@ static uint64_t NextPow2(uint64_t val) { } Value MakeArray(int32_t nslots) { - Array* array = calloc(1, sizeof(Array)); + Array* array = GC_Allocate(sizeof(Array)); array->length = nslots; array->capacity = NextPow2(nslots); - array->values = calloc(nslots, sizeof(Value)); + array->values = GC_Allocate(nslots * sizeof(Value)); return (Value){ .as_uint64 = (NAN_TAG_ARRAY | (uintptr_t)array) }; } @@ -24,7 +24,7 @@ void Array_Set(Value array, int index, Value value) { Array* ary = ValueAsArray(array); if (index >= ary->length) { - Error(MakeString("array index out of bounds")); + RuntimeError("array index out of bounds"); } ary->values[index] = value; } @@ -33,7 +33,7 @@ Value Array_Get(Value array, int index) { Array* ary = ValueAsArray(array); if (index >= ary->length) { - Error(MakeString("array index out of bounds")); + RuntimeError("array index out of bounds"); } return ary->values[index]; } diff --git a/runtime/Dict.c b/runtime/Dict.c index d413869..0c895f8 100644 --- a/runtime/Dict.c +++ b/runtime/Dict.c @@ -39,7 +39,7 @@ static DictNode** FindNode(DictNode** root, DictNode* node) { } Value MakeDict(int32_t nslots) { - Dict* dict = calloc(1, sizeof(Dict)); + Dict* dict = GC_Allocate(sizeof(Dict)); return (Value){ .as_uint64 = (NAN_TAG_DICT | (uintptr_t)dict) }; } @@ -53,7 +53,7 @@ void Dict_Set(Value dictionary, Value key, Value value) Dict* dict = ValueAsDict(dictionary); DictNode** curr = FindNode(&(dict->root), &node); if (!*curr) { - DictNode* new_node = calloc(1, sizeof(DictNode)); + DictNode* new_node = GC_Allocate(sizeof(DictNode)); *new_node = node; *curr = new_node; } else { diff --git a/runtime/Error.c b/runtime/Error.c index bb99752..9bf98a3 100644 --- a/runtime/Error.c +++ b/runtime/Error.c @@ -1,6 +1,10 @@ #include "runtime.h" void Error(Value val) { - fprintf(stderr, "fatal error: %s\n", ValueAsString(val)->bytes); + RuntimeError(ValueAsString(val)->bytes); +} + +void RuntimeError(char* s) { + fprintf(stderr, "fatal error: %s\n", s); exit(1); } diff --git a/runtime/GC.c b/runtime/GC.c new file mode 100644 index 0000000..c39586c --- /dev/null +++ b/runtime/GC.c @@ -0,0 +1,21 @@ +#include "runtime.h" + +#define FIRST_GEN_SIZE ((1024*1024) / sizeof(Value)) + +Value First_Gen_Heap[FIRST_GEN_SIZE]; +Value* Heap_Next = First_Gen_Heap; +Value* Heap_End = First_Gen_Heap + FIRST_GEN_SIZE; + +void* GC_Allocate(size_t nbytes) { + size_t ncells = nbytes / sizeof(Value); + if ((nbytes - (ncells * sizeof(Value))) > 0) { + ncells++; + } + Value* obj = Heap_Next; + Heap_Next += ncells; + if (Heap_Next > Heap_End) { + fprintf(stderr, "out of memory"); + exit(1); + } + return obj; +} diff --git a/runtime/Object.c b/runtime/Object.c index 153416d..a85c6b1 100644 --- a/runtime/Object.c +++ b/runtime/Object.c @@ -10,7 +10,7 @@ Value Object_Get(Value object, Value key) } else if (IsString(object)) { result = String_Get(object, ValueAsInt(key)); } else { - Error(MakeString("object is not indexable")); + RuntimeError("object is not indexable"); } return result; } @@ -22,6 +22,6 @@ void Object_Set(Value object, Value key, Value value) } else if (IsArray(object)) { Array_Set(object, ValueAsInt(key), value); } else { - Error(MakeString("object is not assignable")); + RuntimeError("object is not assignable"); } } diff --git a/runtime/OpAdd.c b/runtime/OpAdd.c index aa126c6..1fd452b 100644 --- a/runtime/OpAdd.c +++ b/runtime/OpAdd.c @@ -11,7 +11,7 @@ Value OpAdd(Value left, Value right) { String* left_str = ValueAsString(left); String* right_str = ValueAsString(right); size_t sz = left_str->length + right_str->length; - String* str = calloc(sizeof(String) + sz + 1, 1); + String* str = GC_Allocate(sizeof(String) + sz + 1); str->length = sz; memcpy( str->bytes, @@ -23,8 +23,7 @@ Value OpAdd(Value left, Value right) { right_str->length + 1); result = (Value){ .as_uint64 = (NAN_TAG_STRING | (uint64_t)str) }; } else { - fprintf(stderr, "fatal error: addition operator used on invalid type\n"); - exit(1); + RuntimeError("addition operator used on invalid type"); } return result; } diff --git a/runtime/String.c b/runtime/String.c index d73c1ce..c2c2cc6 100644 --- a/runtime/String.c +++ b/runtime/String.c @@ -2,7 +2,7 @@ Value MakeString(char* s) { size_t sz = strlen(s); - String* str = calloc(sizeof(String) + sz + 1, 1); + String* str = GC_Allocate(sizeof(String) + sz + 1); str->length = sz; strncpy(str->bytes, s, sz+1); Value ret = (Value){ .as_uint64 = (NAN_TAG_STRING | (uint64_t)str) }; @@ -14,7 +14,7 @@ Value String_Get(Value hash, int index) { String* str = ValueAsString(hash); if (index >= str->length) { - Error(MakeString("string index out of bounds")); + RuntimeError("string index out of bounds"); } return MakeInt( str->bytes[index] ); } -- 2.54.0