[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