From 4f257df8ed7f467178c5a23f00048d72246d1b8c Mon Sep 17 00:00:00 2001 From: Miller Puckette <msp@ucsd.edu> Date: Thu, 13 Dec 2007 10:41:16 -0800 Subject: [PATCH] tighter message stack allocation --- src/m_binbuf.c | 88 ++++++++++++++++++++++++++++++++++++++------------ src/notes.txt | 3 +- 2 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/m_binbuf.c b/src/m_binbuf.c index 69580741a..3d909a75b 100644 --- a/src/m_binbuf.c +++ b/src/m_binbuf.c @@ -387,9 +387,6 @@ void binbuf_restore(t_binbuf *x, int argc, t_atom *argv) x->b_n = newsize; } - -#define MSTACKSIZE 10000 /* FIXME -- make this grow as needed */ - void binbuf_print(t_binbuf *x) { int i, startedpost = 0, newline = 1; @@ -531,13 +528,70 @@ done: return (gensym(buf2)); } +#define SMALLMSG 5 +#define HUGEMSG 1000 +#ifdef MSW +#include <malloc.h> +#else +#include <alloca.h> +#endif +#if HAVE_ALLOCA +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < HUGEMSG ? \ + alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom)))) +#define ATOMS_FREEA(x, n) ( \ + ((n) < HUGEMSG || (freebytes((x), (n) * sizeof(t_atom)), 0))) +#else +#define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)getbytes((n) * sizeof(t_atom))) +#define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom))) +#endif + void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) { - static t_atom mstack[MSTACKSIZE], *msp = mstack, *ems = mstack+MSTACKSIZE; - t_atom *stackwas = msp; + t_atom smallstack[SMALLMSG], *mstack, *msp; t_atom *at = x->b_vec; int ac = x->b_n; - int nargs; + int nargs, maxnargs = 0; + if (ac <= SMALLMSG) + mstack = smallstack; + else + { +#if 1 + /* count number of args in biggest message. The wierd + treatment of "pd_objectmaker" is because when the message + goes out to objectmaker, commas and semis are passed + on as regular args (see below). We're tacitly assuming here + that the pd_objectmaker target can't come up via a named + destination in the message, only because the original "target" + points there. */ + if (target == &pd_objectmaker) + maxnargs = ac; + else + { + int i, j = (target ? 0 : -1); + for (i = 0; i < ac; i++) + { + if (at[i].a_type == A_SEMI) + j = -1; + else if (at[i].a_type == A_COMMA) + j = 0; + else if (++j > maxnargs) + maxnargs = j; + } + } + if (maxnargs <= SMALLMSG) + mstack = smallstack; + else ATOMS_ALLOCA(mstack, maxnargs); +#else + /* just pessimistically allocate enough to hold everything + at once. This turned out to run slower in a simple benchmark + I tried, perhaps because the extra memory allocation + hurt the cache hit rate. */ + maxnargs = ac; + ATOMS_ALLOCA(mstack, maxnargs); +#endif + + } + msp = mstack; while (1) { t_pd *nexttarget; @@ -597,11 +651,6 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) { t_symbol *s9; if (!ac) goto gotmess; - if (msp >= ems) - { - error("message stack overflow"); - goto broken; - } switch (at->a_type) { case A_SEMI: @@ -667,27 +716,26 @@ void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv) gotmess: if (nargs) { - switch (stackwas->a_type) + switch (mstack->a_type) { case A_SYMBOL: - typedmess(target, stackwas->a_w.w_symbol, nargs-1, stackwas+1); + typedmess(target, mstack->a_w.w_symbol, nargs-1, mstack+1); break; case A_FLOAT: - if (nargs == 1) pd_float(target, stackwas->a_w.w_float); - else pd_list(target, 0, nargs, stackwas); + if (nargs == 1) pd_float(target, mstack->a_w.w_float); + else pd_list(target, 0, nargs, mstack); break; } } - msp = stackwas; + msp = mstack; if (!ac) break; target = nexttarget; at++; ac--; } - - return; -broken: - msp = stackwas; +broken: + if (maxnargs > SMALLMSG) + ATOMS_FREEA(mstack, maxnargs); } static int binbuf_doopen(char *s, int mode) diff --git a/src/notes.txt b/src/notes.txt index 3da075642..472487c20 100644 --- a/src/notes.txt +++ b/src/notes.txt @@ -1,6 +1,7 @@ ---------------- dolist -------------------- fixed crash bug closing patches with open GOPs fixed PC device counting problem (first device invoked by -audiodev 0) +fixed MSTACKSIZE limitation in m_binbuf.c test: compile on various versions of linux @@ -19,7 +20,6 @@ problems: check real-time gaps in writesf~ fix declare to update current patch when changed objects on GOP don't erase if you edit the GOP while they're showing -MSTACKSIZE limitation in m_binbuf.c add -stack option to make 'regular' stack larger TK menu on Windows says "wish" help browser broke on Panurge @@ -36,7 +36,6 @@ when retyping abstractions, offer to save dirty one should linux stop grabbing focus on vis? Is there a way to detect whether the mouse is in a window when it opens? arrays that don't fit in bounds don't update (same as red rectangle problem?) -look in d_resample.pd to understand inlet~ upsampling... patcher inlets don't deal with scalars (zbug.pd) check if there's a problem loading libs on startup if superuser read xx.txt in "bad" gives warnings -- GitLab