1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-26 05:51:08 +02:00

36853: replace pushheap/popheap by NEWHEAPS/OLDHEAPS in doshfunc() to optimize memory management

Includes re-indentation that was not done in the posted patch.
This commit is contained in:
Barton E. Schaefer 2015-10-14 21:46:26 -07:00
parent bab1fc5043
commit 827d360776
2 changed files with 214 additions and 209 deletions

View file

@ -1,3 +1,8 @@
2015-10-14 Barton E. Schaefer <schaefer@zsh.org>
* 36853: Src/exec.c: replace pushheap/popheap by NEWHEAPS/OLDHEAPS
in doshfunc() to optimize memory management
2015-10-14 Peter Stephenson <p.stephenson@samsung.com> 2015-10-14 Peter Stephenson <p.stephenson@samsung.com>
* 36856: Doc/Zsh/contrib.yo, Functions/Chpwd/cdr: add -p and -P * 36856: Doc/Zsh/contrib.yo, Functions/Chpwd/cdr: add -p and -P

View file

@ -5067,230 +5067,230 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
#ifdef MAX_FUNCTION_DEPTH #ifdef MAX_FUNCTION_DEPTH
static int funcdepth; static int funcdepth;
#endif #endif
Heap funcheap;
queue_signals(); /* Lots of memory and global state changes coming */ queue_signals(); /* Lots of memory and global state changes coming */
pushheap(); NEWHEAPS(funcheap) {
oargv0 = NULL;
obreaks = breaks;
ocontflag = contflag;
oloops = loops;
if (trap_state == TRAP_STATE_PRIMED)
trap_return--;
oldlastval = lastval;
oldnumpipestats = numpipestats;
if (noreturnval) {
/*
* Easiest to use the heap here since we're bracketed
* immediately by a pushheap/popheap pair.
*/
size_t bytes = sizeof(int)*numpipestats;
oldpipestats = (int *)zhalloc(bytes);
memcpy(oldpipestats, pipestats, bytes);
}
oargv0 = NULL; starttrapscope();
obreaks = breaks; startpatternscope();
ocontflag = contflag;
oloops = loops; pptab = pparams;
if (trap_state == TRAP_STATE_PRIMED) if (!(flags & PM_UNDEFINED))
trap_return--; scriptname = dupstring(name);
oldlastval = lastval; oldzoptind = zoptind;
oldnumpipestats = numpipestats; oldoptcind = optcind;
if (noreturnval) { if (!isset(POSIXBUILTINS)) {
zoptind = 1;
optcind = 0;
}
/* We need to save the current options even if LOCALOPTIONS is *
* not currently set. That's because if it gets set in the *
* function we need to restore the original options on exit. */
memcpy(saveopts, opts, sizeof(opts));
saveemulation = emulation;
save_sticky = sticky;
if (sticky_emulation_differs(shfunc->sticky)) {
/*
* Function is marked for sticky emulation.
* Enable it now.
*
* We deliberately do not do this if the sticky emulation
* in effect is the same as that requested. This enables
* option setting naturally within emulation environments.
* Note that a difference in EMULATE_FULLY (emulate with
* or without -R) counts as a different environment.
*
* This propagates the sticky emulation to subfunctions.
*/
sticky = sticky_emulation_dup(shfunc->sticky, 1);
emulation = sticky->emulation;
restore_sticky = 1;
installemulation(emulation, opts);
if (sticky->n_on_opts) {
OptIndex *onptr;
for (onptr = sticky->on_opts;
onptr < sticky->on_opts + sticky->n_on_opts;
onptr++)
opts[*onptr] = 1;
}
if (sticky->n_off_opts) {
OptIndex *offptr;
for (offptr = sticky->off_opts;
offptr < sticky->off_opts + sticky->n_off_opts;
offptr++)
opts[*offptr] = 0;
}
/* All emulations start with pattern disables clear */
clearpatterndisables();
} else
restore_sticky = 0;
if (flags & (PM_TAGGED|PM_TAGGED_LOCAL))
opts[XTRACE] = 1;
else if (oflags & PM_TAGGED_LOCAL)
opts[XTRACE] = 0;
ooflags = oflags;
/* /*
* Easiest to use the heap here since we're bracketed * oflags is static, because we compare it on the next recursive
* immediately by a pushheap/popheap pair. * call. Hence also we maintain ooflags for restoring the previous
* value of oflags after the call.
*/ */
size_t bytes = sizeof(int)*numpipestats; oflags = flags;
oldpipestats = (int *)zhalloc(bytes); opts[PRINTEXITVALUE] = 0;
memcpy(oldpipestats, pipestats, bytes); if (doshargs) {
} LinkNode node;
starttrapscope(); node = firstnode(doshargs);
startpatternscope(); pparams = x = (char **) zshcalloc(((sizeof *x) *
(1 + countlinknodes(doshargs))));
pptab = pparams; if (isset(FUNCTIONARGZERO)) {
if (!(flags & PM_UNDEFINED)) oargv0 = argzero;
scriptname = dupstring(name); argzero = ztrdup(getdata(node));
oldzoptind = zoptind; }
oldoptcind = optcind; /* first node contains name regardless of option */
if (!isset(POSIXBUILTINS)) { node = node->next;
zoptind = 1; for (; node; node = node->next, x++)
optcind = 0; *x = ztrdup(getdata(node));
} } else {
pparams = (char **) zshcalloc(sizeof *pparams);
/* We need to save the current options even if LOCALOPTIONS is * if (isset(FUNCTIONARGZERO)) {
* not currently set. That's because if it gets set in the * oargv0 = argzero;
* function we need to restore the original options on exit. */ argzero = ztrdup(argzero);
memcpy(saveopts, opts, sizeof(opts)); }
saveemulation = emulation;
save_sticky = sticky;
if (sticky_emulation_differs(shfunc->sticky)) {
/*
* Function is marked for sticky emulation.
* Enable it now.
*
* We deliberately do not do this if the sticky emulation
* in effect is the same as that requested. This enables
* option setting naturally within emulation environments.
* Note that a difference in EMULATE_FULLY (emulate with
* or without -R) counts as a different environment.
*
* This propagates the sticky emulation to subfunctions.
*/
sticky = sticky_emulation_dup(shfunc->sticky, 1);
emulation = sticky->emulation;
restore_sticky = 1;
installemulation(emulation, opts);
if (sticky->n_on_opts) {
OptIndex *onptr;
for (onptr = sticky->on_opts;
onptr < sticky->on_opts + sticky->n_on_opts;
onptr++)
opts[*onptr] = 1;
} }
if (sticky->n_off_opts) {
OptIndex *offptr;
for (offptr = sticky->off_opts;
offptr < sticky->off_opts + sticky->n_off_opts;
offptr++)
opts[*offptr] = 0;
}
/* All emulations start with pattern disables clear */
clearpatterndisables();
} else
restore_sticky = 0;
if (flags & (PM_TAGGED|PM_TAGGED_LOCAL))
opts[XTRACE] = 1;
else if (oflags & PM_TAGGED_LOCAL)
opts[XTRACE] = 0;
ooflags = oflags;
/*
* oflags is static, because we compare it on the next recursive
* call. Hence also we maintain ooflags for restoring the previous
* value of oflags after the call.
*/
oflags = flags;
opts[PRINTEXITVALUE] = 0;
if (doshargs) {
LinkNode node;
node = firstnode(doshargs);
pparams = x = (char **) zshcalloc(((sizeof *x) *
(1 + countlinknodes(doshargs))));
if (isset(FUNCTIONARGZERO)) {
oargv0 = argzero;
argzero = ztrdup(getdata(node));
}
/* first node contains name regardless of option */
node = node->next;
for (; node; node = node->next, x++)
*x = ztrdup(getdata(node));
} else {
pparams = (char **) zshcalloc(sizeof *pparams);
if (isset(FUNCTIONARGZERO)) {
oargv0 = argzero;
argzero = ztrdup(argzero);
}
}
#ifdef MAX_FUNCTION_DEPTH #ifdef MAX_FUNCTION_DEPTH
if(++funcdepth > MAX_FUNCTION_DEPTH) if(++funcdepth > MAX_FUNCTION_DEPTH)
{ {
zerr("maximum nested function level reached"); zerr("maximum nested function level reached");
goto undoshfunc; goto undoshfunc;
} }
#endif #endif
fstack.name = dupstring(name); fstack.name = dupstring(name);
/*
* The caller is whatever is immediately before on the stack,
* unless we're at the top, in which case it's the script
* or interactive shell name.
*/
fstack.caller = funcstack ? funcstack->name :
dupstring(oargv0 ? oargv0 : argzero);
fstack.lineno = lineno;
fstack.prev = funcstack;
fstack.tp = FS_FUNC;
funcstack = &fstack;
fstack.flineno = shfunc->lineno;
fstack.filename = dupstring(shfunc->filename);
prog = shfunc->funcdef;
if (prog->flags & EF_RUN) {
Shfunc shf;
prog->flags &= ~EF_RUN;
runshfunc(prog, NULL, fstack.name);
if (!(shf = (Shfunc) shfunctab->getnode(shfunctab,
(name = fname)))) {
zwarn("%s: function not defined by file", name);
if (noreturnval)
errflag |= ERRFLAG_ERROR;
else
lastval = 1;
goto doneshfunc;
}
prog = shf->funcdef;
}
runshfunc(prog, wrappers, fstack.name);
doneshfunc:
funcstack = fstack.prev;
#ifdef MAX_FUNCTION_DEPTH
undoshfunc:
--funcdepth;
#endif
if (retflag) {
retflag = 0;
breaks = obreaks;
}
freearray(pparams);
if (oargv0) {
zsfree(argzero);
argzero = oargv0;
}
pparams = pptab;
if (!isset(POSIXBUILTINS)) {
zoptind = oldzoptind;
optcind = oldoptcind;
}
scriptname = oldscriptname;
oflags = ooflags;
endpatternscope(); /* before restoring old LOCALPATTERNS */
if (restore_sticky) {
/* /*
* If we switched to an emulation environment just for * The caller is whatever is immediately before on the stack,
* this function, we interpret the option and emulation * unless we're at the top, in which case it's the script
* switch as being a firewall between environments. * or interactive shell name.
*/ */
memcpy(opts, saveopts, sizeof(opts)); fstack.caller = funcstack ? funcstack->name :
emulation = saveemulation; dupstring(oargv0 ? oargv0 : argzero);
sticky = save_sticky; fstack.lineno = lineno;
} else if (isset(LOCALOPTIONS)) { fstack.prev = funcstack;
/* restore all shell options except PRIVILEGED and RESTRICTED */ fstack.tp = FS_FUNC;
saveopts[PRIVILEGED] = opts[PRIVILEGED]; funcstack = &fstack;
saveopts[RESTRICTED] = opts[RESTRICTED];
memcpy(opts, saveopts, sizeof(opts));
emulation = saveemulation;
} else {
/* just restore a couple. */
opts[XTRACE] = saveopts[XTRACE];
opts[PRINTEXITVALUE] = saveopts[PRINTEXITVALUE];
opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS];
opts[LOCALLOOPS] = saveopts[LOCALLOOPS];
}
if (opts[LOCALLOOPS]) { fstack.flineno = shfunc->lineno;
if (contflag) fstack.filename = dupstring(shfunc->filename);
zwarn("`continue' active at end of function scope");
if (breaks)
zwarn("`break' active at end of function scope");
breaks = obreaks;
contflag = ocontflag;
loops = oloops;
}
endtrapscope(); prog = shfunc->funcdef;
if (prog->flags & EF_RUN) {
Shfunc shf;
if (trap_state == TRAP_STATE_PRIMED) prog->flags &= ~EF_RUN;
trap_return++;
ret = lastval; runshfunc(prog, NULL, fstack.name);
if (noreturnval) {
lastval = oldlastval; if (!(shf = (Shfunc) shfunctab->getnode(shfunctab,
numpipestats = oldnumpipestats; (name = fname)))) {
memcpy(pipestats, oldpipestats, sizeof(int)*numpipestats); zwarn("%s: function not defined by file", name);
} if (noreturnval)
popheap(); errflag |= ERRFLAG_ERROR;
else
lastval = 1;
goto doneshfunc;
}
prog = shf->funcdef;
}
runshfunc(prog, wrappers, fstack.name);
doneshfunc:
funcstack = fstack.prev;
#ifdef MAX_FUNCTION_DEPTH
undoshfunc:
--funcdepth;
#endif
if (retflag) {
retflag = 0;
breaks = obreaks;
}
freearray(pparams);
if (oargv0) {
zsfree(argzero);
argzero = oargv0;
}
pparams = pptab;
if (!isset(POSIXBUILTINS)) {
zoptind = oldzoptind;
optcind = oldoptcind;
}
scriptname = oldscriptname;
oflags = ooflags;
endpatternscope(); /* before restoring old LOCALPATTERNS */
if (restore_sticky) {
/*
* If we switched to an emulation environment just for
* this function, we interpret the option and emulation
* switch as being a firewall between environments.
*/
memcpy(opts, saveopts, sizeof(opts));
emulation = saveemulation;
sticky = save_sticky;
} else if (isset(LOCALOPTIONS)) {
/* restore all shell options except PRIVILEGED and RESTRICTED */
saveopts[PRIVILEGED] = opts[PRIVILEGED];
saveopts[RESTRICTED] = opts[RESTRICTED];
memcpy(opts, saveopts, sizeof(opts));
emulation = saveemulation;
} else {
/* just restore a couple. */
opts[XTRACE] = saveopts[XTRACE];
opts[PRINTEXITVALUE] = saveopts[PRINTEXITVALUE];
opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS];
opts[LOCALLOOPS] = saveopts[LOCALLOOPS];
}
if (opts[LOCALLOOPS]) {
if (contflag)
zwarn("`continue' active at end of function scope");
if (breaks)
zwarn("`break' active at end of function scope");
breaks = obreaks;
contflag = ocontflag;
loops = oloops;
}
endtrapscope();
if (trap_state == TRAP_STATE_PRIMED)
trap_return++;
ret = lastval;
if (noreturnval) {
lastval = oldlastval;
numpipestats = oldnumpipestats;
memcpy(pipestats, oldpipestats, sizeof(int)*numpipestats);
}
} OLDHEAPS;
unqueue_signals(); unqueue_signals();