Bob Ippolito wrote:
I'm not quite sure you are up to date on how Stackless 3.0 works. The assembly code is only there to facilitate "hard switching", which is only required to do tasklet switching in the face of some C extension that doesn't know about Stackless.
Yes, that was my understanding. "Some C extensions" includes Tcl and COM, right? Unless I'm mistaken, it also includes map, filter, and .encode/.decode of unicode objects (or any other C module that calls back into Python, except for tasklet mechanism of stackless itself).
In these cases, copying out the stack will break the exception chain that the Visual C++ compiler creates through the FS segment, so that an attempt to throw an exception will cause a program crash, right?
All pure Python code and almost all code built-in to Python goes through "soft switching", which is implemented in pure C with no stack tricks or anything.
What is the control flow for, say, the builtin map() function?
Stackless would still be a very useful addition to Python even when "hard switching" is not available.
That is the point I made at the beginning of this thread: Python is currently not stackless because nobody has contributed a patch recently to make it so. A patch that takes recursion out of eval_frame might alone be valuable, but hasn't been contributed.
Alternatively, Armin believes that Stackless "hard switching" can actually be implemented in mostly-platform-neutral C (either by setjmp/longjmp or alloca hacks, I forget which)
It is setjmp/longjmp. I have implemented a coroutine library on top of setjmp/longjmp myself, so I am well aware of the implications.
I'm also not sure how it could "break C++ exception handling" in scenarios where it wouldn't be broken anyway. I'd like to see a test of that that passes under regular Python but fails in Stackless for this.
The VC++ exception mechanism puts a linked chain of exception frames on the stack, where, at the beginning of each function, the stack pointer is stored at FS:18 (or some such), and the old value of FS:18 is stored on the stack. Then, when an exception occurs, this linked list is used to traverse the stack. If multiple stacks are used in a single thread, then this linked list gets messed up.
Without trying, I think the following call chain might cause a crash if Stackless is compiled with exception handling on:
Py-func1() -> C-func1() -> Py-func2() -> switch to new tasklet Py-func3() -> C-func2() -> throw exception()