From a9e7dc10816dcf5eda63d3ef00930ef9d55e0675 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Sun, 18 Oct 1992 18:53:57 +0000 Subject: [PATCH] * bltinmodule.c: added built-in function cmp(a, b) * flmodule.c: added {do,check}_only_forms to fl's list of functions; and don't print a message when an unknown object is returned. * pythonrun.c: catch SIGHUP and SIGTERM to do essential cleanup. * Made jpegmodule.c smaller by using getargs() and mkvalue() consistently. * Increased parser stack size to 500 in parser.h. * Implemented custom allocation of stack frames to frameobject.c and added dynamic stack overflow checks (value stack only) to ceval.c. (There seems to be a bug left: sometimes stack traces don't make sense.) --- Include/frameobject.h | 4 +++ Modules/flmodule.c | 7 ++-- Objects/frameobject.c | 75 +++++++++++++++++++++++++++++++++++++------ Parser/parser.h | 2 +- Python/bltinmodule.c | 12 +++++++ Python/ceval.c | 20 ++++++++++++ Python/pythonrun.c | 49 +++++++++++++++++++++++++--- 7 files changed, 150 insertions(+), 19 deletions(-) diff --git a/Include/frameobject.h b/Include/frameobject.h index e1f819017ad..dd36468ec16 100644 --- a/Include/frameobject.h +++ b/Include/frameobject.h @@ -81,3 +81,7 @@ frameobject * newframeobject PROTO( void setup_block PROTO((frameobject *, int, int, int)); block *pop_block PROTO((frameobject *)); + +/* Extend the value stack */ + +object **extend_stack PROTO((frameobject *, int, int)); diff --git a/Modules/flmodule.c b/Modules/flmodule.c index 34f01218cdd..dca39ad646b 100644 --- a/Modules/flmodule.c +++ b/Modules/flmodule.c @@ -2078,10 +2078,7 @@ forms_do_or_check_forms(dummy, args, func) } g = findgeneric(generic); if (g == NULL) { - /* XXX What kind of weird object is this? */ - /* XXX Maybe caused by a bug here */ - fprintf(stderr, "weird object: class %d, label '%s'\n", - generic->objclass, generic->label); + /* Object not known to us (some dialogs cause this) */ continue; /* Ignore it */ } if (g->ob_callback == NULL) { @@ -2572,7 +2569,9 @@ static struct methodlist forms_methods[] = { {"getmcolor", forms_getmcolor}, /* interaction */ {"do_forms", forms_do_forms}, + {"do_only_forms", forms_do_only_forms}, {"check_forms", forms_check_forms}, + {"check_only_forms", forms_check_only_forms}, {"set_event_call_back", forms_set_event_call_back}, /* goodies */ {"show_message", forms_show_message}, diff --git a/Objects/frameobject.c b/Objects/frameobject.c index a68704ceeda..c7b5ddf58ef 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -51,6 +51,29 @@ frame_getattr(f, name) return getmember((char *)f, frame_memberlist, name); } +/* Stack frames are allocated and deallocated at a considerable rate. + In an attempt to improve the speed of function calls, we maintain a + separate free list of stack frames (just like integers are + allocated in a special way -- see intobject.c). When a stack frame + is on the free list, only the following members have a meaning: + ob_type == &Frametype + f_back next item on free list, or NULL + f_nvalues size of f_valuestack + f_valuestack array of (f_nvalues+1) object pointers, or NULL + f_nblocks size of f_blockstack + f_blockstack array of (f_nblocks+1) blocks, or NULL + Note that the value and block stacks are preserved -- this can save + another malloc() call or two (and two free() calls as well!). + Also note that, unlike for integers, each frame object is a + malloc'ed object in its own right -- it is only the actual calls to + malloc() that we are trying to save here, not the administration. + After all, while a typical program may make millions of calls, a + call depth of more than 20 or 30 is probably already exceptional + unless the program contains run-away recursion. I hope. +*/ + +static frameobject *free_list = NULL; + static void frame_dealloc(f) frameobject *f; @@ -59,9 +82,8 @@ frame_dealloc(f) XDECREF(f->f_code); XDECREF(f->f_globals); XDECREF(f->f_locals); - XDEL(f->f_valuestack); - XDEL(f->f_blockstack); - DEL(f); + f->f_back = free_list; + free_list = f; } typeobject Frametype = { @@ -99,7 +121,17 @@ newframeobject(back, code, globals, locals, nvalues, nblocks) err_badcall(); return NULL; } - f = NEWOBJ(frameobject, &Frametype); + if (free_list == NULL) { + f = NEWOBJ(frameobject, &Frametype); + f->f_nvalues = f->f_nblocks = 0; + f->f_valuestack = NULL; + f->f_blockstack = NULL; + } + else { + f = free_list; + free_list = free_list->f_back; + NEWREF(f); + } if (f != NULL) { if (back) INCREF(back); @@ -110,22 +142,45 @@ newframeobject(back, code, globals, locals, nvalues, nblocks) f->f_globals = globals; INCREF(locals); f->f_locals = locals; - f->f_valuestack = NEW(object *, nvalues+1); - f->f_blockstack = NEW(block, nblocks+1); - f->f_nvalues = nvalues; - f->f_nblocks = nblocks; + if (nvalues > f->f_nvalues || f->f_valuestack == NULL) { + XDEL(f->f_valuestack); + f->f_valuestack = NEW(object *, nvalues+1); + f->f_nvalues = nvalues; + } + if (nblocks > f->f_nblocks || f->f_blockstack == NULL) { + XDEL(f->f_blockstack); + f->f_blockstack = NEW(block, nblocks+1); + f->f_nblocks = nblocks; + } f->f_iblock = 0; + f->f_lasti = 0; + f->f_lineno = -1; if (f->f_valuestack == NULL || f->f_blockstack == NULL) { err_nomem(); DECREF(f); f = NULL; } - f->f_lasti = 0; - f->f_lineno = -1; } return f; } +object ** +extend_stack(f, level, incr) + frameobject *f; + int level; + int incr; +{ + f->f_nvalues = level + incr + 10; + f->f_valuestack = + (object **) realloc((ANY *)f->f_valuestack, + sizeof(object *) * (f->f_nvalues + 1)); + if (f->f_valuestack == NULL) { + err_nomem(); + return NULL; + } + return f->f_valuestack + level; +} + /* Block management */ void diff --git a/Parser/parser.h b/Parser/parser.h index 72aa9277f19..2c0e327e0e1 100644 --- a/Parser/parser.h +++ b/Parser/parser.h @@ -24,7 +24,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* Parser interface */ -#define MAXSTACK 100 +#define MAXSTACK 500 typedef struct _stackentry { int s_state; /* State in current DFA */ diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 9ba07af3a42..18fae5ca75e 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -77,6 +77,17 @@ builtin_chr(self, args) return newsizedstringobject(s, 1); } +static object * +builtin_cmp(self, args) + object *self; + object *args; +{ + object *a, *b; + if (!getargs(args, "(OO)", &a, &b)) + return NULL; + return newintobject((long)cmpobject(a, b)); +} + static object * builtin_coerce(self, args) object *self; @@ -608,6 +619,7 @@ static struct methodlist builtin_methods[] = { {"abs", builtin_abs}, {"apply", builtin_apply}, {"chr", builtin_chr}, + {"cmp", builtin_cmp}, {"coerce", builtin_coerce}, {"dir", builtin_dir}, {"divmod", builtin_divmod}, diff --git a/Python/ceval.c b/Python/ceval.c index 4637d35f7ef..d3a732a62ee 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -204,6 +204,9 @@ eval_code(co, globals, locals, arg) #define BASIC_PUSH(v) (*stack_pointer++ = (v)) #define BASIC_POP() (*--stack_pointer) +#define CHECK_STACK(n) (STACK_LEVEL() + (n) < f->f_nvalues || \ + (stack_pointer = extend_stack(f, STACK_LEVEL(), n))) + #ifdef LLTRACE #define PUSH(v) (BASIC_PUSH(v), lltrace && prtrace(TOP(), "push")) #define POP() (lltrace && prtrace(TOP(), "pop"), BASIC_POP()) @@ -324,6 +327,11 @@ eval_code(co, globals, locals, arg) } #endif + if (!CHECK_STACK(3)) { + x = NULL; + break; + } + /* Main switch on opcode */ switch (opcode) { @@ -763,6 +771,10 @@ eval_code(co, globals, locals, arg) x = gettupleslice(v, oparg, gettuplesize(v)); if (x != NULL) { PUSH(x); + if (!CHECK_STACK(oparg)) { + x = NULL; + break; + } for (; --oparg >= 0; ) { w = gettupleitem(v, oparg); INCREF(w); @@ -858,6 +870,10 @@ eval_code(co, globals, locals, arg) why = WHY_EXCEPTION; } else { + if (!CHECK_STACK(oparg)) { + x = NULL; + break; + } for (; --oparg >= 0; ) { w = gettupleitem(v, oparg); INCREF(w); @@ -879,6 +895,10 @@ eval_code(co, globals, locals, arg) why = WHY_EXCEPTION; } else { + if (!CHECK_STACK(oparg)) { + x = NULL; + break; + } for (; --oparg >= 0; ) { w = getlistitem(v, oparg); INCREF(w); diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 90a429408c0..1bcc083b61a 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -38,10 +38,21 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "pythonrun.h" #include "import.h" +#ifdef unix +#define HANDLE_SIGNALS +#endif + +#ifdef HANDLE_SIGNALS +#include +#include "sigtype.h" +#endif + extern char *getpythonpath(); extern grammar gram; /* From graminit.c */ +void initsigs(); /* Forward */ + int debugging; /* Needed by parser.c */ int verbose; /* Needed by import.c */ @@ -67,10 +78,10 @@ initall() initsys(); initcalls(); /* Configuration-dependent initializations */ - - initintr(); /* For intrcheck() */ setpythonpath(getpythonpath()); + + initsigs(); /* Signal handling stuff, including initintr() */ } /* Parse input from a file and execute it */ @@ -372,8 +383,7 @@ extern int threads_started; #endif void -goaway(sts) - int sts; +cleanup() { object *exitfunc = sysget("exitfunc"); @@ -395,6 +405,13 @@ goaway(sts) } flushline(); +} + +void +goaway(sts) + int sts; +{ + cleanup(); #ifdef USE_THREAD @@ -433,6 +450,30 @@ goaway(sts) /*NOTREACHED*/ } +#ifdef HANDLE_SIGNALS +SIGTYPE +sighandler(sig) + int sig; +{ + signal(sig, SIG_DFL); /* Don't catch recursive signals */ + cleanup(); /* Do essential clean-up */ + kill(getpid(), sig); /* Pretend the signal killed us */ + /*NOTREACHED*/ +} +#endif + +void +initsigs() +{ + initintr(); +#ifdef HANDLE_SIGNALS + if (signal(SIGHUP, SIG_IGN) != SIG_IGN) + signal(SIGHUP, sighandler); + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) + signal(SIGTERM, sighandler); +#endif +} + #ifdef TRACE_REFS /* Ask a yes/no question */