better GC debugging, added base object for tables

This commit is contained in:
CPunch 2020-11-02 22:32:39 -06:00
parent a15c8d67a1
commit fe93a0b715
7 changed files with 70 additions and 13 deletions

View File

@ -1,9 +1,12 @@
#include "cbaselib.h" #include "cbaselib.h"
#include "cvalue.h" #include "cvalue.h"
#include "cobj.h" #include "cobj.h"
#include "cmem.h"
void cosmoB_loadlibrary(CState *state) { void cosmoB_loadlibrary(CState *state) {
cosmoM_freezeGC(state);
cosmoV_register(state, "print", cosmoV_newObj(cosmoO_newCFunction(state, cosmoB_print))); cosmoV_register(state, "print", cosmoV_newObj(cosmoO_newCFunction(state, cosmoB_print)));
cosmoM_unfreezeGC(state);
} }
int cosmoB_print(CState *state, int nargs, CValue *args) { int cosmoB_print(CState *state, int nargs, CValue *args) {

View File

@ -20,6 +20,11 @@ void *cosmoM_reallocate(CState* state, void *buf, size_t oldSize, size_t newSize
if (!(cosmoM_isFrozen(state)) && newSize > oldSize) { if (!(cosmoM_isFrozen(state)) && newSize > oldSize) {
cosmoM_collectGarbage(state); cosmoM_collectGarbage(state);
} }
#ifdef GC_DEBUG
else {
printf("GC event ignored! state frozen! [%d]\n", state->freezeGC);
}
#endif
#else #else
// if the state isn't frozen && we've reached the GC event // if the state isn't frozen && we've reached the GC event
if (!(cosmoM_isFrozen(state)) && state->allocatedBytes > state->nextGC) { if (!(cosmoM_isFrozen(state)) && state->allocatedBytes > state->nextGC) {
@ -75,12 +80,12 @@ void markArray(CState *state, CValueArray *array) {
void blackenObject(CState *state, CObj *obj) { void blackenObject(CState *state, CObj *obj) {
switch (obj->type) { switch (obj->type) {
case COBJ_STRING: case COBJ_STRING:
case COBJ_TABLE: // TODO: when metatables are added, make sure they're marked
case COBJ_CFUNCTION: case COBJ_CFUNCTION:
// stubbed // stubbed
break; break;
case COBJ_UPVALUE: { case COBJ_UPVALUE: {
markValue(state, ((CObjUpval*)obj)->closed); markValue(state, ((CObjUpval*)obj)->closed);
break; break;
} }
case COBJ_FUNCTION: { case COBJ_FUNCTION: {

View File

@ -28,11 +28,22 @@
#define cosmoM_isFrozen(state) \ #define cosmoM_isFrozen(state) \
state->freezeGC > 0 state->freezeGC > 0
// if debugging, print the locations of when the state is frozen/unfrozen
#ifdef GC_DEBUG
#define cosmoM_freezeGC(state) \
state->freezeGC++; \
printf("freezing state at %s:%d [%d]\n", __FILE__, __LINE__, state->freezeGC)
#define cosmoM_unfreezeGC(state) \
state->freezeGC--; \
printf("unfreezing state at %s:%d [%d]\n", __FILE__, __LINE__, state->freezeGC)
#else
#define cosmoM_freezeGC(state) \ #define cosmoM_freezeGC(state) \
state->freezeGC++ state->freezeGC++
#define cosmoM_unfreezeGC(state) \ #define cosmoM_unfreezeGC(state) \
state->freezeGC-- state->freezeGC--
#endif
COSMO_API void *cosmoM_reallocate(CState* state, void *buf, size_t oldSize, size_t newSize); COSMO_API void *cosmoM_reallocate(CState* state, void *buf, size_t oldSize, size_t newSize);
COSMO_API void cosmoM_collectGarbage(CState* state); COSMO_API void cosmoM_collectGarbage(CState* state);

View File

@ -42,6 +42,12 @@ void cosmoO_freeObject(CState *state, CObj* obj) {
cosmoM_free(state, CObjString, objStr); cosmoM_free(state, CObjString, objStr);
break; break;
} }
case COBJ_TABLE: {
CObjTable *objTbl = (CObjTable*)obj;
cosmoT_clearTable(state, &objTbl->tbl);
cosmoM_free(state, CObjTable, objTbl);
break;
}
case COBJ_UPVALUE: { case COBJ_UPVALUE: {
cosmoM_free(state, CObjUpval, obj); cosmoM_free(state, CObjUpval, obj);
break; break;
@ -72,9 +78,21 @@ bool cosmoO_equalObject(CObj* obj1, CObj* obj2) {
switch (obj1->type) { switch (obj1->type) {
case COBJ_STRING: case COBJ_STRING:
return obj1 == obj2; // compare pointers because we already intern all strings :) return obj1 == obj2; // compare pointers because we already intern all strings :)
default: case COBJ_CFUNCTION: {
return false; // they're some unknown type, probably malformed :( CObjCFunction *cfunc1 = (CObjCFunction*)obj1;
CObjCFunction *cfunc2 = (CObjCFunction*)obj2;
return cfunc1->cfunc == cfunc2->cfunc;
} }
default:
return false;
}
}
CObjTable *cosmoO_newTable(CState *state) {
CObjTable *tbl = (CObjTable*)cosmoO_allocateObject(state, sizeof(CObjTable), COBJ_TABLE);
cosmoT_initTable(state, &tbl->tbl, 8); // start the table at 8
return tbl;
} }
CObjFunction *cosmoO_newFunction(CState *state) { CObjFunction *cosmoO_newFunction(CState *state) {
@ -170,6 +188,11 @@ CObjString *cosmoO_toString(CState *state, CObj *val) {
CObjFunction *func = (CObjFunction*)val; CObjFunction *func = (CObjFunction*)val;
return func->name != NULL ? func->name : cosmoO_copyString(state, UNNAMEDCHUNK, strlen(UNNAMEDCHUNK)); return func->name != NULL ? func->name : cosmoO_copyString(state, UNNAMEDCHUNK, strlen(UNNAMEDCHUNK));
} }
case COBJ_TABLE: { // TODO: maybe not safe??
char buf[64];
int sz = sprintf(buf, "<tbl> %p", val) + 1; // +1 for the null character
return cosmoO_copyString(state, buf, sz);
}
default: default:
return cosmoO_copyString(state, "<unkn>", 6); return cosmoO_copyString(state, "<unkn>", 6);
} }
@ -182,6 +205,10 @@ void printObject(CObj *o) {
printf("\"%.*s\"", objStr->length, objStr->str); printf("\"%.*s\"", objStr->length, objStr->str);
break; break;
} }
case COBJ_TABLE: {
printf("<tbl> %p", o);
return;
}
case COBJ_UPVALUE: { case COBJ_UPVALUE: {
CObjUpval *upval = (CObjUpval*)o; CObjUpval *upval = (CObjUpval*)o;
printf("<upvalue %p> -> ", upval->val); printf("<upvalue %p> -> ", upval->val);

View File

@ -4,15 +4,18 @@
#include "cosmo.h" #include "cosmo.h"
#include "cchunk.h" #include "cchunk.h"
#include "cvalue.h" #include "cvalue.h"
#include "ctable.h"
typedef struct CState CState; typedef struct CState CState;
typedef enum { typedef enum {
COBJ_STRING, COBJ_STRING,
COBJ_UPVALUE, COBJ_TABLE,
COBJ_FUNCTION, COBJ_FUNCTION,
COBJ_CFUNCTION, COBJ_CFUNCTION,
COBJ_CLOSURE // internal use
COBJ_CLOSURE,
COBJ_UPVALUE,
} CObjType; } CObjType;
#define CommonHeader CObj obj; #define CommonHeader CObj obj;
@ -32,12 +35,11 @@ typedef struct CObjString {
uint32_t hash; // for hashtable lookup uint32_t hash; // for hashtable lookup
} CObjString; } CObjString;
typedef struct CObjUpval { typedef struct CObjTable {
CommonHeader; // "is a" CObj CommonHeader; // "is a" CObj
CValue *val; CTable tbl;
CValue closed; //struct CObjTable *meta; // metatable, used to describe table behavior
struct CObjUpval *next; } CObjTable;
} CObjUpval;
typedef struct CObjFunction { typedef struct CObjFunction {
CommonHeader; // "is a" CObj CommonHeader; // "is a" CObj
@ -53,18 +55,27 @@ typedef struct CObjCFunction {
} CObjCFunction; } CObjCFunction;
typedef struct CObjClosure { typedef struct CObjClosure {
CommonHeader; CommonHeader; // "is a" CObj
CObjFunction *function; CObjFunction *function;
CObjUpval **upvalues; CObjUpval **upvalues;
int upvalueCount; int upvalueCount;
} CObjClosure; } CObjClosure;
typedef struct CObjUpval {
CommonHeader; // "is a" CObj
CValue *val;
CValue closed;
struct CObjUpval *next;
} CObjUpval;
#define IS_STRING(x) isObjType(x, COBJ_STRING) #define IS_STRING(x) isObjType(x, COBJ_STRING)
#define IS_TABLE(x) isObjType(x, COBJ_TABLE)
#define IS_FUNCTION(x) isObjType(x, COBJ_FUNCTION) #define IS_FUNCTION(x) isObjType(x, COBJ_FUNCTION)
#define IS_CFUNCTION(x) isObjType(x, COBJ_CFUNCTION) #define IS_CFUNCTION(x) isObjType(x, COBJ_CFUNCTION)
#define IS_CLOSURE(x) isObjType(x, COBJ_CLOSURE) #define IS_CLOSURE(x) isObjType(x, COBJ_CLOSURE)
#define cosmoV_readString(x) ((CObjString*)cosmoV_readObj(x)) #define cosmoV_readString(x) ((CObjString*)cosmoV_readObj(x))
#define cosmoV_readTable(x) ((CObjTable*)cosmoV_readObj(x))
#define cosmoV_readFunction(x) ((CObjFunction*)cosmoV_readObj(x)) #define cosmoV_readFunction(x) ((CObjFunction*)cosmoV_readObj(x))
#define cosmoV_readCFunction(x) (((CObjCFunction*)cosmoV_readObj(x))->cfunc) #define cosmoV_readCFunction(x) (((CObjCFunction*)cosmoV_readObj(x))->cfunc)
#define cosmoV_readClosure(x) ((CObjClosure*)cosmoV_readObj(x)) #define cosmoV_readClosure(x) ((CObjClosure*)cosmoV_readObj(x))
@ -78,6 +89,7 @@ void cosmoO_freeObject(CState *state, CObj* obj);
bool cosmoO_equalObject(CObj* obj1, CObj* obj2); bool cosmoO_equalObject(CObj* obj1, CObj* obj2);
CObjTable *cosmoO_newTable(CState *state);
CObjFunction *cosmoO_newFunction(CState *state); CObjFunction *cosmoO_newFunction(CState *state);
CObjCFunction *cosmoO_newCFunction(CState *state, CosmoCFunction func); CObjCFunction *cosmoO_newCFunction(CState *state, CosmoCFunction func);
CObjClosure *cosmoO_newClosure(CState *state, CObjFunction *func); CObjClosure *cosmoO_newClosure(CState *state, CObjFunction *func);

View File

@ -55,10 +55,10 @@ void cosmoV_freeState(CState *state) {
void cosmoV_register(CState *state, const char *identifier, CValue val) { void cosmoV_register(CState *state, const char *identifier, CValue val) {
// we push the values so the garbage collector can find them // we push the values so the garbage collector can find them
cosmoV_pushValue(state, cosmoV_newObj(cosmoO_copyString(state, identifier, strlen(identifier))));
cosmoV_pushValue(state, val); cosmoV_pushValue(state, val);
cosmoV_pushValue(state, cosmoV_newObj(cosmoO_copyString(state, identifier, strlen(identifier))));
CValue *oldVal = cosmoT_insert(state, &state->globals, *cosmoV_getTop(state, 1)); CValue *oldVal = cosmoT_insert(state, &state->globals, *cosmoV_getTop(state, 0));
*oldVal = val; *oldVal = val;
cosmoV_setTop(state, 2); // pops the 2 values off the stack cosmoV_setTop(state, 2); // pops the 2 values off the stack

View File

@ -90,7 +90,6 @@ static void runFile(const char* fileName) {
char* script = readFile(fileName); char* script = readFile(fileName);
CState *state = cosmoV_newState(); CState *state = cosmoV_newState();
interpret(state, script); interpret(state, script);
cosmoV_freeState(state); cosmoV_freeState(state);