Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7641 views
1
#include "jsi.h"
2
#include "jscompile.h"
3
#include "jsvalue.h"
4
#include "jsrun.h"
5
6
#include "regex.h"
7
8
static void jsG_markobject(js_State *J, int mark, js_Object *obj);
9
10
static void jsG_freeenvironment(js_State *J, js_Environment *env)
11
{
12
js_free(J, env);
13
}
14
15
static void jsG_freefunction(js_State *J, js_Function *fun)
16
{
17
js_free(J, fun->funtab);
18
js_free(J, fun->numtab);
19
js_free(J, fun->strtab);
20
js_free(J, fun->vartab);
21
js_free(J, fun->code);
22
js_free(J, fun);
23
}
24
25
static void jsG_freeproperty(js_State *J, js_Property *node)
26
{
27
while (node) {
28
js_Property *next = node->next;
29
js_free(J, node);
30
node = next;
31
}
32
}
33
34
static void jsG_freeiterator(js_State *J, js_Iterator *node)
35
{
36
while (node) {
37
js_Iterator *next = node->next;
38
js_free(J, node);
39
node = next;
40
}
41
}
42
43
static void jsG_freeobject(js_State *J, js_Object *obj)
44
{
45
if (obj->head)
46
jsG_freeproperty(J, obj->head);
47
if (obj->type == JS_CREGEXP)
48
js_regfree(obj->u.r.prog);
49
if (obj->type == JS_CITERATOR)
50
jsG_freeiterator(J, obj->u.iter.head);
51
if (obj->type == JS_CUSERDATA && obj->u.user.finalize)
52
obj->u.user.finalize(J, obj->u.user.data);
53
js_free(J, obj);
54
}
55
56
static void jsG_markfunction(js_State *J, int mark, js_Function *fun)
57
{
58
unsigned int i;
59
fun->gcmark = mark;
60
for (i = 0; i < fun->funlen; ++i)
61
if (fun->funtab[i]->gcmark != mark)
62
jsG_markfunction(J, mark, fun->funtab[i]);
63
}
64
65
static void jsG_markenvironment(js_State *J, int mark, js_Environment *env)
66
{
67
do {
68
env->gcmark = mark;
69
if (env->variables->gcmark != mark)
70
jsG_markobject(J, mark, env->variables);
71
env = env->outer;
72
} while (env && env->gcmark != mark);
73
}
74
75
static void jsG_markproperty(js_State *J, int mark, js_Property *node)
76
{
77
while (node) {
78
if (node->value.type == JS_TMEMSTR && node->value.u.memstr->gcmark != mark)
79
node->value.u.memstr->gcmark = mark;
80
if (node->value.type == JS_TOBJECT && node->value.u.object->gcmark != mark)
81
jsG_markobject(J, mark, node->value.u.object);
82
if (node->getter && node->getter->gcmark != mark)
83
jsG_markobject(J, mark, node->getter);
84
if (node->setter && node->setter->gcmark != mark)
85
jsG_markobject(J, mark, node->setter);
86
node = node->next;
87
}
88
}
89
90
static void jsG_markobject(js_State *J, int mark, js_Object *obj)
91
{
92
obj->gcmark = mark;
93
if (obj->head)
94
jsG_markproperty(J, mark, obj->head);
95
if (obj->prototype && obj->prototype->gcmark != mark)
96
jsG_markobject(J, mark, obj->prototype);
97
if (obj->type == JS_CITERATOR) {
98
jsG_markobject(J, mark, obj->u.iter.target);
99
}
100
if (obj->type == JS_CFUNCTION || obj->type == JS_CSCRIPT) {
101
if (obj->u.f.scope && obj->u.f.scope->gcmark != mark)
102
jsG_markenvironment(J, mark, obj->u.f.scope);
103
if (obj->u.f.function && obj->u.f.function->gcmark != mark)
104
jsG_markfunction(J, mark, obj->u.f.function);
105
}
106
}
107
108
static void jsG_markstack(js_State *J, int mark)
109
{
110
js_Value *v = J->stack;
111
int n = J->top;
112
while (n--) {
113
if (v->type == JS_TMEMSTR && v->u.memstr->gcmark != mark)
114
v->u.memstr->gcmark = mark;
115
if (v->type == JS_TOBJECT && v->u.object->gcmark != mark)
116
jsG_markobject(J, mark, v->u.object);
117
++v;
118
}
119
}
120
121
void js_gc(js_State *J, int report)
122
{
123
js_Function *fun, *nextfun, **prevnextfun;
124
js_Object *obj, *nextobj, **prevnextobj;
125
js_String *str, *nextstr, **prevnextstr;
126
js_Environment *env, *nextenv, **prevnextenv;
127
int nenv = 0, nfun = 0, nobj = 0, nstr = 0;
128
int genv = 0, gfun = 0, gobj = 0, gstr = 0;
129
int mark;
130
int i;
131
132
mark = J->gcmark = J->gcmark == 1 ? 2 : 1;
133
134
jsG_markobject(J, mark, J->Object_prototype);
135
jsG_markobject(J, mark, J->Array_prototype);
136
jsG_markobject(J, mark, J->Function_prototype);
137
jsG_markobject(J, mark, J->Boolean_prototype);
138
jsG_markobject(J, mark, J->Number_prototype);
139
jsG_markobject(J, mark, J->String_prototype);
140
jsG_markobject(J, mark, J->RegExp_prototype);
141
jsG_markobject(J, mark, J->Date_prototype);
142
143
jsG_markobject(J, mark, J->Error_prototype);
144
jsG_markobject(J, mark, J->EvalError_prototype);
145
jsG_markobject(J, mark, J->RangeError_prototype);
146
jsG_markobject(J, mark, J->ReferenceError_prototype);
147
jsG_markobject(J, mark, J->SyntaxError_prototype);
148
jsG_markobject(J, mark, J->TypeError_prototype);
149
jsG_markobject(J, mark, J->URIError_prototype);
150
151
jsG_markobject(J, mark, J->R);
152
jsG_markobject(J, mark, J->G);
153
154
jsG_markstack(J, mark);
155
156
jsG_markenvironment(J, mark, J->E);
157
jsG_markenvironment(J, mark, J->GE);
158
for (i = 0; i < J->envtop; ++i)
159
jsG_markenvironment(J, mark, J->envstack[i]);
160
161
prevnextenv = &J->gcenv;
162
for (env = J->gcenv; env; env = nextenv) {
163
nextenv = env->gcnext;
164
if (env->gcmark != mark) {
165
*prevnextenv = nextenv;
166
jsG_freeenvironment(J, env);
167
++genv;
168
} else {
169
prevnextenv = &env->gcnext;
170
}
171
++nenv;
172
}
173
174
prevnextfun = &J->gcfun;
175
for (fun = J->gcfun; fun; fun = nextfun) {
176
nextfun = fun->gcnext;
177
if (fun->gcmark != mark) {
178
*prevnextfun = nextfun;
179
jsG_freefunction(J, fun);
180
++gfun;
181
} else {
182
prevnextfun = &fun->gcnext;
183
}
184
++nfun;
185
}
186
187
prevnextobj = &J->gcobj;
188
for (obj = J->gcobj; obj; obj = nextobj) {
189
nextobj = obj->gcnext;
190
if (obj->gcmark != mark) {
191
*prevnextobj = nextobj;
192
jsG_freeobject(J, obj);
193
++gobj;
194
} else {
195
prevnextobj = &obj->gcnext;
196
}
197
++nobj;
198
}
199
200
prevnextstr = &J->gcstr;
201
for (str = J->gcstr; str; str = nextstr) {
202
nextstr = str->gcnext;
203
if (str->gcmark != mark) {
204
*prevnextstr = nextstr;
205
js_free(J, str);
206
++gstr;
207
} else {
208
prevnextstr = &str->gcnext;
209
}
210
++nstr;
211
}
212
213
if (report)
214
printf("garbage collected: %d/%d envs, %d/%d funs, %d/%d objs, %d/%d strs\n",
215
genv, nenv, gfun, nfun, gobj, nobj, gstr, nstr);
216
}
217
218
void js_freestate(js_State *J)
219
{
220
js_Function *fun, *nextfun;
221
js_Object *obj, *nextobj;
222
js_Environment *env, *nextenv;
223
js_String *str, *nextstr;
224
225
for (env = J->gcenv; env; env = nextenv)
226
nextenv = env->gcnext, jsG_freeenvironment(J, env);
227
for (fun = J->gcfun; fun; fun = nextfun)
228
nextfun = fun->gcnext, jsG_freefunction(J, fun);
229
for (obj = J->gcobj; obj; obj = nextobj)
230
nextobj = obj->gcnext, jsG_freeobject(J, obj);
231
for (str = J->gcstr; str; str = nextstr)
232
nextstr = str->gcnext, js_free(J, str);
233
234
jsS_freestrings(J);
235
236
js_free(J, J->lexbuf.text);
237
J->alloc(J->actx, J->stack, 0);
238
J->alloc(J->actx, J, 0);
239
}
240
241