* 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.)
This commit is contained in:
parent
2db91358de
commit
a9e7dc1081
|
@ -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));
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in New Issue