From 96ca91ec7c4ff8fc1705e48d5b67e9e0570f5fde Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 17 Jan 2014 22:57:12 +0100 Subject: [PATCH] Garbage collector lists. --- js.h | 5 ++++- jscompile.c | 30 ++++----------------------- jscompile.h | 3 ++- jsgc.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ jsintern.c | 22 ++++++++++++++++---- jsobject.h | 5 ++++- jsproperty.c | 18 ++++++++++------- jsrun.c | 4 ++++ jsrun.h | 3 +++ jsstate.c | 6 ------ jsstate.h | 6 ++++++ 11 files changed, 113 insertions(+), 46 deletions(-) create mode 100644 jsgc.c diff --git a/js.h b/js.h index 9b71634..a5f60bc 100644 --- a/js.h +++ b/js.h @@ -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 diff --git a/jscompile.c b/jscompile.c index 0a9d7af..a366594 100644 --- a/jscompile.c +++ b/jscompile.c @@ -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); diff --git a/jscompile.h b/jscompile.h index 35dd13c..927b06e 100644 --- a/jscompile.h +++ b/jscompile.h @@ -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); diff --git a/jsgc.c b/jsgc.c new file mode 100644 index 0000000..d8356e9 --- /dev/null +++ b/jsgc.c @@ -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); +} diff --git a/jsintern.c b/jsintern.c index baf2076..1bf299d 100644 --- a/jsintern.c +++ b/jsintern.c @@ -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; diff --git a/jsobject.h b/jsobject.h index e7ca1eb..c2938d7 100644 --- a/jsobject.h +++ b/jsobject.h @@ -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; diff --git a/jsproperty.c b/jsproperty.c index b4df8c7..477b5d0 100644 --- a/jsproperty.c +++ b/jsproperty.c @@ -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; } diff --git a/jsrun.c b/jsrun.c index 865d11f..c8683a1 100644 --- a/jsrun.c +++ b/jsrun.c @@ -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; diff --git a/jsrun.h b/jsrun.h index edef0e7..ebcb455 100644 --- a/jsrun.h +++ b/jsrun.h @@ -5,6 +5,9 @@ struct js_Environment { js_Environment *outer; js_Object *variables; + + js_Environment *gcnext; + int gcmark; }; /* private */ diff --git a/jsstate.c b/jsstate.c index e3a5f4f..cfc2981 100644 --- a/jsstate.c +++ b/jsstate.c @@ -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; diff --git a/jsstate.h b/jsstate.h index cdc09f3..c42aa3f 100644 --- a/jsstate.h +++ b/jsstate.h @@ -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]; };