mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 08:10:05 +00:00
better GC debugging, added base object for tables
This commit is contained in:
parent
a15c8d67a1
commit
fe93a0b715
@ -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) {
|
||||||
|
@ -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: {
|
||||||
|
11
src/cmem.h
11
src/cmem.h
@ -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);
|
||||||
|
31
src/cobj.c
31
src/cobj.c
@ -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);
|
||||||
|
28
src/cobj.h
28
src/cobj.h
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user