New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Get some of the limited API working with Py_LIMITED_API defined #5550
Get some of the limited API working with Py_LIMITED_API defined #5550
Conversation
This gets a minimal limited API example working with Py_LIMITED_API defined, and adds a small test to prove it.
Cython/Utility/FunctionArguments.c
Outdated
if (pos >= PyTuple_GET_SIZE(kwds)) break; | ||
key = PyTuple_GET_ITEM(kwds, pos); | ||
if (pos >= __Pyx_PyTuple_GET_SIZE(kwds)) break; | ||
key = __Pyx_PyTuple_GET_ITEM(kwds, pos); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GET_ITEM
call should rather be guarded by SAFE_MACROS
and BORROWED_REFS
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still thinking about this. In both cases the BORROWED_REFS
guard looks hard to implement, and isn't necessary for limited API support (where we allow borrowed refs by default).
So I'd rather just do SAFE_MACROS
at this stage.
I've moved __Pyx_PyTuple_GET_SIZE
inside SAFE_MACROS
but I don't think this is the right solution so may come back and change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these should now be handled (at the cost of some complication)
Cython/Utility/FunctionArguments.c
Outdated
@@ -414,7 +414,7 @@ static int __Pyx_MergeKeywords(PyObject *kwdict, PyObject *source_mapping) { | |||
// (because it's an old version of CPython or it's not CPython at all), | |||
// then the ..._FASTCALL macros simply alias ..._VARARGS | |||
|
|||
#define __Pyx_Arg_VARARGS(args, i) PyTuple_GET_ITEM(args, i) | |||
#define __Pyx_Arg_VARARGS(args, i) __Pyx_PyTuple_GET_ITEM(args, i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, we shouldn't unconditionally use the macro.
#else | ||
PyObject *from_bytes, *result; | ||
PyObject *py_bytes = NULL, *arg_tuple = NULL, *kwds = NULL, *order_str = NULL; | ||
from_bytes = PyObject_GetAttrString((PyObject*)&PyInt_Type, "from_bytes"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that looks expensive. But having it work at all is probably still better than having it fail..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the fallback code for "int type is bigger than long long" or "int type is bigger than long and Python doesn't define PY_LONG_LONG
". So practically I doubt it gets used much.
But yeah, I expect it's expensive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, PY_LONG_LONG
is now always defined in recent CPython versions. I think since back when they switched to C99 or a bit later, when they noticed that their code actually doesn't compile without HAVE_LONG_LONG
any more. :)
Closing and re-opening (there's an extra commit that github doesn't seem to have noticed...) |
…th-py-limited-api
Mostly that we store the PyCFunctionObject as an attribute of it rather than "inheriting" from PyCFunctionObject.
… into limited-api-with-py-limited-api
#if CYTHON_COMPILING_IN_LIMITED_API | ||
// Note that the limited API doesn't know about PyCodeObject, so the type of this | ||
// is PyObject (unlike for the main API) | ||
static CYTHON_INLINE PyObject* __Pyx_PyCode_New(int a, int p, int k, int l, int s, int f, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've also refactored this slightly again, since it used replace
and so was also broken on Py3.7. Might be a bit more performant than before, but probably relies on somewhat unstable (Python) API
Two other small ones related to the (non) existence of
Reading through https://hg.python.org/cpython/rev/655d7a55c165, it seems like the fix is probably something along the lines of:
|
The follow up PR to this will do classes. I'd got the first of those lines. I hadn't got the second, but I'll make sure it add it - thanks |
Awesome. Thanks again for this change; I'm really hoping this can get out the door. If it wasn't obvious, I'm working through a stack of errors for my own codebase. Let me know if you'd prefer I open tickets as I come across issues or just piggy-back here. |
Another 2 I came across related to tp_basicsize:
Unlike tp_free, there doesn't appear to be a slot macro for |
The PyPy failure looks to be a mess up with fused function optional arguments. The code it's generating is
With the Unfortunately this pretty much blocks this PR until that's sorted I think. |
Another 1-liner related to
Per https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_dictoffset,
|
This is already fixed in the follow-up
This isn't. It probably isn't too hard - it's already conditional on |
Depends on #5614 |
|
||
// Cython uses these constants but they are not available in the limited API. | ||
// (it'd be nice if there was a more robust way of looking these up) | ||
#ifndef CO_OPTIMIZED |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think these would be better read from inspect
when the module is initialized (i.e. much like the debug flag) - it feels a bit against the spirit of the limited API to just redefine constants that have been intentionally excluded.
With that said, I'll create an issue when this PR is done rather than try to make too many more changes.
This gets a minimal limited API example working with Py_LIMITED_API defined, and adds a small test to prove it.