Garbage collector lists.

This commit is contained in:
Tor Andersson
2014-01-17 22:57:12 +01:00
parent 299dbda156
commit 96ca91ec7c
11 changed files with 113 additions and 46 deletions

5
js.h
View File

@@ -46,6 +46,8 @@ int js_loadfile(js_State *J, const char *filename);
int js_dostring(js_State *J, const char *source);
int js_dofile(js_State *J, const char *filename);
void js_gc(js_State *J);
/* binding API: TODO: move from jsrun.h */
typedef int (*js_CFunction)(js_State *J, int argc);
@@ -59,6 +61,7 @@ typedef struct js_Object js_Object;
typedef struct js_StringNode js_StringNode;
const char *js_intern(js_State *J, const char *s);
void js_printstringtree(js_State *J);
void js_printstrings(js_State *J);
void js_freestrings(js_State *J);
#endif

View File

@@ -17,27 +17,18 @@ static js_Function *newfun(js_State *J, js_Ast *name, js_Ast *params, js_Ast *bo
{
js_Function *F = malloc(sizeof *F);
memset(F, 0, sizeof *F);
F->gcmark = 0;
F->gcnext = J->gcfun;
J->gcfun = F;
F->filename = js_intern(J, J->filename);
F->line = name ? name->line : params ? params->line : body->line;
F->next = J->fun;
J->fun = F;
cfunbody(J, F, name, params, body);
return F;
}
static void freefun(js_State *J, js_Function *F)
{
free(F->funtab);
free(F->numtab);
free(F->strtab);
free(F->code);
free(F);
}
/* Emit opcodes, constants and jumps */
static void emit(JF, int value)
@@ -760,25 +751,12 @@ int jsC_error(js_State *J, js_Ast *node, const char *fmt, ...)
longjmp(J->jb, 1);
}
static void jsC_freecompile(js_State *J)
{
js_Function *F = J->fun;
while (F) {
js_Function *next = F->next;
freefun(J, F);
F = next;
}
J->fun = NULL;
}
js_Function *jsC_compile(js_State *J, js_Ast *prog)
{
js_Function *F;
if (setjmp(J->jb)) {
jsC_freecompile(J);
if (setjmp(J->jb))
return NULL;
}
F = newfun(J, NULL, NULL, prog);

View File

@@ -109,7 +109,8 @@ struct js_Function
const char *filename;
int line;
js_Function *next; /* alloc list */
js_Function *gcnext;
int gcmark;
};
js_Function *jsC_compile(js_State *J, js_Ast *prog);

57
jsgc.c Normal file
View File

@@ -0,0 +1,57 @@
#include "js.h"
#include "jscompile.h"
#include "jsrun.h"
#include "jsobject.h"
#include "jsstate.h"
static void jsG_freefunction(js_State *J, js_Function *fun)
{
free(fun->params);
free(fun->funtab);
free(fun->numtab);
free(fun->strtab);
free(fun->code);
free(fun);
}
static void jsG_freeenvironment(js_State *J, js_Environment *env)
{
free(env);
}
static void jsG_freeproperty(js_State *J, js_Property *node)
{
if (node->left->level) jsG_freeproperty(J, node->left);
if (node->right->level) jsG_freeproperty(J, node->right);
free(node);
}
static void jsG_freeobject(js_State *J, js_Object *obj)
{
if (obj->properties->level)
jsG_freeproperty(J, obj->properties);
free(obj);
}
void js_gc(js_State *J)
{
}
void js_close(js_State *J)
{
js_Function *fun, *nextfun;
js_Object *obj, *nextobj;
js_Environment *env, *nextenv;
for (env = J->gcenv; env; env = nextenv)
nextenv = env->gcnext, jsG_freeenvironment(J, env);
for (fun = J->gcfun; fun; fun = nextfun)
nextfun = fun->gcnext, jsG_freefunction(J, fun);
for (obj = J->gcobj; obj; obj = nextobj)
nextobj = obj->gcnext, jsG_freeobject(J, obj);
js_freestrings(J);
free(J->buf.text);
free(J);
}

View File

@@ -5,7 +5,7 @@
struct js_StringNode
{
const char *string;
char *string;
js_StringNode *left, *right;
int level;
};
@@ -15,10 +15,10 @@ static js_StringNode sentinel = { "", &sentinel, &sentinel, 0 };
static js_StringNode *newstringnode(const char *string, const char **result)
{
js_StringNode *node = malloc(sizeof(js_StringNode));
node->string = *result = strdup(string);
node->string = strdup(string);
node->left = node->right = &sentinel;
node->level = 1;
return node;
return *result = node->string, node;
}
static js_StringNode *skew(js_StringNode *node)
@@ -78,7 +78,7 @@ static void printstringnode(js_StringNode *node, int level)
printstringnode(node->right, level + 1);
}
void js_printstringtree(js_State *J)
void js_printstrings(js_State *J)
{
js_StringNode *root = J->strings;
printf("--- string dump ---\n");
@@ -87,6 +87,20 @@ void js_printstringtree(js_State *J)
printf("---\n");
}
static void js_freestringnode(js_State *J, js_StringNode *node)
{
if (node->left != &sentinel) js_freestringnode(J, node->left);
if (node->right != &sentinel) js_freestringnode(J, node->right);
free(node->string);
free(node);
}
void js_freestrings(js_State *J)
{
if (J->strings && J->strings != &sentinel)
js_freestringnode(J, J->strings);
}
const char *js_intern(js_State *J, const char *s)
{
const char *result;

View File

@@ -68,11 +68,14 @@ struct js_Object
js_Function *function;
js_CFunction cfunction;
js_CFunction cconstructor;
js_Object *gcnext;
int gcmark;
};
struct js_Property
{
char *name;
const char *name;
js_Property *left, *right;
int level;
js_Value value;

View File

@@ -21,10 +21,10 @@
static js_Property sentinel = { "", &sentinel, &sentinel, 0 };
static js_Property *newproperty(const char *name)
static js_Property *newproperty(js_State *J, const char *name)
{
js_Property *node = malloc(sizeof(js_Property));
node->name = strdup(name);
node->name = js_intern(J, name);
node->left = node->right = &sentinel;
node->level = 1;
node->value.type = JS_TUNDEFINED;
@@ -74,21 +74,21 @@ static inline js_Property *split(js_Property *node)
return node;
}
static js_Property *insert(js_Property *node, const char *name, js_Property **result)
static js_Property *insert(js_State *J, js_Property *node, const char *name, js_Property **result)
{
if (node != &sentinel) {
int c = strcmp(name, node->name);
if (c < 0)
node->left = insert(node->left, name, result);
node->left = insert(J, node->left, name, result);
else if (c > 0)
node->right = insert(node->right, name, result);
node->right = insert(J, node->right, name, result);
else
return *result = node;
node = skew(node);
node = split(node);
return node;
}
return *result = newproperty(name);
return *result = newproperty(J, name);
}
static js_Property *lookupfirst(js_Property *node)
@@ -133,6 +133,10 @@ found:
js_Object *jsR_newobject(js_State *J, js_Class type, js_Object *prototype)
{
js_Object *obj = malloc(sizeof(js_Object));
obj->gcmark = 0;
obj->gcnext = J->gcobj;
J->gcobj = obj;
obj->type = type;
obj->properties = &sentinel;
obj->prototype = prototype;
@@ -162,7 +166,7 @@ js_Property *jsR_getproperty(js_State *J, js_Object *obj, const char *name)
js_Property *jsR_setproperty(js_State *J, js_Object *obj, const char *name)
{
js_Property *result;
obj->properties = insert(obj->properties, name, &result);
obj->properties = insert(J, obj->properties, name, &result);
return result;
}

View File

@@ -324,6 +324,10 @@ int js_nextproperty(js_State *J, int idx)
js_Environment *jsR_newenvironment(js_State *J, js_Object *vars, js_Environment *outer)
{
js_Environment *E = malloc(sizeof *E);
E->gcmark = 0;
E->gcnext = J->gcenv;
J->gcenv = E;
E->outer = outer;
E->variables = vars;
return E;

View File

@@ -5,6 +5,9 @@ struct js_Environment
{
js_Environment *outer;
js_Object *variables;
js_Environment *gcnext;
int gcmark;
};
/* private */

View File

@@ -87,12 +87,6 @@ js_State *js_newstate(void)
return J;
}
void js_close(js_State *J)
{
free(J->buf.text);
free(J);
}
int js_error(js_State *J, const char *fmt, ...)
{
va_list ap;

View File

@@ -43,6 +43,12 @@ struct js_State
js_Object *G;
js_Environment *E;
/* garbage collector list */
int gcmark;
js_Environment *gcenv;
js_Function *gcfun;
js_Object *gcobj;
int top, bot;
js_Value stack[JS_STACKSIZE];
};