@@ -31,9 +31,11 @@ namespace greenlet
3131 _PyErr_StackItem* exc_info;
3232 _PyErr_StackItem exc_state;
3333#else
34- OwnedObject exc_type;
3534 OwnedObject exc_value;
35+ #if !GREENLET_PY311
36+ OwnedObject exc_type;
3637 OwnedObject exc_traceback;
38+ #endif
3739#endif
3840 public:
3941 ExceptionState ();
@@ -133,6 +135,12 @@ namespace greenlet
133135 int use_tracing;
134136#endif
135137 int recursion_depth;
138+ #if GREENLET_PY311
139+ _interpreter_frame *current_frame;
140+ _PyStackChunk *datastack_chunk;
141+ PyObject **datastack_top;
142+ PyObject **datastack_limit;
143+ #endif
136144
137145 public:
138146 PythonState ();
@@ -640,63 +648,79 @@ void ExceptionState::operator>>(PyThreadState *const tstate) G_NOEXCEPT
640648void ExceptionState::clear () G_NOEXCEPT
641649{
642650 this ->exc_info = nullptr ;
643- this ->exc_state .exc_type = nullptr ;
644651 this ->exc_state .exc_value = nullptr ;
652+ #if !GREENLET_PY311
653+ this ->exc_state .exc_type = nullptr ;
645654 this ->exc_state .exc_traceback = nullptr ;
655+ #endif
646656 this ->exc_state .previous_item = nullptr ;
647657}
648658
649659int ExceptionState::tp_traverse (visitproc visit, void * arg) G_NOEXCEPT
650660{
651- Py_VISIT (this ->exc_state .exc_type );
652661 Py_VISIT (this ->exc_state .exc_value );
662+ #if !GREENLET_PY311
663+ Py_VISIT (this ->exc_state .exc_type );
653664 Py_VISIT (this ->exc_state .exc_traceback );
665+ #endif
654666 return 0 ;
655667}
656668
657669void ExceptionState::tp_clear () G_NOEXCEPT
658670{
659- Py_CLEAR (this ->exc_state .exc_type );
660671 Py_CLEAR (this ->exc_state .exc_value );
672+ #if !GREENLET_PY311
673+ Py_CLEAR (this ->exc_state .exc_type );
661674 Py_CLEAR (this ->exc_state .exc_traceback );
675+ #endif
662676}
663677#else
664678// ********** Python 3.6 and below ********
665679void ExceptionState::operator <<(const PyThreadState *const tstate) G_NOEXCEPT
666680{
667- this ->exc_type .steal (tstate->exc_type );
668681 this ->exc_value .steal (tstate->exc_value );
682+ #if !GREENLET_PY311
683+ this ->exc_type .steal (tstate->exc_type );
669684 this ->exc_traceback .steal (tstate->exc_traceback );
685+ #endif
670686}
671687
672688void ExceptionState::operator >>(PyThreadState *const tstate) G_NOEXCEPT
673689{
674- tstate->exc_type <<= this ->exc_type ;
675690 tstate->exc_value <<= this ->exc_value ;
691+ #if !GREENLET_PY311
692+ tstate->exc_type <<= this ->exc_type ;
676693 tstate->exc_traceback <<= this ->exc_traceback ;
694+ #endif
677695 this ->clear ();
678696}
679697
680698void ExceptionState::clear () G_NOEXCEPT
681699{
682- this ->exc_type = nullptr ;
683700 this ->exc_value = nullptr ;
701+ #if !GREENLET_PY311
702+ this ->exc_type = nullptr ;
684703 this ->exc_traceback = nullptr ;
704+ #endif
685705}
686706
687707int ExceptionState::tp_traverse (visitproc visit, void * arg) G_NOEXCEPT
688708{
689- Py_VISIT (this ->exc_type .borrow ());
690709 Py_VISIT (this ->exc_value .borrow ());
710+ #if !GREENLET_PY311
711+ Py_VISIT (this ->exc_type .borrow ());
691712 Py_VISIT (this ->exc_traceback .borrow ());
713+ #endif
692714 return 0 ;
693715}
694716
695717void ExceptionState::tp_clear () G_NOEXCEPT
696718{
697- this ->exc_type .CLEAR ();
698719 this ->exc_value .CLEAR ();
720+ #if !GREENLET_PY311
721+ this ->exc_type .CLEAR ();
699722 this ->exc_traceback .CLEAR ();
723+ #endif
700724}
701725#endif
702726
@@ -710,6 +734,12 @@ PythonState::PythonState()
710734 ,use_tracing(0 )
711735#endif
712736 ,recursion_depth(0 )
737+ #if GREENLET_PY311
738+ ,current_frame(nullptr )
739+ ,datastack_chunk(nullptr )
740+ ,datastack_top(nullptr )
741+ ,datastack_limit(nullptr )
742+ #endif
713743{
714744#if GREENLET_USE_CFRAME
715745 /*
@@ -767,8 +797,6 @@ PythonState::PythonState()
767797
768798void PythonState::operator <<(const PyThreadState *const tstate) G_NOEXCEPT
769799{
770- this ->recursion_depth = tstate->recursion_depth ;
771- this ->_top_frame .steal (tstate->frame );
772800#if GREENLET_PY37
773801 this ->_context .steal (tstate->context );
774802#endif
@@ -786,12 +814,23 @@ void PythonState::operator<<(const PyThreadState *const tstate) G_NOEXCEPT
786814 this ->cframe = tstate->cframe ;
787815 this ->use_tracing = tstate->cframe ->use_tracing ;
788816#endif
817+ #if GREENLET_PY311
818+ this ->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining ;
819+ this ->current_frame = tstate->cframe ->current_frame ;
820+ this ->datastack_chunk = tstate->datastack_chunk ;
821+ this ->datastack_top = tstate->datastack_top ;
822+ this ->datastack_limit = tstate->datastack_limit ;
823+ PyFrameObject *frame = PyThreadState_GetFrame ((PyThreadState *)tstate);
824+ Py_XDECREF (frame); // PyThreadState_GetFrame gives us a new reference.
825+ this ->_top_frame .steal (frame);
826+ #else
827+ this ->recursion_depth = tstate->recursion_depth ;
828+ this ->_top_frame .steal (tstate->frame );
829+ #endif
789830}
790831
791832void PythonState::operator >>(PyThreadState *const tstate) G_NOEXCEPT
792833{
793- tstate->recursion_depth = this ->recursion_depth ;
794- tstate->frame = this ->_top_frame .relinquish_ownership ();
795834#if GREENLET_PY37
796835 tstate->context = this ->_context .relinquish_ownership ();
797836 /* Incrementing this value invalidates the contextvars cache,
@@ -808,6 +847,17 @@ void PythonState::operator>>(PyThreadState *const tstate) G_NOEXCEPT
808847 */
809848 tstate->cframe ->use_tracing = this ->use_tracing ;
810849#endif
850+ #if GREENLET_PY311
851+ tstate->recursion_remaining = tstate->recursion_limit - this ->recursion_depth ;
852+ tstate->cframe ->current_frame = this ->current_frame ;
853+ tstate->datastack_chunk = this ->datastack_chunk ;
854+ tstate->datastack_top = this ->datastack_top ;
855+ tstate->datastack_limit = this ->datastack_limit ;
856+ this ->_top_frame .relinquish_ownership ();
857+ #else
858+ tstate->frame = this ->_top_frame .relinquish_ownership ();
859+ tstate->recursion_depth = this ->recursion_depth ;
860+ #endif
811861}
812862
813863void PythonState::will_switch_from (PyThreadState *const origin_tstate) G_NOEXCEPT
@@ -824,7 +874,11 @@ void PythonState::will_switch_from(PyThreadState *const origin_tstate) G_NOEXCEP
824874void PythonState::set_initial_state (const PyThreadState* const tstate) G_NOEXCEPT
825875{
826876 this ->_top_frame = nullptr ;
877+ #if GREENLET_PY311
878+ this ->recursion_depth = tstate->recursion_limit - tstate->recursion_remaining ;
879+ #else
827880 this ->recursion_depth = tstate->recursion_depth ;
881+ #endif
828882}
829883// TODO: Better state management about when we own the top frame.
830884int PythonState::tp_traverse (visitproc visit, void * arg, bool own_top_frame) G_NOEXCEPT
0 commit comments