mirror of
https://github.com/ccxvii/mujs.git
synced 2026-02-06 01:41:37 +08:00
Garbage collector lists.
This commit is contained in:
5
js.h
5
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
|
||||
|
||||
30
jscompile.c
30
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);
|
||||
|
||||
|
||||
@@ -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
57
jsgc.c
Normal 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);
|
||||
}
|
||||
22
jsintern.c
22
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
18
jsproperty.c
18
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;
|
||||
}
|
||||
|
||||
|
||||
4
jsrun.c
4
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;
|
||||
|
||||
3
jsrun.h
3
jsrun.h
@@ -5,6 +5,9 @@ struct js_Environment
|
||||
{
|
||||
js_Environment *outer;
|
||||
js_Object *variables;
|
||||
|
||||
js_Environment *gcnext;
|
||||
int gcmark;
|
||||
};
|
||||
|
||||
/* private */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user