acid: fix memory corruption due to gc
we cannot call gc() in execute() because it will gc anonyous intermediate results which happens when we construct a list and the elements are calculated by calling a function thru ocall() which calls execute(). also, the _thiscmd symbol; which is used to keep a reference to a statement so it wont get garbage collected; does not work as yyparse() is recursive (include statements). we add execrec() function which *only* gets called from yyparse() when evaluating a statement. it will keep a stack on the _thiscmd symbol handling the yyparse() recursion. we also only call gc() in execrec() before calling execute(). so execute() will never gc() while evaluating a statement which prevents the intermediate results from getting collected.
This commit is contained in:
parent
6b146c70c2
commit
9d8f5a1466
|
@ -190,6 +190,7 @@ void dostop(int);
|
||||||
Lsym* enter(char*, int);
|
Lsym* enter(char*, int);
|
||||||
void error(char*, ...);
|
void error(char*, ...);
|
||||||
void execute(Node*);
|
void execute(Node*);
|
||||||
|
void execrec(Node*);
|
||||||
void fatal(char*, ...);
|
void fatal(char*, ...);
|
||||||
void flatten(Node**, Node*);
|
void flatten(Node**, Node*);
|
||||||
void gc(void);
|
void gc(void);
|
||||||
|
|
|
@ -50,11 +50,7 @@ prog :
|
||||||
|
|
||||||
bigstmnt : stmnt
|
bigstmnt : stmnt
|
||||||
{
|
{
|
||||||
/* make stmnt a root so it isn't collected! */
|
execrec($1);
|
||||||
mkvar("_thiscmd")->proc = $1;
|
|
||||||
execute($1);
|
|
||||||
mkvar("_thiscmd")->proc = nil;
|
|
||||||
gc();
|
|
||||||
if(interactive)
|
if(interactive)
|
||||||
Bprint(bout, "acid: ");
|
Bprint(bout, "acid: ");
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,32 @@ unwind(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
execrec(Node *n)
|
||||||
|
{
|
||||||
|
Value *v;
|
||||||
|
Lsym *s;
|
||||||
|
|
||||||
|
/* make node a root so it isn't collected! */
|
||||||
|
s = mkvar("_thiscmd");
|
||||||
|
|
||||||
|
v = gmalloc(sizeof(Value));
|
||||||
|
memset(v, 0, sizeof(Value));
|
||||||
|
v->type = TCODE;
|
||||||
|
v->cc = n;
|
||||||
|
v->pop = s->v;
|
||||||
|
|
||||||
|
s->v = v;
|
||||||
|
s->proc = n;
|
||||||
|
|
||||||
|
gc();
|
||||||
|
execute(n);
|
||||||
|
|
||||||
|
s->proc = s->v->cc;
|
||||||
|
s->v = v->pop;
|
||||||
|
free(v);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
execute(Node *n)
|
execute(Node *n)
|
||||||
{
|
{
|
||||||
|
@ -66,7 +92,6 @@ execute(Node *n)
|
||||||
Node res, xx;
|
Node res, xx;
|
||||||
static int stmnt;
|
static int stmnt;
|
||||||
|
|
||||||
gc();
|
|
||||||
if(gotint)
|
if(gotint)
|
||||||
error("interrupted");
|
error("interrupted");
|
||||||
|
|
||||||
|
|
|
@ -569,11 +569,11 @@ enter(char *name, int t)
|
||||||
s->lexval = t;
|
s->lexval = t;
|
||||||
|
|
||||||
v = gmalloc(sizeof(Value));
|
v = gmalloc(sizeof(Value));
|
||||||
s->v = v;
|
memset(v, 0, sizeof(Value));
|
||||||
|
|
||||||
v->fmt = 'X';
|
v->fmt = 'X';
|
||||||
v->type = TINT;
|
v->type = TINT;
|
||||||
memset(v, 0, sizeof(Value));
|
|
||||||
|
s->v = v;
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue