summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1992-10-18 18:53:57 (GMT)
committerGuido van Rossum <guido@python.org>1992-10-18 18:53:57 (GMT)
commita9e7dc10816dcf5eda63d3ef00930ef9d55e0675 (patch)
tree5454bc7a52a71fe9639ec7f0cef856c413b25157
parent2db91358def94cf8081f27b736988320d14eba39 (diff)
downloadcpython-a9e7dc10816dcf5eda63d3ef00930ef9d55e0675.zip
cpython-a9e7dc10816dcf5eda63d3ef00930ef9d55e0675.tar.gz
cpython-a9e7dc10816dcf5eda63d3ef00930ef9d55e0675.tar.bz2
* 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.)
-rw-r--r--Include/frameobject.h4
-rw-r--r--Modules/flmodule.c7
-rw-r--r--Objects/frameobject.c75
-rw-r--r--Parser/parser.h2
-rw-r--r--Python/bltinmodule.c12
-rw-r--r--Python/ceval.c20
-rw-r--r--Python/pythonrun.c49
7 files changed, 150 insertions, 19 deletions
diff --git a/Include/frameobject.h b/Include/frameobject.h
index e1f8190..dd36468 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 34f0121..dca39ad 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 a68704c..c7b5ddf 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 72aa927..2c0e327 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 9ba07af..18fae5c 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -78,6 +78,17 @@ builtin_chr(self, args)
}
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;
object *args;
@@ -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 4637d35..d3a732a 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 90a4294..1bcc083 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 <signal.h>
+#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 */