8000 gh-117139: Add header for tagged pointers by Fidget-Spinner · Pull Request #118330 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-117139: Add header for tagged pointers #118330

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
merged 19 commits into from
Apr 30, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
address review
Co-Authored-By: Sam Gross <655866+colesbury@users.noreply.github.com>
  • Loading branch information
Fidget-Spinner and colesbury committed Apr 30, 2024
commit 003d274650dddd5c872d6d42fb9b9647e17154c6
143 changes: 84 additions & 59 deletions Include/internal/pycore_stackref.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,59 +32,59 @@ typedef union {

static const _PyStackRef Py_STACKREF_NULL = { .bits = 0 };

#ifdef Py_GIL_DISABLED
#define Py_TAG_DEFERRED (1)
#define Py_TAG (Py_TAG_DEFERRED)
#else
#define Py_TAG 0
#endif
#define Py_TAG_DEFERRED (1)

// Gets a PyObject * from a _PyStackRef
#if defined(Py_GIL_DISABLED)
static inline PyObject *
PyStackRef_Get(_PyStackRef tagged) {
PyObject *cleared = ((PyObject *)((tagged).bits & (~Py_TAG)));
return cleared;
}
static inline PyObject *
PyStackRef_Get(_PyStackRef tagged)
{
PyObject *cleared = ((PyObject *)((tagged).bits & (~Py_TAG_DEFERRED)));
return cleared;
}
#else
#define PyStackRef_Get(tagged) ((PyObject *)(uintptr_t)((tagged).bits))
# define PyStackRef_Get(tagged) ((PyObject *)(uintptr_t)((tagged).bits))
#endif

// Converts a PyObject * to a PyStackRef, stealing the reference.
#if defined(Py_GIL_DISABLED)
static inline _PyStackRef
_PyStackRef_StealRef(PyObject *obj) {
// Make sure we don't take an already tagged value.
assert(PyStackRef_Get(((_PyStackRef){.bits = ((uintptr_t)(obj))})) == obj);
return ((_PyStackRef){.bits = ((uintptr_t)(obj))});
}
#define PyStackRef_StealRef(obj) _PyStackRef_StealRef(_PyObject_CAST(obj))
static inline _PyStackRef
_PyStackRef_StealRef(PyObject *obj)
{
// Make sure we don't take an already tagged value.
assert(((uintptr_t)obj & Py_TAG_DEFERRED) == 0);
return ((_PyStackRef){.bits = ((uintptr_t)(obj))});
}
# define PyStackRef_StealRef(obj) _PyStackRef_StealRef(_PyObject_CAST(obj))
#else
#define PyStackRef_StealRef(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))})
# define PyStackRef_StealRef(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))})
#endif

#if defined(Py_GIL_DISABLED)
static inline PyObject *
PyStackRef_StealObject(_PyStackRef tagged) {
if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) {
assert(_PyObject_HasDeferredRefcount(PyStackRef_Get(tagged)));
return Py_NewRef(PyStackRef_Get(tagged));
}
return PyStackRef_Get(tagged);
static inline PyObject *
PyStackRef_StealObject(_PyStackRef tagged)
{
if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) {
assert(_PyObject_HasDeferredRefcount(PyStackRef_Get(tagged)));
return Py_NewRef(PyStackRef_Get(tagged));
}
return PyStackRef_Get(tagged);
}
#else
#define PyStackRef_StealObject(tagged) PyStackRef_Get(tagged)
# define PyStackRef_StealObject(tagged) PyStackRef_Get(tagged)
#endif

static inline void
_Py_untag_stack_borrowed(PyObject **dst, const _PyStackRef *src, size_t length) {
_Py_untag_stack_borrowed(PyObject **dst, const _PyStackRef *src, size_t length)
{
for (size_t i = 0; i < length; i++) {
dst[i] = PyStackRef_Get(src[i]);
}
}

static inline void
_Py_untag_stack_steal(PyObject **dst, const _PyStackRef *src, size_t length) {
_Py_untag_stack_steal(PyObject **dst, const _PyStackRef *src, size_t length)
{
for (size_t i = 0; i < length; i++) {
dst[i] = PyStackRef_StealObject(src[i]);
}
Expand All @@ -93,55 +93,57 @@ _Py_untag_stack_steal(PyObject **dst, const _PyStackRef *src, size_t length) {

#define PyStackRef_XSETREF(dst, src) \
do { \
_PyStackRef *_tmp_dst_ptr = _Py_CAST(_PyStackRef*, &(dst)); \
_PyStackRef *_tmp_dst_ptr = &(dst) \
Copy link
Member Author

Choose a reason for hiding this comment

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

There is a missing semicolon here but I don't want to waste CI resources, so I will fix this in another PR, since nothing is using this file at the moment anyways.

_PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \
*_tmp_dst_ptr = (src); \
PyStackRef_XDECREF(_tmp_old_dst); \
} while (0)

#define PyStackRef_SETREF(dst, src) \
do { \
_PyStackRef *_tmp_dst_ptr = _Py_CAST(_PyStackRef*, &(dst)); \
_PyStackRef *_tmp_dst_ptr = &(dst); \
_PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \
*_tmp_dst_ptr = (src); \
PyStackRef_DECREF(_tmp_old_dst); \
} while (0)

#define PyStackRef_CLEAR(op) \
do { \
_PyStackRef *_tmp_op_ptr = _Py_CAST(_PyStackRef*, &(op)); \
_PyStackRef *_tmp_op_ptr = &(op); \
_PyStackRef _tmp_old_op = (*_tmp_op_ptr); \
if (PyStackRef_Get(_tmp_old_op) != NULL) { \
*_tmp_op_ptr = PyStackRef_StealRef(_Py_NULL); \
if (_tmp_old_op.bits != Py_STACKREF_NULL.bits) { \
*_tmp_op_ptr = Py_STACKREF_NULL; \
PyStackRef_DECREF(_tmp_old_op); \
} \
} while (0)

#if defined(Py_GIL_DISABLED)
static inline void
PyStackRef_DECREF(_PyStackRef tagged) {
if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) {
return;
}
Py_DECREF(PyStackRef_Get(tagged));
static inline void
PyStackRef_DECREF(_PyStackRef tagged)
{
if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) {
return;
}
Py_DECREF(PyStackRef_Get(tagged));
}
#else
#define PyStackRef_DECREF(op) Py_DECREF(PyStackRef_Get(op))
# define PyStackRef_DECREF(op) Py_DECREF(PyStackRef_Get(op))
#endif

#define PyStackRef_DECREF_OWNED(op) Py_DECREF(PyStackRef_Get(op));

#if defined(Py_GIL_DISABLED)
static inline void
PyStackRef_INCREF(_PyStackRef tagged) {
if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) {
assert(_PyObject_HasDeferredRefcount(PyStackRef_Get(tagged)));
return;
}
Py_INCREF(PyStackRef_Get(tagged));
static inline void
PyStackRef_INCREF(_PyStackRef tagged)
{
if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) {
assert(_PyObject_HasDeferredRefcount(PyStackRef_Get(tagged)));
return;
}
Py_INCREF(PyStackRef_Get(tagged));
}
#else
#define PyStackRef_INCREF(op) Py_INCREF(PyStackRef_Get(op))
# define PyStackRef_INCREF(op) Py_INCREF(PyStackRef_Get(op))
#endif

static inline void
Expand Down Expand Up @@ -170,17 +172,40 @@ PyStackRef_XNewRef(_PyStackRef obj)

// Converts a PyObject * to a PyStackRef, with a new reference
#if defined(Py_GIL_DISABLED)
static inline _PyStackRef
_PyStackRef_NewRefDeferred(PyObject *obj) {
// Make sure we don't take an already tagged value.
assert(PyStackRef_Get(((_PyStackRef){.bits = ((uintptr_t)(obj))})) == obj);
int is_deferred = (obj != NULL && _PyObject_HasDeferredRefcount(obj));
int tag = (is_deferred ? Py_TAG_DEFERRED : 0);
return PyStackRef_XNewRef((_PyStackRef){.bits = ((uintptr_t)(obj) | tag)});
static inline _PyStackRef
_PyStackRef_NewRefDeferred(PyObject *obj)
{
// Make sure we don't take an already tagged value.
assert(((uintptr_t)obj & Py_TAG_DEFERRED) == 0);
assert(obj != NULL);
if (_PyObject_HasDeferredRefcount(obj)) {
return (_PyStackRef){ .bits = (uintptr_t)obj | Py_TAG_DEFERRED };
}
else {
return (_PyStackRef){ .bits = (uintptr_t)Py_NewRef(obj) };
}
}
# define PyStackRef_NewRefDeferred(obj) _PyStackRef_NewRefDeferred(_PyObject_CAST(obj))
#else
# define PyStackRef_NewRefDeferred(obj) PyStackRef_NewRef(((_PyStackRef){.bits = ((uintptr_t)(obj))}))
#endif

#if defined(Py_GIL_DISABLED)
static inline _PyStackRef
_PyStackRef_XNewRefDeferred(PyObject *obj)
{
// Make sure we don't take an already tagged value.
assert(((uintptr_t)obj & Py_TAG_DEFERRED) == 0);
if (obj != NULL && _PyObject_HasDeferredRefcount(obj)) {
return (_PyStackRef){ .bits = (uintptr_t)obj | Py_TAG_DEFERRED };
}
#define PyStackRef_NewRefDeferred(obj) _PyStackRef_NewRefDeferred(_PyObject_CAST(obj))
else {
return (_PyStackRef){ .bits = (uintptr_t)Py_XNewRef(obj) };
}
}
# define PyStackRef_XNewRefDeferred(obj) _PyStackRef_XNewRefDeferred(_PyObject_CAST(obj))
#else
#define PyStackRef_NewRefDeferred(obj) PyStackRef_NewRef(((_PyStackRef){.bits = ((uintptr_t)(obj))}))
# define PyStackRef_XNewRefDeferred(obj) PyStackRef_XNewRef(((_PyStackRef){.bits = ((uintptr_t)(obj))}))
#endif

#ifdef __cplusplus
Expand Down
0