Skip to content

GH-95245: Store object values and dict pointers in single tagged pointer. #95278

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

Merged

Conversation

markshannon
Copy link
Member

@markshannon markshannon commented Jul 26, 2022

This is the first part of #95245. Part two will move the weakrefs pointer into the object pre-header.

I have chosen to tag the values pointer, rather than the dict pointer, because it allows _PyObject_GetDictPtr(PyObject *obj) to continue to return a valid pointer.

@markshannon
Copy link
Member Author

No change in performance

@iritkatriel
Copy link
Member

Is there any documentation about this? It's pretty intricate.

@markshannon
Copy link
Member Author

I was going to document this once I'd done the second part of #95245
Something like this: https://github.com/faster-cpython/cpython/blob/document-object-layout/Objects/object_layout.md

Copy link
Member

@iritkatriel iritkatriel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no more comments.

static inline void
_PyDictOrValues_SetValues(PyDictOrValues *ptr, PyDictValues *values)
{
ptr->values = ((char *)values) - 1;
Copy link
Contributor

@matthiasgoergens matthiasgoergens Aug 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why this one is a -1? Naively, I would have expected something like (|1), ie setting the lowest bit. Which would be equivalent to +1.

I assume there's something that goes horribly wrong with that native approach that I am missing, though?

(As far as I can tell, subtracting one should also work. Not sure what C does with null pointers in this context, though.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_PyDictOrValues_SetValues mutates the pointer; _PyDictOrValues_GetValues restores the pointer. Think of it as $f(x) = y$ and $f^{-1}(y) = x$. Currently, $f(x) = x - 1$ and $f^{-1}(y) = y + 1$. If we'd used +1, as you suggest, we'd have to undo that using -1 iso. +1. AFAICS, either way is fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining!

I am working on a prototype with a tagged pointer elsewhere in the code, I so I was looking for exiting examples to learn from.

Thanks for confirming that either way is fine.

I was just wrecking my brain about whether there's something more going on that I was missing. (And something that I would thus be bound to get horriby wrong in my code, where I want to store either a pointer directly, or an odd integer, in the same memory location.)

@markshannon markshannon deleted the merge-dict-and-values-pointers branch September 26, 2023 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants