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);
|
||||
void error(char*, ...);
|
||||
void execute(Node*);
|
||||
void execrec(Node*);
|
||||
void fatal(char*, ...);
|
||||
void flatten(Node**, Node*);
|
||||
void gc(void);
|
||||
|
|
|
@ -50,11 +50,7 @@ prog :
|
|||
|
||||
bigstmnt : stmnt
|
||||
{
|
||||
/* make stmnt a root so it isn't collected! */
|
||||
mkvar("_thiscmd")->proc = $1;
|
||||
execute($1);
|
||||
mkvar("_thiscmd")->proc = nil;
|
||||
gc();
|
||||
execrec($1);
|
||||
if(interactive)
|
||||
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
|
||||
execute(Node *n)
|
||||
{
|
||||
|
@ -66,7 +92,6 @@ execute(Node *n)
|
|||
Node res, xx;
|
||||
static int stmnt;
|
||||
|
||||
gc();
|
||||
if(gotint)
|
||||
error("interrupted");
|
||||
|
||||
|
|
|
@ -569,11 +569,11 @@ enter(char *name, int t)
|
|||
s->lexval = t;
|
||||
|
||||
v = gmalloc(sizeof(Value));
|
||||
s->v = v;
|
||||
|
||||
memset(v, 0, sizeof(Value));
|
||||
v->fmt = 'X';
|
||||
v->type = TINT;
|
||||
memset(v, 0, sizeof(Value));
|
||||
|
||||
s->v = v;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue