Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 33.9k
bpo-45947: Place dict and values pointer at fixed (negative) offset just before GC header.#29879
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
ee5977272b71cccd22dac4c83f778a8593c34b5ceae8c74ab1bf13b0a025dfb5a012a8e7734b814d41ab123171a48d6a5879e61bfce0f65b98ddaed0f376b5d7248129435bae302f46fFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -334,6 +334,12 @@ given type object has a specified feature. | ||
| #ifndef Py_LIMITED_API | ||
| /* Placement of dict (and values) pointers are managed by the VM, not by the type. | ||
| * The VM will automatically set tp_dictoffset. Should not be used for variable sized | ||
| * classes, such as classes that extend tuple. | ||
| */ | ||
| #define Py_TPFLAGS_MANAGED_DICT (1 << 4) | ||
markshannon marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading. Please reload this page. | ||
| /* Set if instances of the type object are treated as sequences for pattern matching */ | ||
| #define Py_TPFLAGS_SEQUENCE (1 << 5) | ||
| /* Set if instances of the type object are treated as mappings for pattern matching */ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Place pointers to dict and values immediately before GC header. This reduces | ||
| number of dependent memory loads to access either dict or values from 3 to | ||
| 1. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -69,10 +69,10 @@ module gc | ||
| #define NEXT_MASK_UNREACHABLE (1) | ||
| /* Get an object's GC head */ | ||
| #define AS_GC(o) ((PyGC_Head *)(o)-1) | ||
| #define AS_GC(o) ((PyGC_Head *)(((char *)(o))-sizeof(PyGC_Head))) | ||
| /* Get the object given the GC head */ | ||
| #define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1)) | ||
| #define FROM_GC(g) ((PyObject *)(((char *)(g))+sizeof(PyGC_Head))) | ||
| static inline int | ||
| gc_is_collecting(PyGC_Head *g) | ||
| @@ -2231,28 +2231,14 @@ PyObject_IS_GC(PyObject *obj) | ||
| return _PyObject_IS_GC(obj); | ||
| } | ||
| static PyObject * | ||
| _PyObject_GC_Alloc(int use_calloc, size_t basicsize) | ||
| void | ||
| _PyObject_GC_Link(PyObject *op) | ||
| { | ||
| PyGC_Head *g = AS_GC(op); | ||
| assert(((uintptr_t)g & (sizeof(uintptr_t)-1)) == 0); // g must be correctly aligned | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow, you can use & on pointers. I didn't know that. :-) MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only after you've cast it to an int. You can do anything with a cast 🙂 Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, somehow I thought uintptr_t was a pointer. :-/ | ||
| PyThreadState *tstate = _PyThreadState_GET(); | ||
| GCState *gcstate = &tstate->interp->gc; | ||
| if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)){ | ||
| return _PyErr_NoMemory(tstate); | ||
| } | ||
| size_t size = sizeof(PyGC_Head) + basicsize; | ||
| PyGC_Head *g; | ||
| if (use_calloc){ | ||
| g = (PyGC_Head *)PyObject_Calloc(1, size); | ||
| } | ||
| else{ | ||
| g = (PyGC_Head *)PyObject_Malloc(size); | ||
| } | ||
| if (g == NULL){ | ||
| return _PyErr_NoMemory(tstate); | ||
| } | ||
| assert(((uintptr_t)g & 3) == 0); // g must be aligned 4bytes boundary | ||
| g->_gc_next = 0; | ||
| g->_gc_prev = 0; | ||
| gcstate->generations[0].count++; /* number of allocated GC objects */ | ||
| @@ -2266,26 +2252,32 @@ _PyObject_GC_Alloc(int use_calloc, size_t basicsize) | ||
| gc_collect_generations(tstate); | ||
| gcstate->collecting = 0; | ||
| } | ||
| PyObject *op = FROM_GC(g); | ||
| return op; | ||
| } | ||
| PyObject * | ||
| _PyObject_GC_Malloc(size_t basicsize) | ||
| { | ||
| return _PyObject_GC_Alloc(0, basicsize); | ||
| } | ||
| PyObject * | ||
| _PyObject_GC_Calloc(size_t basicsize) | ||
| static PyObject * | ||
| gc_alloc(size_t basicsize, size_t presize) | ||
| { | ||
| return _PyObject_GC_Alloc(1, basicsize); | ||
| PyThreadState *tstate = _PyThreadState_GET(); | ||
| if (basicsize > PY_SSIZE_T_MAX - presize){ | ||
| return _PyErr_NoMemory(tstate); | ||
| } | ||
| size_t size = presize + basicsize; | ||
| char *mem = PyObject_Malloc(size); | ||
| if (mem == NULL){ | ||
| return _PyErr_NoMemory(tstate); | ||
| } | ||
| ((PyObject **)mem)[0] = NULL; | ||
| ((PyObject **)mem)[1] = NULL; | ||
| PyObject *op = (PyObject *)(mem + presize); | ||
| _PyObject_GC_Link(op); | ||
| return op; | ||
| } | ||
| PyObject * | ||
| _PyObject_GC_New(PyTypeObject *tp) | ||
| { | ||
| PyObject *op = _PyObject_GC_Malloc(_PyObject_SIZE(tp)); | ||
| size_t presize = _PyType_PreHeaderSize(tp); | ||
| PyObject *op = gc_alloc(_PyObject_SIZE(tp), presize); | ||
| if (op == NULL){ | ||
| return NULL; | ||
| } | ||
| @@ -2303,8 +2295,9 @@ _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems) | ||
| PyErr_BadInternalCall(); | ||
| return NULL; | ||
| } | ||
| size_t presize = _PyType_PreHeaderSize(tp); | ||
| size = _PyObject_VAR_SIZE(tp, nitems); | ||
| op = (PyVarObject *) _PyObject_GC_Malloc(size); | ||
| op = (PyVarObject *)gc_alloc(size, presize); | ||
| if (op == NULL){ | ||
| return NULL; | ||
| } | ||
| @@ -2333,6 +2326,7 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) | ||
| void | ||
| PyObject_GC_Del(void *op) | ||
| { | ||
| size_t presize = _PyType_PreHeaderSize(((PyObject *)op)->ob_type); | ||
| PyGC_Head *g = AS_GC(op); | ||
| if (_PyObject_GC_IS_TRACKED(op)){ | ||
| gc_list_remove(g); | ||
| @@ -2341,7 +2335,7 @@ PyObject_GC_Del(void *op) | ||
| if (gcstate->generations[0].count > 0){ | ||
| gcstate->generations[0].count--; | ||
| } | ||
| PyObject_Free(g); | ||
| PyObject_Free(((char *)op)-presize); | ||
| } | ||
| int | ||
Uh oh!
There was an error while loading. Please reload this page.
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.
_PyObject_GC_Mallocis part of stable ABI. AFAIK the function cannot be removed.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.
It's not part of the stable ABI. It starts with an underscore.
https://www.python.org/dev/peps/pep-0384/#excluded-functions
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.
Misc/stable_abi.txtdefine it as stable ABI.On the other hand, no public macro in Python/C API use it. So I doubt it is actually stable abi.
As far as this repo, only one package in top4000 packages uses it.
https://github.com/hpyproject/top4000-pypi-packages/search?q=_PyObject_GC_Malloc
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 sent an email to python-dev asking for clarification of the status of this functions and others that start with _ but are listed in Misc/stable_abi.txt. (It is not listed in Doc/data/stable_abi.dat.)