Issue 133: Eliminate recursion in GC scanning phase.

Use a queue instead of recursion to scan reachable objects.
This commit is contained in:
Tor Andersson
2020-05-14 13:42:00 +02:00
parent 8c5f2f24c7
commit 331c5ecbac
3 changed files with 26 additions and 5 deletions

26
jsgc.c
View File

@@ -5,8 +5,6 @@
#include "regexp.h"
static void jsG_markobject(js_State *J, int mark, js_Object *obj);
static void jsG_freeenvironment(js_State *J, js_Environment *env)
{
js_free(J, env);
@@ -53,6 +51,14 @@ static void jsG_freeobject(js_State *J, js_Object *obj)
js_free(J, obj);
}
/* Mark and add object to scan queue */
static void jsG_markobject(js_State *J, int mark, js_Object *obj)
{
obj->gcmark = mark;
obj->gcroot = J->gcroot;
J->gcroot = obj;
}
static void jsG_markfunction(js_State *J, int mark, js_Function *fun)
{
int i;
@@ -87,9 +93,9 @@ static void jsG_markproperty(js_State *J, int mark, js_Property *node)
jsG_markobject(J, mark, node->setter);
}
static void jsG_markobject(js_State *J, int mark, js_Object *obj)
/* Mark everything the object can reach. */
static void jsG_scanobject(js_State *J, int mark, js_Object *obj)
{
obj->gcmark = mark;
if (obj->properties->level)
jsG_markproperty(J, mark, obj->properties);
if (obj->prototype && obj->prototype->gcmark != mark)
@@ -139,6 +145,8 @@ void js_gc(js_State *J, int report)
mark = J->gcmark = J->gcmark == 1 ? 2 : 1;
/* Add initial roots. */
jsG_markobject(J, mark, J->Object_prototype);
jsG_markobject(J, mark, J->Array_prototype);
jsG_markobject(J, mark, J->Function_prototype);
@@ -166,6 +174,16 @@ void js_gc(js_State *J, int report)
for (i = 0; i < J->envtop; ++i)
jsG_markenvironment(J, mark, J->envstack[i]);
/* Scan objects until none remain. */
while ((obj = J->gcroot) != NULL) {
J->gcroot = obj->gcroot;
obj->gcroot = NULL;
jsG_scanobject(J, mark, obj);
}
/* Free everything not marked. */
prevnextenv = &J->gcenv;
for (env = J->gcenv; env; env = nextenv) {
nextenv = env->gcnext;

2
jsi.h
View File

@@ -239,6 +239,8 @@ struct js_State
js_Object *gcobj;
js_String *gcstr;
js_Object *gcroot; /* gc scan list */
/* environments on the call stack but currently not in scope */
int envtop;
js_Environment *envstack[JS_ENVLIMIT];

View File

@@ -119,7 +119,8 @@ struct js_Object
js_Finalize finalize;
} user;
} u;
js_Object *gcnext;
js_Object *gcnext; /* allocation list */
js_Object *gcroot; /* scan list */
int gcmark;
};