mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 00:00:10 +00:00
added cosmoM_addRoot & cosmoM_removeRoot
This commit is contained in:
parent
aff011a8d1
commit
f8a062919f
54
src/cmem.c
54
src/cmem.c
@ -191,6 +191,16 @@ void sweep(CState *state) {
|
||||
}
|
||||
}
|
||||
|
||||
void markUserRoots(CState *state) {
|
||||
CObj *root = state->userRoots;
|
||||
|
||||
// traverse userRoots and mark all the object
|
||||
while (root != NULL) {
|
||||
markObject(state, root);
|
||||
root = root->nextRoot;
|
||||
}
|
||||
}
|
||||
|
||||
void markRoots(CState *state) {
|
||||
// mark all values on the stack
|
||||
for (StkPtr value = state->stack; value < state->top; value++) {
|
||||
@ -213,6 +223,9 @@ void markRoots(CState *state) {
|
||||
for (int i = 0; i < ISTRING_MAX; i++)
|
||||
markObject(state, (CObj*)state->iStrings[i]);
|
||||
|
||||
// mark the user defined roots
|
||||
markUserRoots(state);
|
||||
|
||||
// mark our proto object
|
||||
markObject(state, (CObj*)state->protoObj);
|
||||
traceGrays(state);
|
||||
@ -234,7 +247,7 @@ COSMO_API void cosmoM_collectGarbage(CState *state) {
|
||||
// set our next GC event
|
||||
cosmoM_updateThreshhold(state);
|
||||
|
||||
cosmoM_unfreezeGC(state);
|
||||
state->freezeGC--; // we don't want to use cosmoM_unfreezeGC because that might trigger a GC event
|
||||
#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);
|
||||
@ -244,4 +257,43 @@ COSMO_API void cosmoM_collectGarbage(CState *state) {
|
||||
|
||||
COSMO_API void cosmoM_updateThreshhold(CState *state) {
|
||||
state->nextGC = state->allocatedBytes * HEAP_GROW_FACTOR;
|
||||
}
|
||||
|
||||
COSMO_API void cosmoM_addRoot(CState *state, CObj *newRoot) {
|
||||
// first, check and make sure this root doesn't already exist in the list
|
||||
CObj *root = state->userRoots;
|
||||
while (root != NULL) {
|
||||
if (root == newRoot) // found in the list, abort
|
||||
return;
|
||||
|
||||
root = root->nextRoot;
|
||||
}
|
||||
|
||||
// adds root to userRoot linked list
|
||||
newRoot->nextRoot = state->userRoots;
|
||||
state->userRoots = newRoot;
|
||||
}
|
||||
|
||||
COSMO_API void cosmoM_removeRoot(CState *state, CObj *oldRoot) {
|
||||
CObj *prev = NULL;
|
||||
CObj *root = state->userRoots;
|
||||
|
||||
// traverse the userRoot linked list
|
||||
while (root != NULL) {
|
||||
if (root == oldRoot) { // found root in list
|
||||
|
||||
// remove from the linked list
|
||||
if (prev == NULL) {
|
||||
state->userRoots = root->nextRoot;
|
||||
} else {
|
||||
prev->nextRoot = root->nextRoot;
|
||||
}
|
||||
|
||||
root->nextRoot = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
prev = root;
|
||||
root = root->nextRoot;
|
||||
}
|
||||
}
|
13
src/cmem.h
13
src/cmem.h
@ -39,9 +39,12 @@
|
||||
printf("unfreezing state at %s:%d [%d]\n", __FILE__, __LINE__, state->freezeGC); \
|
||||
cosmoM_checkGarbage(state, 0)
|
||||
#else
|
||||
|
||||
// freeze's the garbage collector until cosmoM_unfreezeGC is called
|
||||
#define cosmoM_freezeGC(state) \
|
||||
state->freezeGC++
|
||||
|
||||
// unfreeze's the garbage collector and tries to run a garbage collection cycle
|
||||
#define cosmoM_unfreezeGC(state) \
|
||||
state->freezeGC--; \
|
||||
cosmoM_checkGarbage(state, 0)
|
||||
@ -53,9 +56,13 @@ COSMO_API bool cosmoM_checkGarbage(CState *state, size_t needed); // returns tru
|
||||
COSMO_API void cosmoM_collectGarbage(CState *state);
|
||||
COSMO_API void cosmoM_updateThreshhold(CState *state);
|
||||
|
||||
/*
|
||||
wrapper for cosmoM_reallocate so we can track our memory usage (it's also safer :P)
|
||||
*/
|
||||
// lets the VM know you are holding a reference to a CObj and to not free it
|
||||
COSMO_API void cosmoM_addRoot(CState *state, CObj *newRoot);
|
||||
|
||||
// lets the VM know this root is no longer held in a reference and is able to be free'd
|
||||
COSMO_API void cosmoM_removeRoot(CState *state, CObj *oldRoot);
|
||||
|
||||
// wrapper for cosmoM_reallocate so we can track our memory usage (it's also safer :P)
|
||||
static inline void *cosmoM_xmalloc(CState *state, size_t sz) {
|
||||
return cosmoM_reallocate(state, NULL, 0, sz);
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ CObj *cosmoO_allocateBase(CState *state, size_t sz, CObjType type) {
|
||||
|
||||
obj->next = state->objects;
|
||||
state->objects = obj;
|
||||
|
||||
obj->nextRoot = NULL;
|
||||
#ifdef GC_DEBUG
|
||||
printf("allocated %p with OBJ_TYPE %d\n", obj, type);
|
||||
#endif
|
||||
|
@ -31,6 +31,7 @@ typedef struct CObj {
|
||||
CObjType type;
|
||||
bool isMarked; // for the GC
|
||||
struct CObj *next;
|
||||
struct CObj *nextRoot; // for the root linked list
|
||||
} CObj;
|
||||
|
||||
typedef struct CObjString {
|
||||
|
@ -20,6 +20,7 @@ CState *cosmoV_newState() {
|
||||
|
||||
// GC
|
||||
state->objects = NULL;
|
||||
state->userRoots = NULL;
|
||||
state->grayStack.count = 0;
|
||||
state->grayStack.capacity = 2;
|
||||
state->grayStack.array = NULL;
|
||||
|
@ -32,6 +32,7 @@ typedef struct CState {
|
||||
bool panic;
|
||||
int freezeGC; // when > 0, GC events will be ignored (for internal use)
|
||||
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
|
||||
|
@ -18,13 +18,15 @@ typedef double cosmo_Number;
|
||||
|
||||
#ifdef NAN_BOXXED
|
||||
/*
|
||||
NaN box, this is great for performance on x86_64 or ARM64 architectures. If you don't know how this works please reference these
|
||||
NaN box, this is great for fitting more in the cpu cache on x86_64 or ARM64 architectures. If you don't know how this works please reference these
|
||||
two articles:
|
||||
|
||||
https://leonardschuetz.ch/blog/nan-boxing/ and https://piotrduperas.com/posts/nan-boxing/
|
||||
|
||||
both are great resources :)
|
||||
|
||||
Performance notes: this can actually degrade performance, so only enable if you know what you're doing.
|
||||
|
||||
TL;DR: we can store payloads in the NaN value in the IEEE 754 standard.
|
||||
*/
|
||||
typedef union CValue {
|
||||
|
@ -30,7 +30,6 @@ CValue cosmoB_input(CState *state, int nargs, CValue *args) {
|
||||
}
|
||||
|
||||
static void interpret(CState *state, const char* script) {
|
||||
|
||||
// cosmoP_compileString pushes the result onto the stack (NIL or COBJ_FUNCTION)
|
||||
CObjFunction* func = cosmoP_compileString(state, script);
|
||||
if (func != NULL) {
|
||||
|
Loading…
Reference in New Issue
Block a user