[Stackless] I need Input (was: Stackless breaks generators that do not yield)
Sune Kirkeby
sune at mel.interspace.dk
Tue Mar 18 22:58:03 CET 2003
[ Christian Tismer ]
> Christian Tismer wrote:
> ...
>
> >a refine the extra flags, such that generator
> > frames are never decreffed but by the gen object
> >b remove the decreffing code from frame_dispatch
> > and revert the policy to "a frame has to take
> > care for itself", while keeping generators untouched
> >c replace the missing concept of callers by tiny
> > extra frames, which take care of frame deallocation.
> >d ??? other ideas ???
> >
> >c seems to be quite a clean solution, but maybe the
> > extra effort to put extra frames on the stack
> > might be a bit much?
> >
> >I'm not sure which path to follow.
> >Can a few people please let me know their opinion?
>
> Since nobody gave me his opinions,
> I decided for version a and implemented it.
I would have given my .2e earlier, but I was busy hacking away on
a patch, that implements what I think you meant by option (b). The
patch removes the is_done flag, and add normal "you own it, you
DECREF it rules" to frames.
This means there are three places frames need to be DECREFed, (1) in
gen_dealloc, (2) in PyEval_EvalFrame when a frame is reentered after
a function-call (the Py_UnwindToken'ing kind) and (3) in
PyEval_EvalCodeEx.
The patched stackless passes all tests but minidom, but I can't
figure out why it fails (I suspect the test or the expected
output-file to be b0rked, since neither stock 2.2.2 nor the patched
stackless produce any output for the test...) And I can't seem to
trigger any memory-leaks with my code -- which is a first :)
I'll have a look at your code rsn(tm). Comments?
--
Sune Kirkeby | strange women lying in ponds distributing swords
| is no basis for a system of government. Supreme
| executive power derives from a mandate from the
| masses, not from some farcical aquatic ceremony.
-------------- next part --------------
? python
? typescript
? Lib/distutils/__init__.pyc
? Lib/distutils/archive_util.pyc
? Lib/distutils/ccompiler.pyc
? Lib/distutils/cmd.pyc
? Lib/distutils/core.pyc
? Lib/distutils/dep_util.pyc
? Lib/distutils/dir_util.pyc
? Lib/distutils/dist.pyc
? Lib/distutils/errors.pyc
? Lib/distutils/extension.pyc
? Lib/distutils/fancy_getopt.pyc
? Lib/distutils/file_util.pyc
? Lib/distutils/msvccompiler.pyc
? Lib/distutils/spawn.pyc
? Lib/distutils/sysconfig.pyc
? Lib/distutils/text_file.pyc
? Lib/distutils/unixccompiler.pyc
? Lib/distutils/util.pyc
? Lib/distutils/command/__init__.pyc
? Lib/distutils/command/build.pyc
? Lib/distutils/command/build_ext.pyc
? Lib/distutils/command/build_scripts.pyc
? Lib/distutils/command/install.pyc
? Lib/distutils/command/install_lib.pyc
? Lib/distutils/command/install_scripts.pyc
Index: Python/ceval.c
===================================================================
RCS file: /home/cvs/stackless/src/Python/ceval.c,v
retrieving revision 1.25
diff -u -b -r1.25 ceval.c
--- Python/ceval.c 2003/03/17 15:54:33 1.25
+++ Python/ceval.c 2003/03/18 21:33:12
@@ -112,9 +112,6 @@
Py_DECREF(f);
return NULL;
}
-#ifdef STACKLESS
- Py_INCREF(f);
-#endif
gen->gi_frame = f;
gen->gi_running = 0;
return (PyObject *)gen;
@@ -129,12 +126,7 @@
static void
gen_dealloc(genobject *gen)
{
-#ifdef STACKLESS
- if(! gen->gi_frame->f_flags.is_done) {
Py_DECREF(gen->gi_frame);
- }
-#endif
- Py_DECREF(gen->gi_frame);
PyObject_Del(gen);
}
@@ -687,6 +679,15 @@
w = NULL;
#ifdef STACKLESS
+ if (f->f_flags.reentering) {
+ PyObject *of;
+ f->f_flags.reentering = 0;
+ ++tstate->recursion_depth;
+ of = POP(); /* Py_DECREF(POP()) seems to break really */
+ Py_DECREF(of); /* spectacularly for me?! */
+ --tstate->recursion_depth;
+ }
+
/* see if we are expecting a result */
if (f->f_flags.wants_value) {
--tstate->recursion_depth; /* this was a return */
@@ -2419,10 +2420,6 @@
v = POP();
Py_XDECREF(v);
}
-#ifdef STACKLESS
- /* in all cases but yielding, the frame is done */
- f->f_flags.is_done = 1;
-#endif
}
if (why != WHY_RETURN && why != WHY_YIELD)
@@ -2464,6 +2461,7 @@
#ifdef STACKLESS
stackless_call:
+ PUSH((PyObject*)tstate->frame);
f->f_flags.wants_value = 1;
f->f_flags.reentering = 1;
f->f_stacktop = stack_pointer;
@@ -2743,6 +2741,7 @@
PyThreadState *tstate = PyThreadState_GET();
PyFrameObject *f = tstate->frame;
retval = slp_eval_frame(f);
+ Py_DECREF(f);
}
return retval;
}
Index: Stackless/stackless_frame.h
===================================================================
RCS file: /home/cvs/stackless/src/Stackless/stackless_frame.h,v
retrieving revision 1.15
diff -u -b -r1.15 stackless_frame.h
--- Stackless/stackless_frame.h 2003/03/17 15:54:33 1.15
+++ Stackless/stackless_frame.h 2003/03/18 21:33:13
@@ -13,7 +13,6 @@
unsigned int wants_value: 1;
unsigned int drops_value: 1;
unsigned int reentering: 1;
- unsigned int is_done: 1;
unsigned int locked: 1;
} PyFrameFlagStruc;
Index: Stackless/stacklesseval.c
===================================================================
RCS file: /home/cvs/stackless/src/Stackless/stacklesseval.c,v
retrieving revision 1.89
diff -u -b -r1.89 stacklesseval.c
--- Stackless/stacklesseval.c 2003/03/17 15:54:33 1.89
+++ Stackless/stacklesseval.c 2003/03/18 21:33:14
@@ -381,11 +381,6 @@
while (1) {
result = f->f_execute(f, result);
- if (f->f_flags.is_done) {
- ++ts->recursion_depth;
- Py_DECREF(f);
- --ts->recursion_depth;
- }
f = ts->frame;
if (f==fprev)
break;
More information about the Stackless
mailing list