@@ -85,6 +85,134 @@ int Context_Exit(PyObject *ctx) {
8585
8686#endif
8787
88+ /* Originally apart of loop.pyx via calling context.run
89+ moved here so we can began optimizing more
90+ reason why something like this is more costly is because
91+ we have to find the .run method if these were C Functions instead
92+ This Call would no longer be needed and we skip right to the
93+ meat of the function (run) immediately however, we can go further
94+ to optimize that code too.
95+
96+ Before:
97+ cdef inline run_in_context1(context, method, arg):
98+ Py_INCREF(method)
99+ try:
100+ return context.run(method, arg)
101+ finally:
102+ Py_DECREF(method)
103+
104+ After:
105+ cdef inline run_in_context1(context, method, arg):
106+ Py_INCREF(method)
107+ try:
108+ return Context_RunNoArgs(context, method)
109+ finally:
110+ Py_DECREF(method)
111+ */
112+
113+ /* Context.run is literally this code right here referenced from python 3.15.1
114+
115+ static PyObject *
116+ context_run(PyObject *self, PyObject *const *args,
117+ Py_ssize_t nargs, PyObject *kwnames)
118+ {
119+ PyThreadState *ts = _PyThreadState_GET();
120+
121+ if (nargs < 1) {
122+ _PyErr_SetString(ts, PyExc_TypeError,
123+ "run() missing 1 required positional argument");
124+ return NULL;
125+ }
126+
127+ if (_PyContext_Enter(ts, self)) {
128+ return NULL;
129+ }
130+
131+ PyObject *call_result = _PyObject_VectorcallTstate(
132+ ts, args[0], args + 1, nargs - 1, kwnames);
133+
134+ if (_PyContext_Exit(ts, self)) {
135+ Py_XDECREF(call_result);
136+ return NULL;
137+ }
138+
139+ return call_result;
140+ }
141+
142+ As we can see this code is not very expensive to maintain
143+ at all and can be simply reproduced and improved upon
144+ for our needs of being faster.
145+
146+ Will name them after the different object calls made
147+ to keep things less confusing.
148+ We also eliminate needing to find the run method by doing so.
149+
150+ These changes reflect recent addtions made to winloop.
151+ SEE: https://github.com/Vizonex/Winloop/pull/112
152+ */
153+
154+ static PyObject* Context_RunNoArgs (PyObject* context, PyObject* method){
155+ /* NOTE: Were looking for -1 but we can also say it's not
156+ a no-zero value so we could even treat it as a true case... */
157+ if (Context_Enter (context)){
158+ return NULL ;
159+ }
160+
161+ #if PY_VERSION_HEX >= 0x030a0000
162+ PyObject* call_result = PyObject_CallNoArgs (method);
163+ #else
164+ PyObject* call_result = PyObject_CallFunctionObjArgs (method, NULL );
165+ #endif
166+
167+ if (Context_Exit (context)){
168+ Py_XDECREF (call_result);
169+ return NULL ;
170+ }
171+
172+ return call_result;
173+ }
174+
175+ static PyObject* Context_RunOneArg (PyObject* context, PyObject* method, PyObject* arg){
176+ if (Context_Enter (context)){
177+ return NULL ;
178+ }
179+ /* Introduced in 3.9 */
180+ /* NOTE: Kept around backwards compatability since the same features are planned for uvloop */
181+ #if PY_VERSION_HEX >= 0x03090000
182+ PyObject* call_result = PyObject_CallOneArg (method, arg);
183+ #else /* verison < 3.9 */
184+ PyObject* call_result = PyObject_CallFunctionObjArgs (method, arg, NULL );
185+ #endif
186+ if (Context_Exit (context)){
187+ Py_XDECREF (call_result);
188+ return NULL ;
189+ }
190+ return call_result;
191+ }
192+
193+ static PyObject* Context_RunTwoArgs (PyObject* context, PyObject* method, PyObject* arg1, PyObject* arg2){
194+ /* Cython can't really do this PyObject array packing so writing this in C
195+ has a really good advantage */
196+ if (Context_Enter (context)){
197+ return NULL ;
198+ }
199+ #if PY_VERSION_HEX >= 0x03090000
200+ /* begin packing for call... */
201+ PyObject* args[2 ];
202+ args[0 ] = arg1;
203+ args[1 ] = arg2;
204+ PyObject* call_result = PyObject_Vectorcall (method, args, 2 , NULL );
205+ #else
206+ PyObject* call_result = PyObject_CallFunctionObjArgs (method, arg1, arg2, NULL );
207+ #endif
208+ if (Context_Exit (context)){
209+ Py_XDECREF (call_result);
210+ return NULL ;
211+ }
212+ return call_result;
213+ }
214+
215+
88216/* inlined from cpython/Modules/signalmodule.c
89217 * https://github.com/python/cpython/blob/v3.13.0a6/Modules/signalmodule.c#L1931-L1951
90218 * private _Py_RestoreSignals has been moved to CPython internals in Python 3.13
0 commit comments