aboutsummaryrefslogtreecommitdiff
path: root/pd/src/m_binbuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'pd/src/m_binbuf.c')
-rw-r--r--pd/src/m_binbuf.c92
1 files changed, 70 insertions, 22 deletions
diff --git a/pd/src/m_binbuf.c b/pd/src/m_binbuf.c
index 69580741..c2ebd2ca 100644
--- a/pd/src/m_binbuf.c
+++ b/pd/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)
@@ -959,7 +1007,7 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
atom_getfloatarg(2, natom, nextmess),
atom_getfloatarg(5, natom, nextmess) -
atom_getfloatarg(3, natom, nextmess),
- (float)sys_defaultfont);
+ (t_float)sys_defaultfont);
}
}
if (!strcmp(first, "#P"))
@@ -1042,7 +1090,7 @@ static t_binbuf *binbuf_convert(t_binbuf *oldb, int maxtopd)
}
else if (!strcmp(second, "slider"))
{
- float inc = atom_getfloatarg(7, natom, nextmess);
+ t_float inc = atom_getfloatarg(7, natom, nextmess);
if (inc <= 0)
inc = 1;
binbuf_addv(newb, "ssffsffffffsssfffffffff;",