https://github.com/python/cpython/commit/dc6b12d1b2ea26bb0323d932fa7b1a337eaca562
commit: dc6b12d1b2ea26bb0323d932fa7b1a337eaca562
branch: main
author: Ken Jin <[email protected]>
committer: Fidget-Spinner <[email protected]>
date: 2024-05-01T04:46:13+08:00
summary:

gh-117139: Add header for tagged pointers (GH-118330)



---------

Co-authored-by: Sam Gross <[email protected]>

files:
A Include/internal/pycore_stackref.h
M Makefile.pre.in
M PCbuild/pythoncore.vcxproj
M PCbuild/pythoncore.vcxproj.filters

diff --git a/Include/internal/pycore_stackref.h 
b/Include/internal/pycore_stackref.h
new file mode 100644
index 00000000000000..fd929cd4873a8b
--- /dev/null
+++ b/Include/internal/pycore_stackref.h
@@ -0,0 +1,195 @@
+#ifndef Py_INTERNAL_STACKREF_H
+#define Py_INTERNAL_STACKREF_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+#  error "this header requires Py_BUILD_CORE define"
+#endif
+
+#include <stddef.h>
+
+typedef union {
+    uintptr_t bits;
+} _PyStackRef;
+
+static const _PyStackRef Py_STACKREF_NULL = { .bits = 0 };
+
+#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_DEFERRED)));
+    return cleared;
+}
+#else
+#   define PyStackRef_Get(tagged) ((PyObject *)((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(((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))})
+#endif
+
+// 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(((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) {
+        return Py_STACKREF_NULL;
+    }
+    return _PyStackRef_NewRefDeferred(obj);
+}
+#   define PyStackRef_XNewRefDeferred(obj) 
_PyStackRef_XNewRefDeferred(_PyObject_CAST(obj))
+#else
+#   define PyStackRef_XNewRefDeferred(obj) 
PyStackRef_XNewRef(((_PyStackRef){.bits = ((uintptr_t)(obj))}))
+#endif
+
+// Converts a PyStackRef back to a PyObject *.
+#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);
+}
+#else
+#   define PyStackRef_StealObject(tagged) PyStackRef_Get(tagged)
+#endif
+
+static inline void
+_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)
+{
+    for (size_t i = 0; i < length; i++) {
+        dst[i] = PyStackRef_StealObject(src[i]);
+    }
+}
+
+
+#define PyStackRef_XSETREF(dst, src) \
+    do { \
+        _PyStackRef *_tmp_dst_ptr = &(dst) \
+        _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 = &(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 = &(op); \
+        _PyStackRef _tmp_old_op = (*_tmp_op_ptr); \
+        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));
+}
+#else
+#   define PyStackRef_DECREF(op) Py_DECREF(PyStackRef_Get(op))
+#endif
+
+#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));
+}
+#else
+#   define PyStackRef_INCREF(op) Py_INCREF(PyStackRef_Get(op))
+#endif
+
+static inline void
+PyStackRef_XDECREF(_PyStackRef op)
+{
+    if (op.bits != Py_STACKREF_NULL.bits) {
+        PyStackRef_DECREF(op);
+    }
+}
+
+static inline _PyStackRef
+PyStackRef_NewRef(_PyStackRef obj)
+{
+    PyStackRef_INCREF(obj);
+    return obj;
+}
+
+static inline _PyStackRef
+PyStackRef_XNewRef(_PyStackRef obj)
+{
+    if (obj.bits == Py_STACKREF_NULL.bits) {
+        return obj;
+    }
+    return PyStackRef_NewRef(obj);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_STACKREF_H */
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 4e4d01d14ee3cb..e69d1fe6e2dd14 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1225,6 +1225,7 @@ PYTHON_HEADERS= \
                $(srcdir)/Include/internal/pycore_structseq.h \
                $(srcdir)/Include/internal/pycore_symtable.h \
                $(srcdir)/Include/internal/pycore_sysmodule.h \
+               $(srcdir)/Include/internal/pycore_stackref.h \
                $(srcdir)/Include/internal/pycore_time.h \
                $(srcdir)/Include/internal/pycore_token.h \
                $(srcdir)/Include/internal/pycore_traceback.h \
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 25d52945c1c330..4cb3e0d3227092 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -291,6 +291,7 @@
     <ClInclude Include="..\Include\internal\pycore_structseq.h" />
     <ClInclude Include="..\Include\internal\pycore_sysmodule.h" />
     <ClInclude Include="..\Include\internal\pycore_symtable.h" />
+    <ClInclude Include="..\Include\internal\pycore_stackref.h" />
     <ClInclude Include="..\Include\internal\pycore_time.h" />
     <ClInclude Include="..\Include\internal\pycore_token.h" />
     <ClInclude Include="..\Include\internal\pycore_traceback.h" />
diff --git a/PCbuild/pythoncore.vcxproj.filters 
b/PCbuild/pythoncore.vcxproj.filters
index 4b1f9aa6538562..0b858cf1eb46a8 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -789,6 +789,9 @@
     <ClInclude Include="..\Include\internal\pycore_symtable.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
+    <ClInclude Include="..\Include\internal\pycore_stackref.h">
+      <Filter>Include\internal</Filter>
+    </ClInclude>
     <ClInclude Include="..\Include\internal\pycore_time.h">
       <Filter>Include\internal</Filter>
     </ClInclude>

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to