From 209ddacef59b09ba732a05924f1ebf8ff0e0d044 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 27 Apr 2024 02:37:11 +0800 Subject: [PATCH 01/19] Add header for tagged pointers --- Include/internal/pycore_object.h | 14 -- Include/internal/pycore_tagged.h | 208 +++++++++++++++++++++++++++++ Makefile.pre.in | 1 + Objects/codeobject.c | 1 + Objects/descrobject.c | 1 + Objects/funcobject.c | 1 + Objects/moduleobject.c | 1 + Objects/typeobject.c | 1 + PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 + Python/gc_free_threading.c | 1 + 11 files changed, 219 insertions(+), 14 deletions(-) create mode 100644 Include/internal/pycore_tagged.h diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index 7df8003196d8cc..a96f6cf578853f 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -159,20 +159,6 @@ static inline void _Py_ClearImmortal(PyObject *op) op = NULL; \ } while (0) -// Mark an object as supporting deferred reference counting. This is a no-op -// in the default (with GIL) build. Objects that use deferred reference -// counting should be tracked by the GC so that they are eventually collected. -extern void _PyObject_SetDeferredRefcount(PyObject *op); - -static inline int -_PyObject_HasDeferredRefcount(PyObject *op) -{ -#ifdef Py_GIL_DISABLED - return (op->ob_gc_bits & _PyGC_BITS_DEFERRED) != 0; -#else - return 0; -#endif -} #if !defined(Py_GIL_DISABLED) static inline void diff --git a/Include/internal/pycore_tagged.h b/Include/internal/pycore_tagged.h new file mode 100644 index 00000000000000..267d1824b14661 --- /dev/null +++ b/Include/internal/pycore_tagged.h @@ -0,0 +1,208 @@ +#ifndef Py_INTERNAL_TAGGED_H +#define Py_INTERNAL_TAGGED_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +#include + +// Mark an object as supporting deferred reference counting. This is a no-op +// in the default (with GIL) build. Objects that use deferred reference +// counting should be tracked by the GC so that they are eventually collected. +extern void _PyObject_SetDeferredRefcount(PyObject *op); + +static inline int +_PyObject_HasDeferredRefcount(PyObject *op) +{ +#ifdef Py_GIL_DISABLED + return (op->ob_gc_bits & _PyGC_BITS_DEFERRED) != 0; +#else + return 0; +#endif +} + +typedef union { + uintptr_t bits; +} _PyStackRef; + +#ifdef Py_GIL_DISABLED + #define Py_TAG_DEFERRED (0b1) + #define Py_TAG (Py_TAG_DEFERRED) +#else + #define Py_TAG 0 +#endif + +#if defined(Py_TAG_TEST) + #define Py_STACKREF_UNTAG_BORROWED(tagged) ((PyObject *)(uintptr_t)((tagged).bits & (~Py_TAG_TEST))) +#elif defined(Py_GIL_DISABLED) + static inline PyObject * + _Py_STACKREF_UNTAG_BORROWED(_PyStackRef tagged) { + PyObject *cleared = ((PyObject *)((tagged).bits & (~Py_TAG))); + return cleared; + } + #define Py_STACKREF_UNTAG_BORROWED(tagged) _Py_STACKREF_UNTAG_BORROWED(tagged) +#else + #define Py_STACKREF_UNTAG_BORROWED(tagged) ((PyObject *)(uintptr_t)((tagged).bits)) +#endif + +#if defined(Py_TAG_TEST) + #define Py_STACKREF_TAG(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj) | Py_TAG_TEST)}) +#elif defined(Py_GIL_DISABLED) + static inline _PyStackRef + _Py_STACKREF_TAG(PyObject *obj) { + // Make sure we don't take an already tagged value. + assert(Py_STACKREF_UNTAG_BORROWED(((_PyStackRef){.bits = ((uintptr_t)(obj))})) == obj); + return ((_PyStackRef){.bits = ((uintptr_t)(obj))}); + } + #define Py_STACKREF_TAG(obj) _Py_STACKREF_TAG(_PyObject_CAST(obj)) +#else + #define Py_STACKREF_TAG(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))}) +#endif + +#if defined(Py_TAG_TEST) + #define Py_STACKREF_TAG_DEFERRED(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj) | Py_TAG_TEST)}) +#elif defined(Py_GIL_DISABLED) + static inline _PyStackRef + _Py_STACKREF_TAG_DEFERRED(PyObject *obj) { + // Make sure we don't take an already tagged value. + assert(Py_STACKREF_UNTAG_BORROWED(((_PyStackRef){.bits = ((uintptr_t)(obj))})) == obj); + int is_deferred = (obj != NULL && _PyObject_HasDeferredRefcount(obj)); + int tag = (is_deferred ? Py_TAG_DEFERRED : 0); + return ((_PyStackRef){.bits = ((uintptr_t)(obj) | tag)}); + } +#define Py_STACKREF_TAG_DEFERRED(obj) _Py_STACKREF_TAG_DEFERRED(_PyObject_CAST(obj)) +#else +#define Py_STACKREF_TAG_DEFERRED(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))}) +#endif + +#if defined(Py_TAG_TEST) + #define Py_STACKREF_UNTAG_OWNED(tagged) Py_STACKREF_UNTAG_BORROWED(tagged) +#elif defined(Py_GIL_DISABLED) + static inline PyObject * + _Py_STACKREF_UNTAG_OWNED(_PyStackRef tagged) { + if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) { + assert(_PyObject_HasDeferredRefcount(Py_STACKREF_UNTAG_BORROWED(tagged))); + return Py_NewRef(Py_STACKREF_UNTAG_BORROWED(tagged)); + } + return Py_STACKREF_UNTAG_BORROWED(tagged); + } + #define Py_STACKREF_UNTAG_OWNED(tagged) _Py_STACKREF_UNTAG_OWNED(tagged) +#else + #define Py_STACKREF_UNTAG_OWNED(tagged) Py_STACKREF_UNTAG_BORROWED(tagged) +#endif + +#define MAX_UNTAG_SCRATCH 10 + +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] = Py_STACKREF_UNTAG_BORROWED(src[i]); + } +} + +static inline void +_Py_untag_stack_owned(PyObject **dst, const _PyStackRef *src, size_t length) { + for (size_t i = 0; i < length; i++) { + dst[i] = Py_STACKREF_UNTAG_OWNED(src[i]); + } +} + + +#define Py_XSETREF_STACKREF(dst, src) \ + do { \ + _PyStackRef *_tmp_dst_ptr = _Py_CAST(_PyStackRef*, &(dst)); \ + _PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \ + *_tmp_dst_ptr = (src); \ + Py_XDECREF_STACKREF(_tmp_old_dst); \ + } while (0) + +#define Py_SETREF_STACKREF(dst, src) \ + do { \ + _PyStackRef *_tmp_dst_ptr = _Py_CAST(_PyStackRef*, &(dst)); \ + _PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \ + *_tmp_dst_ptr = (src); \ + Py_DECREF_STACKREF(_tmp_old_dst); \ + } while (0) + +#define Py_CLEAR_STACKREF(op) \ + do { \ + _PyStackRef *_tmp_op_ptr = _Py_CAST(_PyStackRef*, &(op)); \ + _PyStackRef _tmp_old_op = (*_tmp_op_ptr); \ + if (Py_STACKREF_UNTAG_BORROWED(_tmp_old_op) != NULL) { \ + *_tmp_op_ptr = Py_STACKREF_TAG(_Py_NULL); \ + Py_DECREF_STACKREF(_tmp_old_op); \ + } \ + } while (0) + +#if defined(Py_GIL_DISABLED) + static inline void + _Py_DecRef_StackRef(_PyStackRef tagged) { + if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) { + return; + } + Py_DECREF(Py_STACKREF_UNTAG_BORROWED(tagged)); + } + #define Py_DECREF_STACKREF(op) _Py_DecRef_StackRef(op) +#else + #define Py_DECREF_STACKREF(op) Py_DECREF(Py_STACKREF_UNTAG_BORROWED(op)) +#endif + +#if defined(Py_GIL_DISABLED) + static inline _PyStackRef + _Py_NewRef_StackRef_Owned(_PyStackRef tagged) { + if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) { + Py_INCREF(Py_STACKREF_UNTAG_BORROWED(tagged)); + uintptr_t res = tagged.bits & (~Py_TAG_DEFERRED); + return ((_PyStackRef){.bits = res}); + } + return tagged; + } + #define Py_NEWREF_STACKREF_OWNED(op) _Py_NewRef_StackRef_Owned(op) +#else + #define Py_NEWREF_STACKREF_OWNED(op) (op) +#endif + +#define Py_DECREF_STACKREF_OWNED(op) Py_DECREF(Py_STACKREF_UNTAG_BORROWED(op)); + +#if defined(Py_GIL_DISABLED) + static inline void + _Py_IncRef_StackRef(_PyStackRef tagged) { + if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) { + assert(_PyObject_HasDeferredRefcount(Py_STACKREF_UNTAG_BORROWED(tagged))); + return; + } + return Py_INCREF(Py_STACKREF_UNTAG_BORROWED(tagged)); + } + #define Py_INCREF_STACKREF(op) _Py_IncRef_StackRef(op) +#else + #define Py_INCREF_STACKREF(op) Py_INCREF(Py_STACKREF_UNTAG_BORROWED(op)) +#endif + +static inline void +_Py_XDECREF_STACKREF(_PyStackRef op) +{ + if (Py_STACKREF_UNTAG_BORROWED(op) != NULL) { + Py_DECREF_STACKREF(op); + } +} + +#define Py_XDECREF_STACKREF(op) _Py_XDECREF_STACKREF(op) + +static inline _PyStackRef +Py_NewRef_StackRef(_PyStackRef obj) +{ + Py_INCREF_STACKREF(obj); + return obj; +} + + +#define Py_NewRef_StackRef(op) Py_NewRef_StackRef(op) + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_TAGGED_H */ \ No newline at end of file diff --git a/Makefile.pre.in b/Makefile.pre.in index 0e52e10602cf85..674ce8305c9d1e 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_tagged.h \ $(srcdir)/Include/internal/pycore_time.h \ $(srcdir)/Include/internal/pycore_token.h \ $(srcdir)/Include/internal/pycore_traceback.h \ diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 014632962bfcf3..c95e017726d724 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -11,6 +11,7 @@ #include "pycore_opcode_utils.h" // RESUME_AT_FUNC_START #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_setobject.h" // _PySet_NextEntry() +#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "clinic/codeobject.c.h" diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 1b7e2fde3ceccd..b0c562847f386a 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -9,6 +9,7 @@ #include "pycore_modsupport.h" // _PyArg_UnpackStack() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount #include "pycore_tuple.h" // _PyTuple_ITEMS() diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 276b3db2970371..c0f788f5ec8cbd 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -6,6 +6,7 @@ #include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pyerrors.h" // _PyErr_Occurred() +#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount static const char * diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 2f6adb9a2e12be..10b5f8adb26f70 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -10,6 +10,7 @@ #include "pycore_object.h" // _PyType_AllocNoTrack #include "pycore_pyerrors.h" // _PyErr_FormatFromCause() #include "pycore_pystate.h" // _PyInterpreterState_GET() +#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount #include "osdefs.h" // MAXPATHLEN diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 07e0a5a02da87f..e751b2f6c6fbc2 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -16,6 +16,7 @@ #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // _Py_Mangle() +#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount #include "pycore_typeobject.h" // struct type_cache #include "pycore_unionobject.h" // _Py_union_type_or #include "pycore_weakref.h" // _PyWeakref_GET_REF() diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 25d52945c1c330..f5467366c5ba44 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -291,6 +291,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 4b1f9aa6538562..d596c8d9f57a4b 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -789,6 +789,9 @@ Include\internal + + Include\internal + Include\internal diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index 9cf0e989d0993f..fab612f4726a0e 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -11,6 +11,7 @@ #include "pycore_object_stack.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() +#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount #include "pycore_time.h" // _PyTime_GetPerfCounter() #include "pycore_tstate.h" // _PyThreadStateImpl #include "pycore_weakref.h" // _PyWeakref_ClearRef() From f783bc4e0cec6519def85cf21e475dd1cdf5c69a Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 27 Apr 2024 02:39:41 +0800 Subject: [PATCH 02/19] cleanup --- Include/internal/pycore_tagged.h | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/Include/internal/pycore_tagged.h b/Include/internal/pycore_tagged.h index 267d1824b14661..00a3a3c22de7eb 100644 --- a/Include/internal/pycore_tagged.h +++ b/Include/internal/pycore_tagged.h @@ -151,23 +151,6 @@ _Py_untag_stack_owned(PyObject **dst, const _PyStackRef *src, size_t length) { #define Py_DECREF_STACKREF(op) Py_DECREF(Py_STACKREF_UNTAG_BORROWED(op)) #endif -#if defined(Py_GIL_DISABLED) - static inline _PyStackRef - _Py_NewRef_StackRef_Owned(_PyStackRef tagged) { - if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) { - Py_INCREF(Py_STACKREF_UNTAG_BORROWED(tagged)); - uintptr_t res = tagged.bits & (~Py_TAG_DEFERRED); - return ((_PyStackRef){.bits = res}); - } - return tagged; - } - #define Py_NEWREF_STACKREF_OWNED(op) _Py_NewRef_StackRef_Owned(op) -#else - #define Py_NEWREF_STACKREF_OWNED(op) (op) -#endif - -#define Py_DECREF_STACKREF_OWNED(op) Py_DECREF(Py_STACKREF_UNTAG_BORROWED(op)); - #if defined(Py_GIL_DISABLED) static inline void _Py_IncRef_StackRef(_PyStackRef tagged) { @@ -193,14 +176,14 @@ _Py_XDECREF_STACKREF(_PyStackRef op) #define Py_XDECREF_STACKREF(op) _Py_XDECREF_STACKREF(op) static inline _PyStackRef -Py_NewRef_StackRef(_PyStackRef obj) +_Py_NewRef_StackRef(_PyStackRef obj) { Py_INCREF_STACKREF(obj); return obj; } -#define Py_NewRef_StackRef(op) Py_NewRef_StackRef(op) +#define Py_NewRef_StackRef(op) _Py_NewRef_StackRef(op) #ifdef __cplusplus } From 4c52accdc41587c10a3460c22c21d406f9fc12d8 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 27 Apr 2024 02:42:43 +0800 Subject: [PATCH 03/19] end EOL --- Include/internal/pycore_tagged.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/internal/pycore_tagged.h b/Include/internal/pycore_tagged.h index 00a3a3c22de7eb..4f8f0f9ea2daac 100644 --- a/Include/internal/pycore_tagged.h +++ b/Include/internal/pycore_tagged.h @@ -188,4 +188,4 @@ _Py_NewRef_StackRef(_PyStackRef obj) #ifdef __cplusplus } #endif -#endif /* !Py_INTERNAL_TAGGED_H */ \ No newline at end of file +#endif /* !Py_INTERNAL_TAGGED_H */ From 9e0ed428c7b14633b09e26fcf621c08de58e7f78 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 27 Apr 2024 11:28:33 +0800 Subject: [PATCH 04/19] fix warnings --- Include/internal/pycore_tagged.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/internal/pycore_tagged.h b/Include/internal/pycore_tagged.h index 4f8f0f9ea2daac..7a8f99739a2c0f 100644 --- a/Include/internal/pycore_tagged.h +++ b/Include/internal/pycore_tagged.h @@ -158,7 +158,7 @@ _Py_untag_stack_owned(PyObject **dst, const _PyStackRef *src, size_t length) { assert(_PyObject_HasDeferredRefcount(Py_STACKREF_UNTAG_BORROWED(tagged))); return; } - return Py_INCREF(Py_STACKREF_UNTAG_BORROWED(tagged)); + Py_INCREF(Py_STACKREF_UNTAG_BORROWED(tagged)); } #define Py_INCREF_STACKREF(op) _Py_IncRef_StackRef(op) #else From 4610cac934ca5b9902116caa869d07862841790e Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sat, 27 Apr 2024 21:31:25 +0800 Subject: [PATCH 05/19] format --- Include/internal/pycore_tagged.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Include/internal/pycore_tagged.h b/Include/internal/pycore_tagged.h index 7a8f99739a2c0f..47ab1062fa3bb8 100644 --- a/Include/internal/pycore_tagged.h +++ b/Include/internal/pycore_tagged.h @@ -74,9 +74,9 @@ typedef union { int tag = (is_deferred ? Py_TAG_DEFERRED : 0); return ((_PyStackRef){.bits = ((uintptr_t)(obj) | tag)}); } -#define Py_STACKREF_TAG_DEFERRED(obj) _Py_STACKREF_TAG_DEFERRED(_PyObject_CAST(obj)) + #define Py_STACKREF_TAG_DEFERRED(obj) _Py_STACKREF_TAG_DEFERRED(_PyObject_CAST(obj)) #else -#define Py_STACKREF_TAG_DEFERRED(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))}) + #define Py_STACKREF_TAG_DEFERRED(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))}) #endif #if defined(Py_TAG_TEST) From f0df2bcf88d835822359622e84b25785970afb20 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 28 Apr 2024 16:01:36 +0800 Subject: [PATCH 06/19] make macro names more symmetrical --- Include/internal/pycore_tagged.h | 43 +++++++++++++++++--------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/Include/internal/pycore_tagged.h b/Include/internal/pycore_tagged.h index 47ab1062fa3bb8..88e7e847498ced 100644 --- a/Include/internal/pycore_tagged.h +++ b/Include/internal/pycore_tagged.h @@ -33,6 +33,8 @@ typedef union { #define Py_TAG_DEFERRED (0b1) #define Py_TAG (Py_TAG_DEFERRED) #else + // Define this to test for tagged pointer leakage in the ceval stack. + // #define Py_TAG_TEST (0b1) #define Py_TAG 0 #endif @@ -112,78 +114,79 @@ _Py_untag_stack_owned(PyObject **dst, const _PyStackRef *src, size_t length) { } -#define Py_XSETREF_STACKREF(dst, src) \ +#define Py_STACKREF_XSETREF(dst, src) \ do { \ _PyStackRef *_tmp_dst_ptr = _Py_CAST(_PyStackRef*, &(dst)); \ _PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \ *_tmp_dst_ptr = (src); \ - Py_XDECREF_STACKREF(_tmp_old_dst); \ + Py_STACKREF_XDECREF(_tmp_old_dst); \ } while (0) -#define Py_SETREF_STACKREF(dst, src) \ +#define Py_STACKREF_SETREF(dst, src) \ do { \ _PyStackRef *_tmp_dst_ptr = _Py_CAST(_PyStackRef*, &(dst)); \ _PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \ *_tmp_dst_ptr = (src); \ - Py_DECREF_STACKREF(_tmp_old_dst); \ + Py_STACKREF_DECREF(_tmp_old_dst); \ } while (0) -#define Py_CLEAR_STACKREF(op) \ +#define Py_STACKREF_CLEAR(op) \ do { \ _PyStackRef *_tmp_op_ptr = _Py_CAST(_PyStackRef*, &(op)); \ _PyStackRef _tmp_old_op = (*_tmp_op_ptr); \ if (Py_STACKREF_UNTAG_BORROWED(_tmp_old_op) != NULL) { \ *_tmp_op_ptr = Py_STACKREF_TAG(_Py_NULL); \ - Py_DECREF_STACKREF(_tmp_old_op); \ + Py_STACKREF_DECREF(_tmp_old_op); \ } \ } while (0) #if defined(Py_GIL_DISABLED) static inline void - _Py_DecRef_StackRef(_PyStackRef tagged) { + _Py_STACKREF_DECREF(_PyStackRef tagged) { if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) { return; } Py_DECREF(Py_STACKREF_UNTAG_BORROWED(tagged)); } - #define Py_DECREF_STACKREF(op) _Py_DecRef_StackRef(op) + #define Py_STACKREF_DECREF(op) _Py_STACKREF_DECREF(op) #else - #define Py_DECREF_STACKREF(op) Py_DECREF(Py_STACKREF_UNTAG_BORROWED(op)) + #define Py_STACKREF_DECREF(op) Py_DECREF(Py_STACKREF_UNTAG_BORROWED(op)) #endif +#define Py_STACKREF_DECREF_OWNED(op) Py_DECREF(Py_STACKREF_UNTAG_BORROWED(op)); + #if defined(Py_GIL_DISABLED) static inline void - _Py_IncRef_StackRef(_PyStackRef tagged) { + _Py_STACKREF_INCREF(_PyStackRef tagged) { if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) { assert(_PyObject_HasDeferredRefcount(Py_STACKREF_UNTAG_BORROWED(tagged))); return; } - Py_INCREF(Py_STACKREF_UNTAG_BORROWED(tagged)); + return Py_INCREF(Py_STACKREF_UNTAG_BORROWED(tagged)); } - #define Py_INCREF_STACKREF(op) _Py_IncRef_StackRef(op) + #define Py_STACKREF_INCREF(op) _Py_STACKREF_INCREF(op) #else - #define Py_INCREF_STACKREF(op) Py_INCREF(Py_STACKREF_UNTAG_BORROWED(op)) + #define Py_STACKREF_INCREF(op) Py_INCREF(Py_STACKREF_UNTAG_BORROWED(op)) #endif static inline void -_Py_XDECREF_STACKREF(_PyStackRef op) +_Py_STACKREF_XDECREF(_PyStackRef op) { if (Py_STACKREF_UNTAG_BORROWED(op) != NULL) { - Py_DECREF_STACKREF(op); + Py_STACKREF_DECREF(op); } } -#define Py_XDECREF_STACKREF(op) _Py_XDECREF_STACKREF(op) +#define Py_STACKREF_XDECREF(op) _Py_STACKREF_XDECREF(op) static inline _PyStackRef -_Py_NewRef_StackRef(_PyStackRef obj) +_Py_StackRef_NewRef(_PyStackRef obj) { - Py_INCREF_STACKREF(obj); + Py_STACKREF_INCREF(obj); return obj; } - -#define Py_NewRef_StackRef(op) _Py_NewRef_StackRef(op) +#define Py_StackRef_NewRef(op) _Py_StackRef_NewRef(op) #ifdef __cplusplus } From 35ac0ce7b2ebd730266481ec0c4155977b3d5621 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Sun, 28 Apr 2024 16:14:50 +0800 Subject: [PATCH 07/19] fix warning --- Include/internal/pycore_tagged.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/internal/pycore_tagged.h b/Include/internal/pycore_tagged.h index 88e7e847498ced..f9e422eb03cb79 100644 --- a/Include/internal/pycore_tagged.h +++ b/Include/internal/pycore_tagged.h @@ -162,7 +162,7 @@ _Py_untag_stack_owned(PyObject **dst, const _PyStackRef *src, size_t length) { assert(_PyObject_HasDeferredRefcount(Py_STACKREF_UNTAG_BORROWED(tagged))); return; } - return Py_INCREF(Py_STACKREF_UNTAG_BORROWED(tagged)); + Py_INCREF(Py_STACKREF_UNTAG_BORROWED(tagged)); } #define Py_STACKREF_INCREF(op) _Py_STACKREF_INCREF(op) #else From c08a6f5500d2f6a4da184bf212a37b641cfb5327 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 30 Apr 2024 20:35:37 +0800 Subject: [PATCH 08/19] address rest of review --- Include/internal/pycore_tagged.h | 125 ++++++++++++++----------------- 1 file changed, 55 insertions(+), 70 deletions(-) diff --git a/Include/internal/pycore_tagged.h b/Include/internal/pycore_tagged.h index f9e422eb03cb79..3c5e9fc9b708cc 100644 --- a/Include/internal/pycore_tagged.h +++ b/Include/internal/pycore_tagged.h @@ -30,71 +30,47 @@ typedef union { } _PyStackRef; #ifdef Py_GIL_DISABLED - #define Py_TAG_DEFERRED (0b1) + #define Py_TAG_DEFERRED (1) #define Py_TAG (Py_TAG_DEFERRED) #else - // Define this to test for tagged pointer leakage in the ceval stack. - // #define Py_TAG_TEST (0b1) #define Py_TAG 0 #endif -#if defined(Py_TAG_TEST) - #define Py_STACKREF_UNTAG_BORROWED(tagged) ((PyObject *)(uintptr_t)((tagged).bits & (~Py_TAG_TEST))) -#elif defined(Py_GIL_DISABLED) +// Gets a PyObject * from a _PyStackRef +#if defined(Py_GIL_DISABLED) static inline PyObject * - _Py_STACKREF_UNTAG_BORROWED(_PyStackRef tagged) { + PyStackRef_Get(_PyStackRef tagged) { PyObject *cleared = ((PyObject *)((tagged).bits & (~Py_TAG))); return cleared; } - #define Py_STACKREF_UNTAG_BORROWED(tagged) _Py_STACKREF_UNTAG_BORROWED(tagged) #else - #define Py_STACKREF_UNTAG_BORROWED(tagged) ((PyObject *)(uintptr_t)((tagged).bits)) + #define PyStackRef_Get(tagged) ((PyObject *)(uintptr_t)((tagged).bits)) #endif -#if defined(Py_TAG_TEST) - #define Py_STACKREF_TAG(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj) | Py_TAG_TEST)}) -#elif defined(Py_GIL_DISABLED) +// Converts a PyObject * to a PyStackRef, stealing the reference. +#if defined(Py_GIL_DISABLED) static inline _PyStackRef - _Py_STACKREF_TAG(PyObject *obj) { + _PyStackRef_StealRef(PyObject *obj) { // Make sure we don't take an already tagged value. - assert(Py_STACKREF_UNTAG_BORROWED(((_PyStackRef){.bits = ((uintptr_t)(obj))})) == obj); + assert(PyStackRef_Get(((_PyStackRef){.bits = ((uintptr_t)(obj))})) == obj); return ((_PyStackRef){.bits = ((uintptr_t)(obj))}); } - #define Py_STACKREF_TAG(obj) _Py_STACKREF_TAG(_PyObject_CAST(obj)) -#else - #define Py_STACKREF_TAG(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))}) -#endif - -#if defined(Py_TAG_TEST) - #define Py_STACKREF_TAG_DEFERRED(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj) | Py_TAG_TEST)}) -#elif defined(Py_GIL_DISABLED) - static inline _PyStackRef - _Py_STACKREF_TAG_DEFERRED(PyObject *obj) { - // Make sure we don't take an already tagged value. - assert(Py_STACKREF_UNTAG_BORROWED(((_PyStackRef){.bits = ((uintptr_t)(obj))})) == obj); - int is_deferred = (obj != NULL && _PyObject_HasDeferredRefcount(obj)); - int tag = (is_deferred ? Py_TAG_DEFERRED : 0); - return ((_PyStackRef){.bits = ((uintptr_t)(obj) | tag)}); - } - #define Py_STACKREF_TAG_DEFERRED(obj) _Py_STACKREF_TAG_DEFERRED(_PyObject_CAST(obj)) + #define PyStackRef_StealRef(obj) _PyStackRef_StealRef(_PyObject_CAST(obj)) #else - #define Py_STACKREF_TAG_DEFERRED(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))}) + #define PyStackRef_StealRef(obj) ((_PyStackRef){.bits = ((uintptr_t)(obj))}) #endif -#if defined(Py_TAG_TEST) - #define Py_STACKREF_UNTAG_OWNED(tagged) Py_STACKREF_UNTAG_BORROWED(tagged) -#elif defined(Py_GIL_DISABLED) +#if defined(Py_GIL_DISABLED) static inline PyObject * - _Py_STACKREF_UNTAG_OWNED(_PyStackRef tagged) { + PyStackRef_StealObject(_PyStackRef tagged) { if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) { - assert(_PyObject_HasDeferredRefcount(Py_STACKREF_UNTAG_BORROWED(tagged))); - return Py_NewRef(Py_STACKREF_UNTAG_BORROWED(tagged)); + assert(_PyObject_HasDeferredRefcount(PyStackRef_Get(tagged))); + return Py_NewRef(PyStackRef_Get(tagged)); } - return Py_STACKREF_UNTAG_BORROWED(tagged); + return PyStackRef_Get(tagged); } - #define Py_STACKREF_UNTAG_OWNED(tagged) _Py_STACKREF_UNTAG_OWNED(tagged) #else - #define Py_STACKREF_UNTAG_OWNED(tagged) Py_STACKREF_UNTAG_BORROWED(tagged) + #define PyStackRef_StealObject(tagged) PyStackRef_Get(tagged) #endif #define MAX_UNTAG_SCRATCH 10 @@ -102,91 +78,100 @@ typedef union { 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] = Py_STACKREF_UNTAG_BORROWED(src[i]); + dst[i] = PyStackRef_Get(src[i]); } } static inline void -_Py_untag_stack_owned(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] = Py_STACKREF_UNTAG_OWNED(src[i]); + dst[i] = PyStackRef_StealObject(src[i]); } } -#define Py_STACKREF_XSETREF(dst, src) \ +#define PyStackRef_XSETREF(dst, src) \ do { \ _PyStackRef *_tmp_dst_ptr = _Py_CAST(_PyStackRef*, &(dst)); \ _PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \ *_tmp_dst_ptr = (src); \ - Py_STACKREF_XDECREF(_tmp_old_dst); \ + PyStackRef_XDECREF(_tmp_old_dst); \ } while (0) -#define Py_STACKREF_SETREF(dst, src) \ +#define PyStackRef_SETREF(dst, src) \ do { \ _PyStackRef *_tmp_dst_ptr = _Py_CAST(_PyStackRef*, &(dst)); \ _PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \ *_tmp_dst_ptr = (src); \ - Py_STACKREF_DECREF(_tmp_old_dst); \ + PyStackRef_DECREF(_tmp_old_dst); \ } while (0) -#define Py_STACKREF_CLEAR(op) \ +#define PyStackRef_CLEAR(op) \ do { \ _PyStackRef *_tmp_op_ptr = _Py_CAST(_PyStackRef*, &(op)); \ _PyStackRef _tmp_old_op = (*_tmp_op_ptr); \ - if (Py_STACKREF_UNTAG_BORROWED(_tmp_old_op) != NULL) { \ - *_tmp_op_ptr = Py_STACKREF_TAG(_Py_NULL); \ - Py_STACKREF_DECREF(_tmp_old_op); \ + if (PyStackRef_Get(_tmp_old_op) != NULL) { \ + *_tmp_op_ptr = PyStackRef_StealRef(_Py_NULL); \ + PyStackRef_DECREF(_tmp_old_op); \ } \ } while (0) #if defined(Py_GIL_DISABLED) static inline void - _Py_STACKREF_DECREF(_PyStackRef tagged) { + PyStackRef_DECREF(_PyStackRef tagged) { if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) { return; } - Py_DECREF(Py_STACKREF_UNTAG_BORROWED(tagged)); + Py_DECREF(PyStackRef_Get(tagged)); } - #define Py_STACKREF_DECREF(op) _Py_STACKREF_DECREF(op) #else - #define Py_STACKREF_DECREF(op) Py_DECREF(Py_STACKREF_UNTAG_BORROWED(op)) + #define PyStackRef_DECREF(op) Py_DECREF(PyStackRef_Get(op)) #endif -#define Py_STACKREF_DECREF_OWNED(op) Py_DECREF(Py_STACKREF_UNTAG_BORROWED(op)); +#define PyStackRef_DECREF_OWNED(op) Py_DECREF(PyStackRef_Get(op)); #if defined(Py_GIL_DISABLED) static inline void - _Py_STACKREF_INCREF(_PyStackRef tagged) { + PyStackRef_INCREF(_PyStackRef tagged) { if ((tagged.bits & Py_TAG_DEFERRED) == Py_TAG_DEFERRED) { - assert(_PyObject_HasDeferredRefcount(Py_STACKREF_UNTAG_BORROWED(tagged))); + assert(_PyObject_HasDeferredRefcount(PyStackRef_Get(tagged))); return; } - Py_INCREF(Py_STACKREF_UNTAG_BORROWED(tagged)); + Py_INCREF(PyStackRef_Get(tagged)); } - #define Py_STACKREF_INCREF(op) _Py_STACKREF_INCREF(op) #else - #define Py_STACKREF_INCREF(op) Py_INCREF(Py_STACKREF_UNTAG_BORROWED(op)) + #define PyStackRef_INCREF(op) Py_INCREF(PyStackRef_Get(op)) #endif static inline void -_Py_STACKREF_XDECREF(_PyStackRef op) +PyStackRef_XDECREF(_PyStackRef op) { - if (Py_STACKREF_UNTAG_BORROWED(op) != NULL) { - Py_STACKREF_DECREF(op); + if (PyStackRef_Get(op) != NULL) { + PyStackRef_DECREF(op); } } -#define Py_STACKREF_XDECREF(op) _Py_STACKREF_XDECREF(op) - static inline _PyStackRef -_Py_StackRef_NewRef(_PyStackRef obj) +PyStackRef_NewRef(_PyStackRef obj) { - Py_STACKREF_INCREF(obj); + PyStackRef_INCREF(obj); return obj; } -#define Py_StackRef_NewRef(op) _Py_StackRef_NewRef(op) +// 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_NewRef((_PyStackRef){.bits = ((uintptr_t)(obj) | tag)}); + } + #define PyStackRef_NewRefDeferred(obj) _PyStackRef_NewRefDeferred(_PyObject_CAST(obj)) +#else + #define PyStackRef_NewRefDeferred(obj) PyStackRef_NewRef(((_PyStackRef){.bits = ((uintptr_t)(obj))})) +#endif #ifdef __cplusplus } From 9b5f8b25733142ad16b52d9cc192705240916f91 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 30 Apr 2024 20:36:21 +0800 Subject: [PATCH 09/19] remove MAX_UNTAG_SCRATCH --- Include/internal/pycore_tagged.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Include/internal/pycore_tagged.h b/Include/internal/pycore_tagged.h index 3c5e9fc9b708cc..f78d89945f41a4 100644 --- a/Include/internal/pycore_tagged.h +++ b/Include/internal/pycore_tagged.h @@ -73,8 +73,6 @@ typedef union { #define PyStackRef_StealObject(tagged) PyStackRef_Get(tagged) #endif -#define MAX_UNTAG_SCRATCH 10 - static inline void _Py_untag_stack_borrowed(PyObject **dst, const _PyStackRef *src, size_t length) { for (size_t i = 0; i < length; i++) { From 046e3081ceb4bd5a0fc50937b0fc0540822014c0 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 30 Apr 2024 20:38:22 +0800 Subject: [PATCH 10/19] rename file --- Include/internal/{pycore_tagged.h => pycore_stackref.h} | 0 Makefile.pre.in | 2 +- Objects/codeobject.c | 2 +- Objects/descrobject.c | 2 +- Objects/funcobject.c | 2 +- Objects/moduleobject.c | 2 +- Objects/typeobject.c | 2 +- PCbuild/pythoncore.vcxproj | 2 +- PCbuild/pythoncore.vcxproj.filters | 2 +- Python/gc_free_threading.c | 2 +- 10 files changed, 9 insertions(+), 9 deletions(-) rename Include/internal/{pycore_tagged.h => pycore_stackref.h} (100%) diff --git a/Include/internal/pycore_tagged.h b/Include/internal/pycore_stackref.h similarity index 100% rename from Include/internal/pycore_tagged.h rename to Include/internal/pycore_stackref.h diff --git a/Makefile.pre.in b/Makefile.pre.in index 674ce8305c9d1e..f9c520fc31df35 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1225,7 +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_tagged.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/Objects/codeobject.c b/Objects/codeobject.c index c95e017726d724..7ead1fd655ca90 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -11,7 +11,7 @@ #include "pycore_opcode_utils.h" // RESUME_AT_FUNC_START #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_setobject.h" // _PySet_NextEntry() -#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount +#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "clinic/codeobject.c.h" diff --git a/Objects/descrobject.c b/Objects/descrobject.c index b0c562847f386a..42a406b4ef295f 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -9,7 +9,7 @@ #include "pycore_modsupport.h" // _PyArg_UnpackStack() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount +#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount #include "pycore_tuple.h" // _PyTuple_ITEMS() diff --git a/Objects/funcobject.c b/Objects/funcobject.c index c0f788f5ec8cbd..156e29db2877c8 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -6,7 +6,7 @@ #include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pyerrors.h" // _PyErr_Occurred() -#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount +#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount static const char * diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index 10b5f8adb26f70..ba8b554e635a1c 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -10,7 +10,7 @@ #include "pycore_object.h" // _PyType_AllocNoTrack #include "pycore_pyerrors.h" // _PyErr_FormatFromCause() #include "pycore_pystate.h" // _PyInterpreterState_GET() -#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount +#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount #include "osdefs.h" // MAXPATHLEN diff --git a/Objects/typeobject.c b/Objects/typeobject.c index e751b2f6c6fbc2..bb7cac4447e255 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -16,7 +16,7 @@ #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // _Py_Mangle() -#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount +#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount #include "pycore_typeobject.h" // struct type_cache #include "pycore_unionobject.h" // _Py_union_type_or #include "pycore_weakref.h" // _PyWeakref_GET_REF() diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index f5467366c5ba44..4cb3e0d3227092 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -291,7 +291,7 @@ - + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index d596c8d9f57a4b..0b858cf1eb46a8 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -789,7 +789,7 @@ Include\internal - + Include\internal diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index fab612f4726a0e..f75eb63d9f36ba 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -11,7 +11,7 @@ #include "pycore_object_stack.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_tagged.h" // _PyObject_SetDeferredRefcount +#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount #include "pycore_time.h" // _PyTime_GetPerfCounter() #include "pycore_tstate.h" // _PyThreadStateImpl #include "pycore_weakref.h" // _PyWeakref_ClearRef() From 1a7087ee3a84008d264fcfcfd7c4930a1e865806 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 30 Apr 2024 20:39:32 +0800 Subject: [PATCH 11/19] rename header guards --- Include/internal/pycore_stackref.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index f78d89945f41a4..05f2e85c2676fd 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -1,5 +1,5 @@ -#ifndef Py_INTERNAL_TAGGED_H -#define Py_INTERNAL_TAGGED_H +#ifndef Py_INTERNAL_STACKREF_H +#define Py_INTERNAL_STACKREF_H #ifdef __cplusplus extern "C" { #endif @@ -174,4 +174,4 @@ PyStackRef_NewRef(_PyStackRef obj) #ifdef __cplusplus } #endif -#endif /* !Py_INTERNAL_TAGGED_H */ +#endif /* !Py_INTERNAL_STACKREF_H */ From 2090980803563029deb6e3182353348d9d2bf201 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 30 Apr 2024 20:46:19 +0800 Subject: [PATCH 12/19] add xnewref --- Include/internal/pycore_stackref.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 05f2e85c2676fd..1d5d3e9487e673 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -156,6 +156,15 @@ PyStackRef_NewRef(_PyStackRef obj) return obj; } +static inline _PyStackRef +PyStackRef_XNewRef(_PyStackRef obj) +{ + if (PyStackRef_Get(obj) == NULL) { + return obj; + } + return PyStackRef_NewRef(obj); +} + // Converts a PyObject * to a PyStackRef, with a new reference #if defined(Py_GIL_DISABLED) static inline _PyStackRef @@ -164,7 +173,7 @@ PyStackRef_NewRef(_PyStackRef obj) 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_NewRef((_PyStackRef){.bits = ((uintptr_t)(obj) | tag)}); + return PyStackRef_XNewRef((_PyStackRef){.bits = ((uintptr_t)(obj) | tag)}); } #define PyStackRef_NewRefDeferred(obj) _PyStackRef_NewRefDeferred(_PyObject_CAST(obj)) #else From 2f50bcb678fe4261219fc1c8cb3e35ce34f60430 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 30 Apr 2024 20:52:24 +0800 Subject: [PATCH 13/19] Add Py_STACKREF_NULL --- Include/internal/pycore_stackref.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 1d5d3e9487e673..07409ba4832d4f 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -29,6 +29,8 @@ typedef union { uintptr_t bits; } _PyStackRef; +static const _PyStackRef Py_STACKREF_NULL = ((_PyStackRef) { .bits = (uintptr_t)NULL }); + #ifdef Py_GIL_DISABLED #define Py_TAG_DEFERRED (1) #define Py_TAG (Py_TAG_DEFERRED) @@ -144,7 +146,7 @@ _Py_untag_stack_steal(PyObject **dst, const _PyStackRef *src, size_t length) { static inline void PyStackRef_XDECREF(_PyStackRef op) { - if (PyStackRef_Get(op) != NULL) { + if (op.bits != Py_STACKREF_NULL.bits) { PyStackRef_DECREF(op); } } @@ -159,7 +161,7 @@ PyStackRef_NewRef(_PyStackRef obj) static inline _PyStackRef PyStackRef_XNewRef(_PyStackRef obj) { - if (PyStackRef_Get(obj) == NULL) { + if (obj.bits == Py_STACKREF_NULL.bits) { return obj; } return PyStackRef_NewRef(obj); From 5961992d5b62c8999153b5cb3f55e58983276c5c Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 30 Apr 2024 21:06:54 +0800 Subject: [PATCH 14/19] fix Windows build --- Include/internal/pycore_stackref.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 07409ba4832d4f..36339a9637b6f9 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -9,6 +9,7 @@ extern "C" { #endif #include +#include "pycore_gc.h" // Mark an object as supporting deferred reference counting. This is a no-op // in the default (with GIL) build. Objects that use deferred reference @@ -29,7 +30,7 @@ typedef union { uintptr_t bits; } _PyStackRef; -static const _PyStackRef Py_STACKREF_NULL = ((_PyStackRef) { .bits = (uintptr_t)NULL }); +static const _PyStackRef Py_STACKREF_NULL = ((_PyStackRef) { .bits = 0 }); #ifdef Py_GIL_DISABLED #define Py_TAG_DEFERRED (1) From 6bf6d440142b8226d92d2a4b71dc748cc3ab4bb6 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Tue, 30 Apr 2024 21:23:20 +0800 Subject: [PATCH 15/19] try fix Windows for real this time Co-Authored-By: Sam Gross <655866+colesbury@users.noreply.github.com> --- Include/internal/pycore_stackref.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 36339a9637b6f9..5d81e52571405c 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -30,7 +30,7 @@ typedef union { uintptr_t bits; } _PyStackRef; -static const _PyStackRef Py_STACKREF_NULL = ((_PyStackRef) { .bits = 0 }); +static const _PyStackRef Py_STACKREF_NULL = { .bits = 0 }; #ifdef Py_GIL_DISABLED #define Py_TAG_DEFERRED (1) From 003d274650dddd5c872d6d42fb9b9647e17154c6 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Wed, 1 May 2024 02:04:36 +0800 Subject: [PATCH 16/19] address review Co-Authored-By: Sam Gross <655866+colesbury@users.noreply.github.com> --- Include/internal/pycore_stackref.h | 143 +++++++++++++++++------------ 1 file changed, 84 insertions(+), 59 deletions(-) diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 5d81e52571405c..0b42d9094f007c 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -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]); } @@ -93,7 +93,7 @@ _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) \ _PyStackRef _tmp_old_dst = (*_tmp_dst_ptr); \ *_tmp_dst_ptr = (src); \ PyStackRef_XDECREF(_tmp_old_dst); \ @@ -101,7 +101,7 @@ _Py_untag_stack_steal(PyObject **dst, const _PyStackRef *src, size_t length) { #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); \ @@ -109,39 +109,41 @@ _Py_untag_stack_steal(PyObject **dst, const _PyStackRef *src, size_t length) { #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 @@ -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 From 75013570b29b585266dec3447a18173873333d32 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Wed, 1 May 2024 02:07:20 +0800 Subject: [PATCH 17/19] revert hasdeferred refcount back to original file --- Include/internal/pycore_object.h | 14 ++++++++++++++ Include/internal/pycore_stackref.h | 16 ---------------- Objects/codeobject.c | 1 - Objects/descrobject.c | 1 - Objects/funcobject.c | 1 - Objects/moduleobject.c | 1 - Objects/typeobject.c | 1 - Python/gc_free_threading.c | 1 - 8 files changed, 14 insertions(+), 22 deletions(-) diff --git a/Include/internal/pycore_object.h b/Include/internal/pycore_object.h index a96f6cf578853f..7df8003196d8cc 100644 --- a/Include/internal/pycore_object.h +++ b/Include/internal/pycore_object.h @@ -159,6 +159,20 @@ static inline void _Py_ClearImmortal(PyObject *op) op = NULL; \ } while (0) +// Mark an object as supporting deferred reference counting. This is a no-op +// in the default (with GIL) build. Objects that use deferred reference +// counting should be tracked by the GC so that they are eventually collected. +extern void _PyObject_SetDeferredRefcount(PyObject *op); + +static inline int +_PyObject_HasDeferredRefcount(PyObject *op) +{ +#ifdef Py_GIL_DISABLED + return (op->ob_gc_bits & _PyGC_BITS_DEFERRED) != 0; +#else + return 0; +#endif +} #if !defined(Py_GIL_DISABLED) static inline void diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 0b42d9094f007c..d637db9d7b2840 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -9,22 +9,6 @@ extern "C" { #endif #include -#include "pycore_gc.h" - -// Mark an object as supporting deferred reference counting. This is a no-op -// in the default (with GIL) build. Objects that use deferred reference -// counting should be tracked by the GC so that they are eventually collected. -extern void _PyObject_SetDeferredRefcount(PyObject *op); - -static inline int -_PyObject_HasDeferredRefcount(PyObject *op) -{ -#ifdef Py_GIL_DISABLED - return (op->ob_gc_bits & _PyGC_BITS_DEFERRED) != 0; -#else - return 0; -#endif -} typedef union { uintptr_t bits; diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 7ead1fd655ca90..014632962bfcf3 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -11,7 +11,6 @@ #include "pycore_opcode_utils.h" // RESUME_AT_FUNC_START #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_setobject.h" // _PySet_NextEntry() -#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "clinic/codeobject.c.h" diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 42a406b4ef295f..1b7e2fde3ceccd 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -9,7 +9,6 @@ #include "pycore_modsupport.h" // _PyArg_UnpackStack() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount #include "pycore_tuple.h" // _PyTuple_ITEMS() diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 156e29db2877c8..276b3db2970371 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -6,7 +6,6 @@ #include "pycore_modsupport.h" // _PyArg_NoKeywords() #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pyerrors.h" // _PyErr_Occurred() -#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount static const char * diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index ba8b554e635a1c..2f6adb9a2e12be 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -10,7 +10,6 @@ #include "pycore_object.h" // _PyType_AllocNoTrack #include "pycore_pyerrors.h" // _PyErr_FormatFromCause() #include "pycore_pystate.h" // _PyInterpreterState_GET() -#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount #include "osdefs.h" // MAXPATHLEN diff --git a/Objects/typeobject.c b/Objects/typeobject.c index bb7cac4447e255..07e0a5a02da87f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -16,7 +16,6 @@ #include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_symtable.h" // _Py_Mangle() -#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount #include "pycore_typeobject.h" // struct type_cache #include "pycore_unionobject.h" // _Py_union_type_or #include "pycore_weakref.h" // _PyWeakref_GET_REF() diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index f75eb63d9f36ba..9cf0e989d0993f 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -11,7 +11,6 @@ #include "pycore_object_stack.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_stackref.h" // _PyObject_SetDeferredRefcount #include "pycore_time.h" // _PyTime_GetPerfCounter() #include "pycore_tstate.h" // _PyThreadStateImpl #include "pycore_weakref.h" // _PyWeakref_ClearRef() From 53608d7a8ae3a5f5a983d41bd7a457f10a854ec7 Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Wed, 1 May 2024 03:10:03 +0800 Subject: [PATCH 18/19] remove decref_owned --- Include/internal/pycore_stackref.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index d637db9d7b2840..bff8ff4627880d 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -114,8 +114,6 @@ PyStackRef_DECREF(_PyStackRef tagged) # 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) From 0131fc1e615490c53b5e93c1c7088ac6f5c96d2d Mon Sep 17 00:00:00 2001 From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Wed, 1 May 2024 03:54:34 +0800 Subject: [PATCH 19/19] address review --- Include/internal/pycore_stackref.h | 77 +++++++++++++++--------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index bff8ff4627880d..fd929cd4873a8b 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -27,7 +27,7 @@ PyStackRef_Get(_PyStackRef tagged) return cleared; } #else -# define PyStackRef_Get(tagged) ((PyObject *)(uintptr_t)((tagged).bits)) +# define PyStackRef_Get(tagged) ((PyObject *)((tagged).bits)) #endif // Converts a PyObject * to a PyStackRef, stealing the reference. @@ -44,6 +44,43 @@ _PyStackRef_StealRef(PyObject *obj) # 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) @@ -152,44 +189,6 @@ PyStackRef_XNewRef(_PyStackRef obj) return PyStackRef_NewRef(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(((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 }; - } - else { - return (_PyStackRef){ .bits = (uintptr_t)Py_XNewRef(obj) }; - } -} -# define PyStackRef_XNewRefDeferred(obj) _PyStackRef_XNewRefDeferred(_PyObject_CAST(obj)) -#else -# define PyStackRef_XNewRefDeferred(obj) PyStackRef_XNewRef(((_PyStackRef){.bits = ((uintptr_t)(obj))})) -#endif - #ifdef __cplusplus } #endif