Compare commits

...

8 Commits

Author SHA1 Message Date
bfde2d25cf Merge branch 'main' into error-handling 2023-08-30 12:03:01 -05:00
97d40765ce more refactoring; things seem to work fine
all example scripts run fine with GC_STRESS enabled
2023-08-30 12:00:52 -05:00
37e4653d40 don't freezeGC during GC cycle 2023-08-29 23:32:25 -05:00
1ae473383d fix more GC bugs 2023-08-29 23:21:52 -05:00
6ed5589513 fix cparse.c gc bug 2023-08-29 23:01:47 -05:00
1408a07b23 fix this test script 2023-08-29 16:51:04 -05:00
27818b3788 cosmoV_throw() now resets the vm stack as well
also a minor GC bug in cosmoO_newError was fixed.

i'm going to try to phase out cosmoM_freezeGC & friends
since that would cause hell with this new
error handling solution. the only thing still using it is the GC.
2023-08-29 16:48:38 -05:00
409937c1fa fix vm.collect()
we don't freeze the vm on entry to C functions now
2023-08-26 15:03:56 -05:00
14 changed files with 66 additions and 143 deletions

View File

@@ -6,7 +6,7 @@ end
// instance of test
let obj = test()
test.__index = function(self, key)
test.__index = func(self, key)
print("__index called!")
if (key == "lol") then
return 9001

View File

@@ -30,7 +30,6 @@ int cosmoB_assert(CState *state, int nargs, CValue *args)
{
if (nargs < 1 || nargs > 2) {
cosmoV_error(state, "assert() expected 1 or 2 arguments, got %d!", nargs);
return 0; // nothing pushed onto the stack to return
}
if (!IS_BOOLEAN(args[0]) || (nargs == 2 && !IS_STRING(args[1]))) {
@@ -40,7 +39,6 @@ int cosmoB_assert(CState *state, int nargs, CValue *args)
} else {
cosmoV_typeError(state, "assert()", "<boolean>", "%s", cosmoV_typeStr(args[0]));
}
return 0;
}
if (!cosmoV_readBoolean(args[0])) // expression passed was false, error!
@@ -53,7 +51,6 @@ int cosmoB_type(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "type() expected 1 argument, got %d!", nargs);
return 0;
}
// push the type string to the stack
@@ -65,7 +62,6 @@ int cosmoB_pcall(CState *state, int nargs, CValue *args)
{
if (nargs < 1) {
cosmoV_error(state, "pcall() expected at least 1 argument!");
return 0;
}
// call the passed callable, the passed arguments are already in the
@@ -81,7 +77,6 @@ int cosmoB_tonumber(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "tonumber() expected 1 argument, got %d!", nargs);
return 0;
}
cosmoV_pushNumber(state, cosmoV_toNumber(state, args[0]));
@@ -90,10 +85,8 @@ int cosmoB_tonumber(CState *state, int nargs, CValue *args)
int cosmoB_tostring(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
if (nargs != 1)
cosmoV_error(state, "tostring() expected 1 argument, got %d!", nargs);
return 0;
}
cosmoV_pushRef(state, (CObj *)cosmoV_toString(state, args[0]));
return 1;
@@ -103,12 +96,10 @@ int cosmoB_loadstring(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "loadstring() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_STRING(args[0])) {
cosmoV_typeError(state, "loadstring()", "<string>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
CObjString *str = cosmoV_readString(args[0]);
@@ -122,12 +113,10 @@ int cosmoB_error(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "error() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_STRING(args[0])) {
cosmoV_typeError(state, "error()", "<string>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
cosmoV_error(state, "%s", cosmoV_readCString(args[0]));
@@ -176,10 +165,8 @@ int cosmoB_osetProto(CState *state, int nargs, CValue *args)
int cosmoB_ogetProto(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
if (nargs != 1)
cosmoV_error(state, "Expected 1 argument, got %d!", nargs);
return 0;
}
cosmoV_pushRef(state, (CObj *)cosmoV_readObject(args[0])->_obj.proto); // just return the proto
@@ -190,13 +177,11 @@ int cosmoB_oisChild(CState *state, int nargs, CValue *args)
{
if (nargs != 2) {
cosmoV_error(state, "object.ischild() expected 2 arguments, got %d!", nargs);
return 0;
}
if (!IS_REF(args[0]) || !IS_OBJECT(args[1])) {
cosmoV_typeError(state, "object.ischild()", "<reference obj>, <object>", "%s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
return 0;
}
CObj *obj = cosmoV_readRef(args[0]);
@@ -255,12 +240,10 @@ int cosmoB_osRead(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "os.read() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_STRING(args[0])) {
cosmoV_typeError(state, "os.read()", "<string>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
CObjString *str = cosmoV_readString(args[0]);
@@ -301,7 +284,6 @@ int cosmoB_osTime(CState *state, int nargs, CValue *args)
struct timeval time;
if (nargs > 0) {
cosmoV_error(state, "os.time() expected no arguments, got %d!", nargs);
return 0;
}
gettimeofday(&time, NULL);
@@ -314,12 +296,10 @@ int cosmoB_osSystem(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "os.system() expects 1 argument, got %d!", nargs);
return 0;
}
if (!IS_STRING(args[0])) {
cosmoV_typeError(state, "os.system()", "<string>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
// run the command and return the exit code
@@ -354,7 +334,6 @@ int cosmoB_sSub(CState *state, int nargs, CValue *args)
if (!IS_STRING(args[0]) || !IS_NUMBER(args[1])) {
cosmoV_typeError(state, "string.sub()", "<string>, <number>", "%s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
return 0;
}
CObjString *str = cosmoV_readString(args[0]);
@@ -364,7 +343,6 @@ int cosmoB_sSub(CState *state, int nargs, CValue *args)
if (indx < 0 || indx >= str->length) {
cosmoV_error(state, "string.sub() expected index to be 0-%d, got %d!", str->length - 1,
indx);
return 0;
}
cosmoV_pushLString(state, str->str + ((int)indx), str->length - ((int)indx));
@@ -373,7 +351,6 @@ int cosmoB_sSub(CState *state, int nargs, CValue *args)
cosmoV_typeError(state, "string.sub()", "<string>, <number>, <number>", "%s, %s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]),
cosmoV_typeStr(args[2]));
return 0;
}
CObjString *str = cosmoV_readString(args[0]);
@@ -385,13 +362,11 @@ int cosmoB_sSub(CState *state, int nargs, CValue *args)
cosmoV_error(
state, "string.sub() expected subbed string goes out of bounds, max length is %d!",
str->length);
return 0;
}
cosmoV_pushLString(state, str->str + ((int)indx), ((int)length));
} else {
cosmoV_error(state, "string.sub() expected 2 or 3 arguments, got %d!", nargs);
return 0;
}
return 1;
@@ -404,7 +379,6 @@ int cosmoB_sFind(CState *state, int nargs, CValue *args)
if (!IS_STRING(args[0]) || !IS_STRING(args[1])) {
cosmoV_typeError(state, "string.find()", "<string>, <string>", "%s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
return 0;
}
CObjString *str = cosmoV_readString(args[0]);
@@ -425,7 +399,6 @@ int cosmoB_sFind(CState *state, int nargs, CValue *args)
cosmoV_typeError(state, "string.find()", "<string>, <string>, <number>", "%s, %s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]),
cosmoV_typeStr(args[2]));
return 0;
}
CObjString *str = cosmoV_readString(args[0]);
@@ -444,7 +417,6 @@ int cosmoB_sFind(CState *state, int nargs, CValue *args)
cosmoV_pushNumber(state, (cosmo_Number)(indx - str->str));
} else {
cosmoV_error(state, "string.find() expected 2 or 3 arguments, got %d!", nargs);
return 0;
}
return 1;
@@ -455,13 +427,11 @@ int cosmoB_sSplit(CState *state, int nargs, CValue *args)
{
if (nargs != 2) {
cosmoV_error(state, "string.split() expected 2 arguments, got %d!", nargs);
return 0;
}
if (!IS_STRING(args[0]) || !IS_STRING(args[1])) {
cosmoV_typeError(state, "string.split()", "<string>, <string>", "%s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
return 0;
}
CObjString *str = cosmoV_readString(args[0]);
@@ -492,12 +462,10 @@ int cosmoB_sByte(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "string.byte() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_STRING(args[0])) {
cosmoV_typeError(state, "string.byte", "<string>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
CObjString *str = cosmoV_readString(args[0]);
@@ -518,12 +486,10 @@ int cosmoB_sChar(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "string.char() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "string.char", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
// small side effect of truncating the number, but ignoring the decimal instead of throwing an
@@ -533,7 +499,6 @@ int cosmoB_sChar(CState *state, int nargs, CValue *args)
if (num > 255 || num < 0) {
cosmoV_error(state, "Character expected to be in range 0-255, got %d!", num);
return 0;
}
// basically, treat the character value on the C stack as an """"array"""" with a length of 1
@@ -545,12 +510,10 @@ int cosmoB_sLen(CState *state, int nargs, CValue *args)
{
if (nargs < 1) {
cosmoV_error(state, "string.len() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_STRING(args[0])) {
cosmoV_typeError(state, "string.len", "<string>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
cosmoV_pushNumber(state, (cosmo_Number)strlen(cosmoV_readCString(args[0])));
@@ -562,14 +525,12 @@ int cosmoB_sRep(CState *state, int nargs, CValue *args)
{
if (nargs != 2) {
cosmoV_error(state, "string.rep() expected 2 arguments, got %d!", nargs);
return 0;
}
// expects <string>, <number>
if (!IS_STRING(args[0]) || !IS_NUMBER(args[1])) {
cosmoV_typeError(state, "string.rep", "<string>, <number>", "%s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
return 0;
}
CObjString *str = cosmoV_readString(args[0]);
@@ -627,12 +588,10 @@ int cosmoB_mAbs(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.abs() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.abs", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
cosmoV_pushNumber(state, fabs(cosmoV_readNumber(args[0])));
@@ -644,12 +603,10 @@ int cosmoB_mFloor(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.floor() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.floor", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
cosmoV_pushNumber(state, (int)cosmoV_readNumber(args[0]));
@@ -661,12 +618,10 @@ int cosmoB_mCeil(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.ceil() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.ceil", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
int roundedDown = (int)cosmoV_readNumber(args[0]);
@@ -685,12 +640,10 @@ int cosmoB_mSin(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.sin() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.sin", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
cosmoV_pushNumber(state, sin(cosmoV_readNumber(args[0])));
@@ -701,12 +654,10 @@ int cosmoB_mCos(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.cos() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.cos", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
cosmoV_pushNumber(state, cos(cosmoV_readNumber(args[0])));
@@ -717,12 +668,10 @@ int cosmoB_mTan(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.tan() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.tan", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
cosmoV_pushNumber(state, tan(cosmoV_readNumber(args[0])));
@@ -733,12 +682,10 @@ int cosmoB_mASin(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.asin() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.asin", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
cosmoV_pushNumber(state, asin(cosmoV_readNumber(args[0])));
@@ -749,12 +696,10 @@ int cosmoB_mACos(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.acos() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.acos", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
cosmoV_pushNumber(state, acos(cosmoV_readNumber(args[0])));
@@ -765,12 +710,10 @@ int cosmoB_mATan(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.atan() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.atan", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
cosmoV_pushNumber(state, atan(cosmoV_readNumber(args[0])));
@@ -781,12 +724,10 @@ int cosmoB_mRad(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.rad() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.rad", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
// convert the degree to radians
@@ -798,12 +739,10 @@ int cosmoB_mDeg(CState *state, int nargs, CValue *args)
{
if (nargs != 1) {
cosmoV_error(state, "math.deg() expected 1 argument, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[0])) {
cosmoV_typeError(state, "math.deg", "<number>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
// convert the degree to radians
@@ -852,13 +791,11 @@ int cosmoB_vsetGlobal(CState *state, int nargs, CValue *args)
{
if (nargs != 2) {
cosmoV_error(state, "Expected 2 argumenst, got %d!", nargs);
return 0;
}
if (!IS_TABLE(args[1])) {
cosmoV_typeError(state, "vm.__setter[\"globals\"]", "<object>, <table>", "%s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
return 0;
}
// this makes me very nervous ngl
@@ -874,13 +811,11 @@ int cosmoB_vdisassemble(CState *state, int nargs, CValue *args)
if (nargs != 1) {
cosmoV_error(state, "Expected 1 argument, got %d!", nargs);
return 0;
}
// get the closure
if (!IS_CLOSURE(args[0])) {
cosmoV_typeError(state, "vm.disassemble", "<closure>", "%s", cosmoV_typeStr(args[0]));
return 0;
}
closure = cosmoV_readClosure(args[0]);
@@ -895,13 +830,11 @@ int cosmoB_vindexBProto(CState *state, int nargs, CValue *args)
{
if (nargs != 2) {
cosmoV_error(state, "Expected 2 arguments, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[1])) {
cosmoV_typeError(state, "baseProtos.__index", "<object>, <number>", "%s, %s",
cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]));
return 0;
}
int indx = (int)cosmoV_readNumber(args[1]);
@@ -923,14 +856,12 @@ int cosmoB_vnewindexBProto(CState *state, int nargs, CValue *args)
{
if (nargs != 3) {
cosmoV_error(state, "Expected 3 arguments, got %d!", nargs);
return 0;
}
if (!IS_NUMBER(args[1]) || !IS_OBJECT(args[2])) {
cosmoV_typeError(state, "baseProtos.__newindex", "<object>, <number>, <object>",
"%s, %s, %s", cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]),
cosmoV_typeStr(args[2]));
return 0;
}
int indx = (int)cosmoV_readNumber(args[1]);
@@ -938,7 +869,6 @@ int cosmoB_vnewindexBProto(CState *state, int nargs, CValue *args)
if (indx >= COBJ_MAX || indx < 0) {
cosmoV_error(state, "index out of range! expected 0 - %d, got %d!", COBJ_MAX, indx);
return 0;
}
cosmoV_registerProtoObject(state, indx, proto);
@@ -948,16 +878,8 @@ int cosmoB_vnewindexBProto(CState *state, int nargs, CValue *args)
// vm.collect()
int cosmoB_vcollect(CState *state, int nargs, CValue *args)
{
// first, unfreeze the state (we start frozen on entry to any C Function)
cosmoM_unfreezeGC(state);
// now force a garbage collection
// force a garbage collection
cosmoM_collectGarbage(state);
// and re-freeze the state
cosmoM_freezeGC(state);
// the end!
return 0;
}

View File

@@ -27,9 +27,9 @@ void initChunk(CState *state, CChunk *chunk, size_t startCapacity)
void cleanChunk(CState *state, CChunk *chunk)
{
// first, free the chunk buffer
cosmoM_freearray(state, INSTRUCTION, chunk->buf, chunk->capacity);
cosmoM_freeArray(state, INSTRUCTION, chunk->buf, chunk->capacity);
// then the line info
cosmoM_freearray(state, int, chunk->lineInfo, chunk->capacity);
cosmoM_freeArray(state, int, chunk->lineInfo, chunk->capacity);
// free the constants
cleanValArray(state, &chunk->constants);
}
@@ -61,8 +61,8 @@ int addConstant(CState *state, CChunk *chunk, CValue value)
void writeu8Chunk(CState *state, CChunk *chunk, INSTRUCTION i, int line)
{
// does the buffer need to be reallocated?
cosmoM_growarray(state, INSTRUCTION, chunk->buf, chunk->count, chunk->capacity);
cosmoM_growarray(state, int, chunk->lineInfo, chunk->count, chunk->lineCapacity);
cosmoM_growArray(state, INSTRUCTION, chunk->buf, chunk->count, chunk->capacity);
cosmoM_growArray(state, int, chunk->lineInfo, chunk->count, chunk->lineCapacity);
// write data to the chunk :)
chunk->lineInfo[chunk->count] = line;

View File

@@ -54,7 +54,7 @@ static void resetBuffer(CLexState *state)
// cancels the token heap buffer and frees it
static void freeBuffer(CLexState *state)
{
cosmoM_freearray(state->cstate, char, state->buffer, state->bufCap);
cosmoM_freeArray(state->cstate, char, state->buffer, state->bufCap);
resetBuffer(state);
}
@@ -62,7 +62,7 @@ static void freeBuffer(CLexState *state)
// adds character to buffer
static void appendBuffer(CLexState *state, char c)
{
cosmoM_growarray(state->cstate, char, state->buffer, state->bufCount, state->bufCap);
cosmoM_growArray(state->cstate, char, state->buffer, state->bufCount, state->bufCap);
state->buffer[state->bufCount++] = c;
}

View File

@@ -206,7 +206,7 @@ static void markObject(CState *state, CObj *obj)
return;
// we can use cosmoM_growarray because we lock the GC when we entered in cosmoM_collectGarbage
cosmoM_growarray(state, CObj *, state->grayStack.array, state->grayStack.count,
cosmoM_growArray(state, CObj *, state->grayStack.array, state->grayStack.count,
state->grayStack.capacity);
state->grayStack.array[state->grayStack.count++] = obj;
@@ -296,12 +296,11 @@ static void markRoots(CState *state)
COSMO_API void cosmoM_collectGarbage(CState *state)
{
cosmoM_freezeGC(state);
#ifdef GC_DEBUG
printf("-- GC start\n");
size_t start = state->allocatedBytes;
#endif
cosmoM_freezeGC(state); // we don't want a recursive garbage collection event!
markRoots(state);
tableRemoveWhite(
@@ -312,14 +311,12 @@ COSMO_API void cosmoM_collectGarbage(CState *state)
// set our next GC event
cosmoM_updateThreshhold(state);
state->freezeGC--; // we don't want to use cosmoM_unfreezeGC because that might trigger a GC
// event (if GC_STRESS is defined)
#ifdef GC_DEBUG
printf("-- GC end, reclaimed %ld bytes (started at %ld, ended at %ld), next garbage collection "
"scheduled at %ld bytes\n",
start - state->allocatedBytes, start, state->allocatedBytes, state->nextGC);
#endif
cosmoM_unfreezeGC(state);
}
COSMO_API void cosmoM_updateThreshhold(CState *state)

View File

@@ -12,16 +12,16 @@
#define ARRAY_START 8
#ifdef GC_DEBUG
# define cosmoM_freearray(state, type, buf, capacity) \
# define cosmoM_freeArray(state, type, buf, capacity) \
printf("freeing array %p [size %lu] at %s:%d\n", buf, sizeof(type) * capacity, __FILE__, \
__LINE__); \
cosmoM_reallocate(state, buf, sizeof(type) * capacity, 0)
#else
# define cosmoM_freearray(state, type, buf, capacity) \
# define cosmoM_freeArray(state, type, buf, capacity) \
cosmoM_reallocate(state, buf, sizeof(type) * capacity, 0)
#endif
#define cosmoM_growarray(state, type, buf, count, capacity) \
#define cosmoM_growArray(state, type, buf, count, capacity) \
if (count >= capacity || buf == NULL) { \
int old = capacity; \
capacity = old * GROW_FACTOR; \
@@ -38,6 +38,7 @@
#define cosmoM_isFrozen(state) (state->freezeGC > 0)
// cosmoM_freezeGC should only be used in the garbage collector !
// if debugging, print the locations of when the state is frozen/unfrozen
#ifdef GC_DEBUG
# define cosmoM_freezeGC(state) \
@@ -79,7 +80,4 @@ static inline void *cosmoM_xmalloc(CState *state, size_t sz)
return cosmoM_reallocate(state, NULL, 0, sz);
}
// #define cosmoM_xmalloc(state, sz) \
// (printf("allocating new buffer at %s:%d of size %ld\n", __FILE__, __LINE__, sz), cosmoM_reallocate(state, NULL, 0, sz))
#endif

View File

@@ -46,7 +46,7 @@ void cosmoO_free(CState *state, CObj *obj)
switch (obj->type) {
case COBJ_STRING: {
CObjString *objStr = (CObjString *)obj;
cosmoM_freearray(state, char, objStr->str, objStr->length + 1);
cosmoM_freeArray(state, char, objStr->str, objStr->length + 1);
cosmoM_free(state, CObjString, objStr);
break;
}
@@ -82,13 +82,13 @@ void cosmoO_free(CState *state, CObj *obj)
}
case COBJ_ERROR: {
CObjError *err = (CObjError *)obj;
cosmoM_freearray(state, CCallFrame, err->frames, err->frameCount);
cosmoM_freeArray(state, CCallFrame, err->frames, err->frameCount);
cosmoM_free(state, CObjError, obj);
break;
}
case COBJ_CLOSURE: {
CObjClosure *closure = (CObjClosure *)obj;
cosmoM_freearray(state, CObjUpval *, closure->upvalues, closure->upvalueCount);
cosmoM_freeArray(state, CObjUpval *, closure->upvalues, closure->upvalueCount);
cosmoM_free(state, CObjClosure, closure);
break;
}
@@ -229,14 +229,13 @@ CObjCFunction *cosmoO_newCFunction(CState *state, CosmoCFunction func)
CObjError *cosmoO_newError(CState *state, CValue err)
{
CCallFrame *frames = cosmoM_xmalloc(state, sizeof(CCallFrame) * state->frameCount);
CObjError *cerror = (CObjError *)cosmoO_allocateBase(state, sizeof(CObjError), COBJ_ERROR);
cerror->err = err;
cerror->frameCount = state->frameCount;
cerror->frames = frames;
cerror->parserError = false;
// allocate the callframe
cerror->frames = cosmoM_xmalloc(state, sizeof(CCallFrame) * cerror->frameCount);
// clone the call frame
for (int i = 0; i < state->frameCount; i++)
cerror->frames[i] = state->callFrame[i];
@@ -306,7 +305,7 @@ CObjString *cosmoO_takeString(CState *state, char *str, size_t length)
// have we already interned this string?
if (lookup != NULL) {
cosmoM_freearray(state, char, str,
cosmoM_freeArray(state, char, str,
length + 1); // free our passed character array, it's unneeded!
return lookup;
}
@@ -322,8 +321,7 @@ CObjString *cosmoO_allocateString(CState *state, const char *str, size_t sz, uin
strObj->length = sz;
strObj->hash = hash;
// we push & pop the string so our GC can find it (we don't use freezeGC/unfreezeGC because we
// *want* a GC event to happen)
// push/pop to make sure GC doesn't collect it
cosmoV_pushRef(state, (CObj *)strObj);
cosmoT_insert(state, &state->strings, cosmoV_newRef((CObj *)strObj));
cosmoV_pop(state);
@@ -762,6 +760,8 @@ const char *cosmoO_typeStr(CObj *obj)
return "<function>";
case COBJ_CFUNCTION:
return "<c function>";
case COBJ_ERROR:
return "<error>";
case COBJ_METHOD:
return "<method>";
case COBJ_CLOSURE:

View File

@@ -64,9 +64,10 @@ typedef struct
CCompilerState *compiler;
CObjString *module; // name of the module
CToken current;
CToken previous; // token right after the current token
int workingStackCount; // we push CValues of objects we need onto the stack so the garbage collector can see them.
// this is the count of those values so we'll know how many to pop off when we're done
CToken previous; // token right after the current token
int workingStackCount; // we push CValues of objects we need onto the stack so the garbage
// collector can see them. this is the count of those values so we'll
// know how many to pop off when we're done
} CParseState;
typedef enum
@@ -481,6 +482,7 @@ static void string(CParseState *pstate, bool canAssign, Precedence prec)
{
CObjString *strObj =
cosmoO_takeString(pstate->state, pstate->previous.start, pstate->previous.length);
keepTrackOf(pstate, cosmoV_newRef((CObj *)strObj));
writeConstant(pstate, cosmoV_newRef((CObj *)strObj));
}
@@ -1369,7 +1371,7 @@ static void endLoop(CParseState *pstate)
patchJmp(pstate, pstate->compiler->loop.breaks[--pstate->compiler->loop.breakCount]);
}
cosmoM_freearray(pstate->state, int, pstate->compiler->loop.breaks,
cosmoM_freeArray(pstate->state, int, pstate->compiler->loop.breaks,
pstate->compiler->loop.breakCapacity);
}
@@ -1658,7 +1660,7 @@ static void breakStatement(CParseState *pstate)
pstate->compiler->localCount = savedLocals;
// add break to loop
cosmoM_growarray(pstate->state, int, pstate->compiler->loop.breaks,
cosmoM_growArray(pstate->state, int, pstate->compiler->loop.breaks,
pstate->compiler->loop.breakCount, pstate->compiler->loop.breakCapacity);
pstate->compiler->loop.breaks[pstate->compiler->loop.breakCount++] = writeJmp(pstate, OP_JMP);
}

View File

@@ -4,8 +4,7 @@
#include "clex.h"
#include "cosmo.h"
// compiles source into CChunk, if NULL is returned, a syntaxical error has occurred and pushed onto
// the stack
// compiles source into CChunk
CObjFunction *cosmoP_compileString(CState *state, const char *source, const char *module);
#endif

View File

@@ -10,6 +10,8 @@
CPanic *cosmoV_newPanic(CState *state)
{
CPanic *panic = cosmoM_xmalloc(state, sizeof(CPanic));
panic->top = state->top;
panic->frameCount = state->frameCount;
panic->prev = state->panic;
state->panic = panic;
@@ -95,7 +97,6 @@ void cosmoV_freeState(CState *state)
#ifdef GC_DEBUG
printf("state %p is being free'd!\n", state);
#endif
cosmoM_freezeGC(state);
// frees all the objects
CObj *objs = state->objects;
@@ -119,7 +120,7 @@ void cosmoV_freeState(CState *state)
cosmoT_clearTable(state, &state->strings);
// free our gray stack & finally free the state structure
cosmoM_freearray(state, CObj *, state->grayStack.array, state->grayStack.capacity);
cosmoM_freeArray(state, CObj *, state->grayStack.array, state->grayStack.capacity);
#ifdef GC_DEBUG
if (state->allocatedBytes != 0) {

View File

@@ -43,32 +43,33 @@ typedef struct ArrayCObj
typedef struct CPanic
{
jmp_buf jmp;
StkPtr top;
struct CPanic *prev;
int frameCount;
} CPanic;
struct CState
{
int freezeGC; // when > 0, GC events will be ignored (for internal use)
int frameCount;
CPanic *panic;
CObj *objects; // tracks all of our allocated objects
CObj *userRoots; // user definable roots, this holds CObjs that should be considered "roots",
// lets the VM know you are holding a reference to a CObj in your code
ArrayCObj grayStack; // keeps track of which objects *haven't yet* been traversed in our GC, but
// *have been* found
size_t allocatedBytes;
size_t nextGC; // when allocatedBytes reaches this threshhold, trigger a GC event
CObjUpval *openUpvalues; // tracks all of our still open (meaning still on the stack) upvalues
CTable strings;
CObjTable *globals;
CValue *top; // top of the stack
CObjObject *protoObjects[COBJ_MAX]; // proto object for each COBJ type [NULL = no default proto]
CObjString *iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index
CCallFrame callFrame[FRAME_MAX]; // call frames
CValue stack[STACK_MAX]; // stack
CObjObject *protoObjects[COBJ_MAX]; // proto object for each COBJ type [NULL = no default proto]
CObjString *iStrings[ISTRING_MAX]; // strings used internally by the VM, eg. __init, __index
CTable strings;
ArrayCObj grayStack; // keeps track of which objects *haven't yet* been traversed in our GC, but
// *have been* found
CObjUpval *openUpvalues; // tracks all of our still open (meaning still on the stack) upvalues
CObjTable *globals;
CValue *top; // top of the stack
CObj *objects; // tracks all of our allocated objects
CObj *userRoots; // user definable roots, this holds CObjs that should be considered "roots",
// lets the VM know you are holding a reference to a CObj in your code
CPanic *panic;
int freezeGC; // when > 0, GC events will be ignored (for internal use)
int frameCount;
size_t allocatedBytes;
size_t nextGC; // when allocatedBytes reaches this threshhold, trigger a GC event
};
CPanic *cosmoV_newPanic(CState *state);

View File

@@ -61,7 +61,7 @@ void cosmoT_addTable(CState *state, CTable *from, CTable *to)
void cosmoT_clearTable(CState *state, CTable *tbl)
{
cosmoM_freearray(state, CTableEntry, tbl->table, cosmoT_getCapacity(tbl));
cosmoM_freeArray(state, CTableEntry, tbl->table, cosmoT_getCapacity(tbl));
}
static uint32_t getObjectHash(CObj *obj)
@@ -165,7 +165,7 @@ static void resizeTbl(CState *state, CTable *tbl, int newCapacity, bool canShrin
}
// free the old table
cosmoM_freearray(state, CTableEntry, tbl->table, oldCap);
cosmoM_freeArray(state, CTableEntry, tbl->table, oldCap);
tbl->table = entries;
tbl->capacityMask = newCapacity - 1;

View File

@@ -13,12 +13,12 @@ void initValArray(CState *state, CValueArray *val, size_t startCapacity)
void cleanValArray(CState *state, CValueArray *array)
{
cosmoM_freearray(state, CValue, array->values, array->capacity);
cosmoM_freeArray(state, CValue, array->values, array->capacity);
}
void appendValArray(CState *state, CValueArray *array, CValue val)
{
cosmoM_growarray(state, CValue, array->values, array->count, array->capacity);
cosmoM_growArray(state, CValue, array->values, array->count, array->capacity);
array->values[array->count++] = val;
}

View File

@@ -118,11 +118,14 @@ void cosmoV_throw(CState *state)
StkPtr temp = cosmoV_getTop(state, 0);
CObjError *error = cosmoO_newError(state, *temp);
// replace the value on the stack with the error
*temp = cosmoV_newRef((CObj *)cosmoO_newError(state, *temp));
CValue val = cosmoV_newRef((CObj *)cosmoO_newError(state, *temp));
if (state->panic) {
state->top = state->panic->top;
state->frameCount = state->panic->frameCount;
cosmoV_pushValue(state, val);
longjmp(state->panic->jmp, 1);
} else {
cosmoV_pushValue(state, val);
fprintf(stderr, "Unhandled panic! ");
cosmoV_printError(state, error);
exit(1);