added garbage collector draft

This commit is contained in:
Francesco Cozzuto
2021-12-06 00:12:02 +01:00
parent 60b871be55
commit dbcf50c71b
21 changed files with 389 additions and 48 deletions
+10
View File
@@ -0,0 +1,10 @@
i = 0;
n = 10000000;
while i < n:
{
1 + 1 * 1;
i = i + 1;
print('\r', 100.0 * i / n, '% ');
}
+2
View File
@@ -237,6 +237,8 @@ int main(int argc, char **argv)
Object *result = run(runtime, (Error*) &error, exe, 0, NULL, NULL, 0); Object *result = run(runtime, (Error*) &error, exe, 0, NULL, NULL, 0);
// NOTE: The `builtins` pointer is invalidated now.
if(result == NULL) if(result == NULL)
{ {
fprintf(stderr, "RUNTIME ERROR: %s.\n", error.base.message); fprintf(stderr, "RUNTIME ERROR: %s.\n", error.base.message);
+1 -1
View File
@@ -21,7 +21,7 @@ typedef struct {
Runtime *runtime; Runtime *runtime;
} BuiltinsMapOjbect; } BuiltinsMapOjbect;
static const Type t_builtins_map = { static TypeObject t_builtins_map = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "builtins map", .name = "builtins map",
.size = sizeof(BuiltinsMapOjbect), .size = sizeof(BuiltinsMapOjbect),
+1 -1
View File
@@ -32,7 +32,7 @@ typedef struct {
Runtime *runtime; Runtime *runtime;
} NetworkBuiltinsMapOjbect; } NetworkBuiltinsMapOjbect;
static const Type t_builtins_map = { static TypeObject t_builtins_map = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "network builtins map", .name = "network builtins map",
.size = sizeof(NetworkBuiltinsMapOjbect), .size = sizeof(NetworkBuiltinsMapOjbect),
+169 -1
View File
@@ -17,8 +17,17 @@ struct OflowAlloc {
struct xHeap { struct xHeap {
int size; int size;
int used; int used;
int total;
void *body; void *body;
OflowAlloc *oflow; OflowAlloc *oflow;
_Bool collecting;
_Bool collection_failed;
void *old_body;
int old_used;
int old_total;
OflowAlloc *old_oflow;
Error *error;
}; };
Heap *Heap_New(int size) Heap *Heap_New(int size)
@@ -31,10 +40,12 @@ Heap *Heap_New(int size)
if(heap == NULL) if(heap == NULL)
return NULL; return NULL;
heap->total = 0;
heap->size = size; heap->size = size;
heap->used = 0; heap->used = 0;
heap->body = malloc(size); heap->body = malloc(size);
heap->oflow = 0; heap->oflow = 0;
heap->collecting = 0;
if(heap->body == NULL) if(heap->body == NULL)
{ {
@@ -67,7 +78,12 @@ void Heap_Free(Heap *heap)
free(heap); free(heap);
} }
void *Heap_Malloc(Heap *heap, const Type *type, Error *err) float Heap_GetUsagePercentage(Heap *heap)
{
return 100.0 * heap->total / heap->size;
}
void *Heap_Malloc(Heap *heap, TypeObject *type, Error *err)
{ {
void *addr = Heap_RawMalloc(heap, type->size, err); void *addr = Heap_RawMalloc(heap, type->size, err);
@@ -107,14 +123,20 @@ void *Heap_RawMalloc(Heap *heap, int size, Error *err)
heap->oflow = oflow; heap->oflow = oflow;
addr = oflow->body; addr = oflow->body;
heap->total += size;
} }
else else
{ {
int prev_used = heap->used;
if(heap->used & 7) if(heap->used & 7)
heap->used = (heap->used & ~7) + 8; heap->used = (heap->used & ~7) + 8;
addr = heap->body + heap->used; addr = heap->body + heap->used;
heap->used += size; heap->used += size;
heap->total += heap->used - prev_used;
} }
assert(((intptr_t) addr) % 8 == 0); assert(((intptr_t) addr) % 8 == 0);
@@ -125,3 +147,149 @@ void *Heap_RawMalloc(Heap *heap, int size, Error *err)
return addr; return addr;
} }
_Bool Heap_StartCollection(Heap *heap, Error *error)
{
assert(heap->collecting == 0);
void *new_body = malloc(heap->size);
if(new_body == NULL)
{
Error_Report(error, 1, "No memory");
return 0;
}
heap->old_body = heap->body;
heap->old_used = heap->used;
heap->old_total = heap->total;
heap->old_oflow = heap->oflow;
heap->total = 0;
heap->body = new_body;
heap->used = 0;
heap->oflow = NULL;
heap->collecting = 1;
heap->collection_failed = 0;
heap->error = error;
return 1;
}
_Bool Heap_StopCollection(Heap *heap)
{
assert(heap->collecting == 1);
if(heap->collection_failed)
{
free(heap->old_body);
return 0;
}
/* Call destructors here */
while(heap->old_oflow)
{
OflowAlloc *prev = heap->old_oflow->prev;
free(heap->old_oflow);
heap->old_oflow = prev;
}
free(heap->old_body);
heap->collecting = 0;
return 1;
}
void Heap_CollectExtension(void **referer, int size, Heap *heap)
{
assert(referer != NULL);
assert(heap->collecting);
void *old_location = *referer;
if(heap->collection_failed || old_location == NULL)
return;
void *new_location = Heap_RawMalloc(heap, size, heap->error);
if(new_location == NULL)
{
heap->collection_failed = 1;
return;
}
memcpy(new_location, old_location, size);
*referer = new_location;
}
void Heap_CollectReference(Object **referer, Heap *heap)
{
assert(referer != NULL);
assert(heap->collecting);
Object *old_location = *referer;
if(heap->collection_failed || old_location == NULL)
return;
Object *new_location;
if(old_location->flags & Object_STATIC)
// The object doesn't need to be moved
// since it was statically allocated.
new_location = old_location;
else if(old_location->flags & Object_MOVED)
// The object was already moved.
new_location = ((MovedObject*) old_location)->new_location;
else
{
// This object wasn't moved to
// the new heap yet.
// Get some information.
TypeObject *type = old_location->type;
int size = type->size;
// Copy the object to a new location.
{
new_location = Heap_RawMalloc(heap, size, heap->error);
if(new_location == NULL)
{
heap->collection_failed = 1;
return;
}
memcpy(new_location, old_location, size);
}
// Set the old location as moved and
// leave the reference to the new
// location.
{
old_location->flags |= Object_MOVED;
assert((int) sizeof(MovedObject) <= size);
((MovedObject*) old_location)->new_location = new_location;
}
}
// Update the referer
*referer = new_location;
// Collect the reference to the type.
if((Object*) new_location->type != new_location)
Heap_CollectReference((Object**) &new_location->type, heap);
// Collect all of the references to
// extensions allocate using the GC'd
// heap.
Object_WalkExtensions(new_location, Heap_CollectExtension, heap);
// Now collect all of the children.
Object_WalkReferences(new_location, Heap_CollectReference, heap);
}
+1 -1
View File
@@ -5,7 +5,7 @@
static _Bool to_bool(Object *obj, Error *err); static _Bool to_bool(Object *obj, Error *err);
static void print(Object *obj, FILE *fp); static void print(Object *obj, FILE *fp);
static const Type t_bool = { static TypeObject t_bool = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "bool", .name = "bool",
.size = sizeof (Object), .size = sizeof (Object),
+1 -1
View File
@@ -20,7 +20,7 @@ static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error
static int count(Object *self); static int count(Object *self);
static void print(Object *obj, FILE *fp); static void print(Object *obj, FILE *fp);
static const Type t_buffer = { static TypeObject t_buffer = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "buffer", .name = "buffer",
.size = sizeof (BufferObject), .size = sizeof (BufferObject),
+11 -1
View File
@@ -9,13 +9,15 @@ struct ClosureObject {
Object *vars; Object *vars;
}; };
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
static Object *select(Object *self, Object *key, Heap *heap, Error *err); static Object *select(Object *self, Object *key, Heap *heap, Error *err);
static const Type t_closure = { static TypeObject t_closure = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "closure", .name = "closure",
.size = sizeof(ClosureObject), .size = sizeof(ClosureObject),
.select = select, .select = select,
.walk = walk,
}; };
Object *Object_NewClosure(Object *parent, Object *new_map, Heap *heap, Error *error) Object *Object_NewClosure(Object *parent, Object *new_map, Heap *heap, Error *error)
@@ -55,3 +57,11 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *err)
return selected; return selected;
} }
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp)
{
ClosureObject *closure = (ClosureObject*) self;
callback((Object**) &closure->prev, userp);
callback(&closure->vars, userp);
}
+1 -1
View File
@@ -9,7 +9,7 @@ typedef struct {
double val; double val;
} FloatObject; } FloatObject;
static const Type t_float = { static TypeObject t_float = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "float", .name = "float",
.size = sizeof (FloatObject), .size = sizeof (FloatObject),
+1 -1
View File
@@ -11,7 +11,7 @@ typedef struct {
long long int val; long long int val;
} IntObject; } IntObject;
static const Type t_int = { static TypeObject t_int = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "int", .name = "int",
.size = sizeof (IntObject), .size = sizeof (IntObject),
+20 -1
View File
@@ -12,8 +12,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *err);
static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err); static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err);
static int count(Object *self); static int count(Object *self);
static void print(Object *obj, FILE *fp); static void print(Object *obj, FILE *fp);
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp);
static const Type t_list = { static TypeObject t_list = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "list", .name = "list",
.size = sizeof (ListObject), .size = sizeof (ListObject),
@@ -21,6 +23,8 @@ static const Type t_list = {
.insert = insert, .insert = insert,
.count = count, .count = count,
.print = print, .print = print,
.walk = walk,
.walkexts = walkexts,
}; };
static inline int calc_capacity(int mapper_size) static inline int calc_capacity(int mapper_size)
@@ -53,6 +57,21 @@ Object *Object_NewList(int capacity, Heap *heap, Error *error)
return (Object*) obj; return (Object*) obj;
} }
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp)
{
ListObject *list = (ListObject*) self;
for(int i = 0; i < list->count; i += 1)
callback(&list->vals[i], userp);
}
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp)
{
ListObject *list = (ListObject*) self;
callback((void**) &list->vals, sizeof(Object) * list->capacity, userp);
}
static Object *select(Object *self, Object *key, Heap *heap, Error *error) static Object *select(Object *self, Object *key, Heap *heap, Error *error)
{ {
assert(self != NULL); assert(self != NULL);
+25 -1
View File
@@ -14,8 +14,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *err);
static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err); static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err);
static int count(Object *self); static int count(Object *self);
static void print(Object *self, FILE *fp); static void print(Object *self, FILE *fp);
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp);
static const Type t_map = { static TypeObject t_map = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "map", .name = "map",
.size = sizeof (MapObject), .size = sizeof (MapObject),
@@ -23,6 +25,8 @@ static const Type t_map = {
.insert = insert, .insert = insert,
.count = count, .count = count,
.print = print, .print = print,
.walk = walk,
.walkexts = walkexts,
}; };
static inline int calc_capacity(int mapper_size) static inline int calc_capacity(int mapper_size)
@@ -68,6 +72,26 @@ Object *Object_NewMap(int num, Heap *heap, Error *error)
return (Object*) obj; return (Object*) obj;
} }
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp)
{
MapObject *map = (MapObject*) self;
for(int i = 0; i < map->count; i += 1)
{
callback(&map->keys[i], userp);
callback(&map->vals[i], userp);
}
}
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp)
{
MapObject *map = (MapObject*) self;
callback((void**) &map->mapper, sizeof(int) * map->mapper_size, userp);
callback((void**) &map->keys, sizeof(Object) * calc_capacity(map->mapper_size), userp);
callback((void**) &map->vals, sizeof(Object) * calc_capacity(map->mapper_size), userp);
}
static Object *select(Object *self, Object *key, Heap *heap, Error *error) static Object *select(Object *self, Object *key, Heap *heap, Error *error)
{ {
assert(self != NULL); assert(self != NULL);
+1 -1
View File
@@ -5,7 +5,7 @@
static _Bool op_eql(Object *self, Object *other); static _Bool op_eql(Object *self, Object *other);
static void print(Object *obj, FILE *fp); static void print(Object *obj, FILE *fp);
static const Type t_none = { static TypeObject t_none = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "none", .name = "none",
.size = sizeof (Object), .size = sizeof (Object),
+10 -1
View File
@@ -16,8 +16,9 @@ static Object *copy(Object *self, Heap *heap, Error *err);
static void print(Object *obj, FILE *fp); static void print(Object *obj, FILE *fp);
static char *to_string(Object *self, int *size, Heap *heap, Error *err); static char *to_string(Object *self, int *size, Heap *heap, Error *err);
static _Bool op_eql(Object *self, Object *other); static _Bool op_eql(Object *self, Object *other);
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp);
static const Type t_string = { static TypeObject t_string = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "string", .name = "string",
.atomic = ATMTP_STRING, .atomic = ATMTP_STRING,
@@ -28,6 +29,7 @@ static const Type t_string = {
.print = print, .print = print,
.to_string = to_string, .to_string = to_string,
.op_eql = op_eql, .op_eql = op_eql,
.walkexts = walkexts,
}; };
static char *to_string(Object *self, int *size, Heap *heap, Error *err) static char *to_string(Object *self, int *size, Heap *heap, Error *err)
@@ -128,3 +130,10 @@ static void print(Object *obj, FILE *fp)
fprintf(fp, "%.*s", str->size, str->body); fprintf(fp, "%.*s", str->size, str->body);
} }
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp)
{
StringObject *str = (StringObject*) self;
callback((void**) &str->body, str->size+1, userp);
}
+32 -20
View File
@@ -2,17 +2,17 @@
#include "../utils/defs.h" #include "../utils/defs.h"
#include "objects.h" #include "objects.h"
const Type t_type = { TypeObject t_type = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "type", .name = "type",
.size = sizeof (Type), .size = sizeof (TypeObject),
}; };
const char *Object_GetName(const Object *obj) const char *Object_GetName(const Object *obj)
{ {
assert(obj != NULL); assert(obj != NULL);
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
const char *name = type->name; const char *name = type->name;
@@ -21,7 +21,7 @@ const char *Object_GetName(const Object *obj)
return name; return name;
} }
const Type *Object_GetType(const Object *obj) const TypeObject *Object_GetType(const Object *obj)
{ {
assert(obj != NULL); assert(obj != NULL);
assert(obj->type != NULL); assert(obj->type != NULL);
@@ -33,7 +33,7 @@ unsigned int Object_GetSize(const Object *obj, Error *err)
assert(err != NULL); assert(err != NULL);
assert(obj != NULL); assert(obj != NULL);
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
return type->size; return type->size;
@@ -44,7 +44,7 @@ unsigned int Object_GetDeepSize(const Object *obj, Error *err)
assert(err != NULL); assert(err != NULL);
assert(obj != NULL); assert(obj != NULL);
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->deepsize == NULL) if(type->deepsize == NULL)
@@ -60,7 +60,7 @@ int Object_Hash(Object *obj, Error *err)
{ {
assert(obj != NULL); assert(obj != NULL);
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type != NULL); assert(type != NULL);
if(type->hash == NULL) if(type->hash == NULL)
@@ -77,7 +77,7 @@ Object *Object_Copy(Object *obj, Heap *heap, Error *err)
assert(err != NULL); assert(err != NULL);
assert(obj != NULL); assert(obj != NULL);
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type != NULL); assert(type != NULL);
if(type->copy == NULL) if(type->copy == NULL)
@@ -94,7 +94,7 @@ Object *Object_Call(Object *obj, Object **argv, unsigned int argc, Heap *heap, E
assert(err); assert(err);
assert(obj); assert(obj);
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->call == NULL) if(type->call == NULL)
@@ -110,7 +110,7 @@ void Object_Print(Object *obj, FILE *fp)
{ {
assert(obj != NULL); assert(obj != NULL);
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->print == NULL) if(type->print == NULL)
@@ -125,7 +125,7 @@ Object *Object_Select(Object *coll, Object *key, Heap *heap, Error *err)
assert(key); assert(key);
assert(coll); assert(coll);
const Type *type = Object_GetType(coll); const TypeObject *type = Object_GetType(coll);
assert(type); assert(type);
if(type->select == NULL) if(type->select == NULL)
@@ -143,7 +143,7 @@ Object *Object_Delete(Object *coll, Object *key, Heap *heap, Error *err)
assert(key); assert(key);
assert(coll); assert(coll);
const Type *type = Object_GetType(coll); const TypeObject *type = Object_GetType(coll);
assert(type); assert(type);
if(type->delete == NULL) if(type->delete == NULL)
@@ -161,7 +161,7 @@ _Bool Object_Insert(Object *coll, Object *key, Object *val, Heap *heap, Error *e
assert(key); assert(key);
assert(coll); assert(coll);
const Type *type = Object_GetType(coll); const TypeObject *type = Object_GetType(coll);
assert(type); assert(type);
if(type->insert == NULL) if(type->insert == NULL)
@@ -178,7 +178,7 @@ int Object_Count(Object *coll, Error *err)
assert(err); assert(err);
assert(coll); assert(coll);
const Type *type = Object_GetType(coll); const TypeObject *type = Object_GetType(coll);
assert(type); assert(type);
if(type->count == NULL) if(type->count == NULL)
@@ -195,7 +195,7 @@ Object *Object_Next(Object *iter, Heap *heap, Error *err)
assert(err); assert(err);
assert(iter); assert(iter);
const Type *type = Object_GetType(iter); const TypeObject *type = Object_GetType(iter);
assert(type); assert(type);
if(type->next == NULL) if(type->next == NULL)
@@ -212,7 +212,7 @@ Object *Object_Prev(Object *iter, Heap *heap, Error *err)
assert(err); assert(err);
assert(iter); assert(iter);
const Type *type = Object_GetType(iter); const TypeObject *type = Object_GetType(iter);
assert(type); assert(type);
if(type->prev == NULL) if(type->prev == NULL)
@@ -263,7 +263,7 @@ long long int Object_ToInt(Object *obj, Error *err)
return 0; return 0;
} }
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->to_int == NULL) if(type->to_int == NULL)
@@ -286,7 +286,7 @@ _Bool Object_ToBool(Object *obj, Error *err)
return 0; return 0;
} }
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->to_bool == NULL) if(type->to_bool == NULL)
@@ -309,7 +309,7 @@ double Object_ToFloat(Object *obj, Error *err)
return 0; return 0;
} }
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->to_float == NULL) if(type->to_float == NULL)
@@ -332,7 +332,7 @@ const char *Object_ToString(Object *obj, int *size, Heap *heap, Error *err)
return NULL; return NULL;
} }
const Type *type = Object_GetType(obj); const TypeObject *type = Object_GetType(obj);
assert(type); assert(type);
if(type->to_string == NULL) if(type->to_string == NULL)
@@ -361,3 +361,15 @@ _Bool Object_Compare(Object *obj1, Object *obj2, Error *error)
return obj1->type->op_eql(obj1, obj2); return obj1->type->op_eql(obj1, obj2);
} }
void Object_WalkReferences(Object *parent, void (*callback)(Object **referer, void *userp), void *userp)
{
if(parent->type->walk != NULL)
parent->type->walk(parent, callback, userp);
}
void Object_WalkExtensions(Object *parent, void (*callback)(void **referer, unsigned int size, void *userp), void *userp)
{
if(parent->type->walkexts != NULL)
parent->type->walkexts(parent, callback, userp);
}
+22 -6
View File
@@ -4,15 +4,20 @@
#include <stdio.h> #include <stdio.h>
#include "../utils/error.h" #include "../utils/error.h"
typedef struct Type Type; typedef struct TypeObject TypeObject;
typedef struct Object Object; typedef struct Object Object;
typedef struct xHeap Heap; typedef struct xHeap Heap;
struct Object { struct Object {
const Type *type; TypeObject *type;
unsigned int flags; unsigned int flags;
}; };
typedef struct {
Object base;
Object *new_location;
} MovedObject;
typedef enum { typedef enum {
ATMTP_NOTATOMIC = 0, ATMTP_NOTATOMIC = 0,
ATMTP_INT, ATMTP_INT,
@@ -21,7 +26,7 @@ typedef enum {
ATMTP_STRING, ATMTP_STRING,
} AtomicType; } AtomicType;
struct Type { struct TypeObject {
Object base; Object base;
@@ -57,18 +62,27 @@ struct Type {
}; };
_Bool (*op_eql)(Object *self, Object *other); _Bool (*op_eql)(Object *self, Object *other);
// All.
void (*walk) (Object *self, void (*callback)(Object **referer, void *userp), void *userp);
void (*walkexts)(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp);
}; };
enum { enum {
Object_STATIC = 1, Object_STATIC = 1,
Object_MOVED = 2,
}; };
Heap* Heap_New(int size); Heap* Heap_New(int size);
void Heap_Free(Heap *heap); void Heap_Free(Heap *heap);
void* Heap_Malloc (Heap *heap, const Type *type, Error *err); void* Heap_Malloc (Heap *heap, TypeObject *type, Error *err);
void* Heap_RawMalloc(Heap *heap, int size, Error *err); void* Heap_RawMalloc(Heap *heap, int size, Error *err);
_Bool Heap_StartCollection(Heap *heap, Error *error);
_Bool Heap_StopCollection(Heap *heap);
void Heap_CollectReference(Object **referer, Heap *heap);
float Heap_GetUsagePercentage(Heap *heap);
const Type* Object_GetType(const Object *obj); const TypeObject* Object_GetType(const Object *obj);
const char* Object_GetName(const Object *obj); const char* Object_GetName(const Object *obj);
unsigned int Object_GetSize(const Object *obj, Error *err); unsigned int Object_GetSize(const Object *obj, Error *err);
unsigned int Object_GetDeepSize(const Object *obj, Error *err); unsigned int Object_GetDeepSize(const Object *obj, Error *err);
@@ -83,6 +97,8 @@ _Bool Object_Insert(Object *coll, Object *key, Object *val, Heap *heap, Error
int Object_Count (Object *coll, Error *err); int Object_Count (Object *coll, Error *err);
Object* Object_Next (Object *iter, Heap *heap, Error *err); Object* Object_Next (Object *iter, Heap *heap, Error *err);
Object* Object_Prev (Object *iter, Heap *heap, Error *err); Object* Object_Prev (Object *iter, Heap *heap, Error *err);
void Object_WalkReferences(Object *parent, void (*callback)(Object **referer, void *userp), void *userp);
void Object_WalkExtensions(Object *parent, void (*callback)(void **referer, unsigned int size, void *userp), void *userp);
Object* Object_NewMap(int num, Heap *heap, Error *error); Object* Object_NewMap(int num, Heap *heap, Error *error);
Object* Object_NewList(int capacity, Heap *heap, Error *error); Object* Object_NewList(int capacity, Heap *heap, Error *error);
@@ -108,5 +124,5 @@ const char *Object_ToString(Object *obj, int *size, Heap *heap, Error *err);
_Bool Object_Compare(Object *obj1, Object *obj2, Error *error); _Bool Object_Compare(Object *obj1, Object *obj2, Error *error);
extern const Type t_type; extern TypeObject t_type;
#endif #endif
+9 -1
View File
@@ -13,14 +13,22 @@ typedef struct {
} FunctionObject; } FunctionObject;
static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error); static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error);
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
static const Type t_func = { static TypeObject t_func = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "function", .name = "function",
.size = sizeof (FunctionObject), .size = sizeof (FunctionObject),
.call = call, .call = call,
.walk = walk,
}; };
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp)
{
FunctionObject *func = (FunctionObject*) self;
callback(&func->closure, userp);
}
static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error) static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error)
{ {
assert(self != NULL); assert(self != NULL);
+1 -1
View File
@@ -13,7 +13,7 @@ typedef struct {
static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error); static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error);
static const Type t_nfunc = { static TypeObject t_nfunc = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC }, .base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "native function", .name = "native function",
.size = sizeof (NativeFunctionObject), .size = sizeof (NativeFunctionObject),
+43 -1
View File
@@ -1032,6 +1032,33 @@ static _Bool step(Runtime *runtime, Error *error)
return 1; return 1;
} }
static _Bool collect(Runtime *runtime, Error *error)
{
Frame *frame = runtime->frame;
if(!Heap_StartCollection(runtime->heap, error))
return 0;
Heap_CollectReference(&runtime->builtins, runtime->heap);
while(frame)
{
Heap_CollectReference(&frame->locals, runtime->heap);
Heap_CollectReference(&frame->closure, runtime->heap);
frame = frame->prev;
}
for(unsigned int i = 0; i < Stack_Size(runtime->stack); i += 1)
{
Object **ref = (Object**) Stack_TopRef(runtime->stack, -i);
assert(ref != NULL);
Heap_CollectReference(ref, runtime->heap);
}
return Heap_StopCollection(runtime->heap);
}
Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *closure, Object **argv, int argc) Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *closure, Object **argv, int argc)
{ {
assert(runtime != NULL); assert(runtime != NULL);
@@ -1086,14 +1113,29 @@ Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *
Error_Report(error, 0, "Forced abortion"); Error_Report(error, 0, "Forced abortion");
else else
while(step(runtime, error)) while(step(runtime, error))
{
if(!runtime->callback_addr(runtime, runtime->callback_userp)) if(!runtime->callback_addr(runtime, runtime->callback_userp))
{ {
Error_Report(error, 0, "Forced abortion"); Error_Report(error, 0, "Forced abortion");
break; break;
} }
//printf("%2.2f%% percent.\n", Heap_GetUsagePercentage(runtime->heap));
if(Heap_GetUsagePercentage(runtime->heap) > 100)
if(!collect(runtime, error))
break;
}
} }
else else
while(step(runtime, error)); while(step(runtime, error))
{
if(Heap_GetUsagePercentage(runtime->heap) > 100)
if(!collect(runtime, error))
break;
//printf("%2.2f%% percent.\n", Heap_GetUsagePercentage(runtime->heap));
}
// This is what the function will return. // This is what the function will return.
Object *result = NULL; Object *result = NULL;
+20
View File
@@ -54,6 +54,26 @@ void *Stack_Top(Stack *s, int n)
return s->body[s->used + n - 1]; return s->body[s->used + n - 1];
} }
void **Stack_TopRef(Stack *s, int n)
{
assert(n <= 0);
if(Stack_IsReadOnlyCopy(s))
return NULL;
// Remove readonly bit.
s = unmark(s);
if(s->used == 0)
return NULL;
if((int) s->used + n - 1 < 0)
return NULL;
return &s->body[s->used + n - 1];
}
_Bool Stack_Pop(Stack *s, unsigned int n) _Bool Stack_Pop(Stack *s, unsigned int n)
{ {
if(Stack_IsReadOnlyCopy(s)) if(Stack_IsReadOnlyCopy(s))
+1
View File
@@ -8,6 +8,7 @@ _Bool Stack_Push(Stack *s, void *item);
void Stack_Free(Stack *s); void Stack_Free(Stack *s);
unsigned int Stack_Size(Stack *s); unsigned int Stack_Size(Stack *s);
Stack *Stack_Copy(Stack *s, _Bool readonly); Stack *Stack_Copy(Stack *s, _Bool readonly);
void **Stack_TopRef(Stack *s, int n);
unsigned int Stack_Capacity(Stack *s); unsigned int Stack_Capacity(Stack *s);
_Bool Stack_IsReadOnlyCopy(Stack *s); _Bool Stack_IsReadOnlyCopy(Stack *s);
#endif #endif