4
4
#include "internal/pystate.h"
5
5
#include "internal/context.h"
6
6
#include "internal/hamt.h"
7
+ #include "core/stackless_impl.h"
8
+ #include "pickling/prickelpit.h"
7
9
8
10
9
11
#define CONTEXT_FREELIST_MAXLEN 255
@@ -562,10 +564,33 @@ _contextvars_Context_copy_impl(PyContext *self)
562
564
}
563
565
564
566
567
+ #ifdef STACKLESS
568
+ static PyObject * context_run_callback (PyFrameObject * f , int exc , PyObject * result )
569
+ {
570
+ PyCFrameObject * cf = (PyCFrameObject * )f ;
571
+ assert (PyContext_CheckExact (cf -> ob1 ));
572
+ PyContext * context = (PyContext * )cf -> ob1 ;
573
+ cf -> ob1 = NULL ;
574
+
575
+ if (PyContext_Exit (context )) {
576
+ Py_CLEAR (result );
577
+ }
578
+
579
+ Py_DECREF (context );
580
+ SLP_STORE_NEXT_FRAME (PyThreadState_GET (), cf -> f_back );
581
+ return result ;
582
+ }
583
+
584
+ SLP_DEF_INVALID_EXEC (context_run_callback )
585
+ #endif
586
+
587
+
565
588
static PyObject *
566
589
context_run (PyContext * self , PyObject * const * args ,
567
590
Py_ssize_t nargs , PyObject * kwnames )
568
591
{
592
+ STACKLESS_GETARG ();
593
+
569
594
if (nargs < 1 ) {
570
595
PyErr_SetString (PyExc_TypeError ,
571
596
"run() missing 1 required positional argument" );
@@ -576,9 +601,42 @@ context_run(PyContext *self, PyObject *const *args,
576
601
return NULL ;
577
602
}
578
603
604
+ #ifdef STACKLESS
605
+ PyThreadState * ts = PyThreadState_GET ();
606
+ PyCFrameObject * f = NULL ;
607
+ if (stackless ) {
608
+ f = slp_cframe_new (context_run_callback , 1 );
609
+ if (f == NULL )
610
+ return NULL ;
611
+ Py_INCREF (self );
612
+ f -> ob1 = (PyObject * )self ;
613
+ SLP_SET_CURRENT_FRAME (ts , (PyFrameObject * )f );
614
+ /* f contains the only counted reference to current frame. This reference
615
+ * keeps the fame alive during the following _PyObject_FastCallKeywords().
616
+ */
617
+ }
618
+ #endif
619
+ STACKLESS_PROMOTE_ALL ();
620
+
579
621
PyObject * call_result = _PyObject_FastCallKeywords (
580
622
args [0 ], args + 1 , nargs - 1 , kwnames );
581
623
624
+ STACKLESS_ASSERT ();
625
+ #ifdef STACKLESS
626
+ if (stackless && !STACKLESS_UNWINDING (call_result )) {
627
+ /* required, because we added a C-frame */
628
+ assert (f );
629
+ assert ((PyFrameObject * )f == SLP_CURRENT_FRAME (ts ));
630
+ SLP_STORE_NEXT_FRAME (ts , (PyFrameObject * )f );
631
+ Py_DECREF (f );
632
+ return STACKLESS_PACK (ts , call_result );
633
+ }
634
+ Py_XDECREF (f );
635
+ if (STACKLESS_UNWINDING (call_result )) {
636
+ return call_result ;
637
+ }
638
+ #endif
639
+
582
640
if (PyContext_Exit (self )) {
583
641
return NULL ;
584
642
}
@@ -593,7 +651,7 @@ static PyMethodDef PyContext_methods[] = {
593
651
_CONTEXTVARS_CONTEXT_KEYS_METHODDEF
594
652
_CONTEXTVARS_CONTEXT_VALUES_METHODDEF
595
653
_CONTEXTVARS_CONTEXT_COPY_METHODDEF
596
- {"run" , (PyCFunction )context_run , METH_FASTCALL | METH_KEYWORDS , NULL },
654
+ {"run" , (PyCFunction )context_run , METH_FASTCALL | METH_KEYWORDS | METH_STACKLESS , NULL },
597
655
{NULL , NULL }
598
656
};
599
657
@@ -1222,5 +1280,13 @@ _PyContext_Init(void)
1222
1280
}
1223
1281
Py_DECREF (missing );
1224
1282
1283
+ #ifdef STACKLESS
1284
+ if (slp_register_execute (& PyCFrame_Type , "context_run_callback" ,
1285
+ context_run_callback , SLP_REF_INVALID_EXEC (context_run_callback )) != 0 )
1286
+ {
1287
+ return 0 ;
1288
+ }
1289
+ #endif
1290
+
1225
1291
return 1 ;
1226
1292
}
0 commit comments