mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	bpo-39573: Add Py_SET_REFCNT() function (GH-18389)
Add a Py_SET_REFCNT() function to set the reference counter of an object.
This commit is contained in:
		
							parent
							
								
									a93c51e3a8
								
							
						
					
					
						commit
						c86a11221d
					
				
					 7 changed files with 30 additions and 14 deletions
				
			
		|  | @ -79,6 +79,13 @@ the definition of all other Python objects. | |||
|       (((PyObject*)(o))->ob_refcnt) | ||||
| 
 | ||||
| 
 | ||||
| .. c:function:: void Py_SET_REFCNT(PyObject *o, Py_ssize_t refcnt) | ||||
| 
 | ||||
|    Set the object *o* reference counter to *refcnt*. | ||||
| 
 | ||||
|    .. versionadded:: 3.9 | ||||
| 
 | ||||
| 
 | ||||
| .. c:macro:: Py_SIZE(o) | ||||
| 
 | ||||
|    This macro is used to access the :attr:`ob_size` member of a Python object. | ||||
|  |  | |||
|  | @ -123,6 +123,11 @@ typedef struct { | |||
| #define Py_TYPE(ob)             (_PyObject_CAST(ob)->ob_type) | ||||
| #define Py_SIZE(ob)             (_PyVarObject_CAST(ob)->ob_size) | ||||
| 
 | ||||
| static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { | ||||
|     ob->ob_refcnt = refcnt; | ||||
| } | ||||
| #define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) | ||||
| 
 | ||||
| /*
 | ||||
| Type objects contain a string containing the type name (to help somewhat | ||||
| in debugging), the allocation parameters (see PyObject_New() and | ||||
|  |  | |||
|  | @ -0,0 +1,2 @@ | |||
| Add a :c:func:`Py_SET_REFCNT` function to set the reference counter of an | ||||
| object. | ||||
|  | @ -3551,7 +3551,7 @@ slot_tp_del(PyObject *self) | |||
| 
 | ||||
|     /* Temporarily resurrect the object. */ | ||||
|     assert(Py_REFCNT(self) == 0); | ||||
|     Py_REFCNT(self) = 1; | ||||
|     Py_SET_REFCNT(self, 1); | ||||
| 
 | ||||
|     /* Save the current exception, if any. */ | ||||
|     PyErr_Fetch(&error_type, &error_value, &error_traceback); | ||||
|  | @ -3574,7 +3574,8 @@ slot_tp_del(PyObject *self) | |||
|      * cause a recursive call. | ||||
|      */ | ||||
|     assert(Py_REFCNT(self) > 0); | ||||
|     if (--Py_REFCNT(self) == 0) { | ||||
|     Py_SET_REFCNT(self, Py_REFCNT(self) - 1); | ||||
|     if (Py_REFCNT(self) == 0) { | ||||
|         /* this is the normal path out */ | ||||
|         return; | ||||
|     } | ||||
|  | @ -3585,7 +3586,7 @@ slot_tp_del(PyObject *self) | |||
|     { | ||||
|         Py_ssize_t refcnt = Py_REFCNT(self); | ||||
|         _Py_NewReference(self); | ||||
|         Py_REFCNT(self) = refcnt; | ||||
|         Py_SET_REFCNT(self, refcnt); | ||||
|     } | ||||
|     assert(!PyType_IS_GC(Py_TYPE(self)) || _PyObject_GC_IS_TRACKED(self)); | ||||
|     /* If Py_REF_DEBUG macro is defined, _Py_NewReference() increased
 | ||||
|  | @ -4621,7 +4622,7 @@ check_pyobject_uninitialized_is_freed(PyObject *self, PyObject *Py_UNUSED(args)) | |||
|         return NULL; | ||||
|     } | ||||
|     /* Initialize reference count to avoid early crash in ceval or GC */ | ||||
|     Py_REFCNT(op) = 1; | ||||
|     Py_SET_REFCNT(op, 1); | ||||
|     /* object fields like ob_type are uninitialized! */ | ||||
|     return test_pyobject_is_freed("check_pyobject_uninitialized_is_freed", op); | ||||
| } | ||||
|  | @ -4636,7 +4637,7 @@ check_pyobject_forbidden_bytes_is_freed(PyObject *self, PyObject *Py_UNUSED(args | |||
|         return NULL; | ||||
|     } | ||||
|     /* Initialize reference count to avoid early crash in ceval or GC */ | ||||
|     Py_REFCNT(op) = 1; | ||||
|     Py_SET_REFCNT(op, 1); | ||||
|     /* ob_type field is after the memory block: part of "forbidden bytes"
 | ||||
|        when using debug hooks on memory allocators! */ | ||||
|     return test_pyobject_is_freed("check_pyobject_forbidden_bytes_is_freed", op); | ||||
|  | @ -4652,7 +4653,7 @@ check_pyobject_freed_is_freed(PyObject *self, PyObject *Py_UNUSED(args)) | |||
|     } | ||||
|     Py_TYPE(op)->tp_dealloc(op); | ||||
|     /* Reset reference count to avoid early crash in ceval or GC */ | ||||
|     Py_REFCNT(op) = 1; | ||||
|     Py_SET_REFCNT(op, 1); | ||||
|     /* object memory is freed! */ | ||||
|     return test_pyobject_is_freed("check_pyobject_freed_is_freed", op); | ||||
| } | ||||
|  | @ -5134,7 +5135,7 @@ negative_refcount(PyObject *self, PyObject *Py_UNUSED(args)) | |||
|     } | ||||
|     assert(Py_REFCNT(obj) == 1); | ||||
| 
 | ||||
|     Py_REFCNT(obj) = 0; | ||||
|     Py_SET_REFCNT(obj,  0); | ||||
|     /* Py_DECREF() must call _Py_NegativeRefcount() and abort Python */ | ||||
|     Py_DECREF(obj); | ||||
| 
 | ||||
|  |  | |||
|  | @ -51,7 +51,7 @@ PyModuleDef_Init(struct PyModuleDef* def) | |||
|          return NULL; | ||||
|     if (def->m_base.m_index == 0) { | ||||
|         max_module_number++; | ||||
|         Py_REFCNT(def) = 1; | ||||
|         Py_SET_REFCNT(def, 1); | ||||
|         Py_TYPE(def) = &PyModuleDef_Type; | ||||
|         def->m_base.m_index = max_module_number; | ||||
|     } | ||||
|  |  | |||
|  | @ -213,7 +213,7 @@ PyObject_CallFinalizerFromDealloc(PyObject *self) | |||
|     } | ||||
| 
 | ||||
|     /* Temporarily resurrect the object. */ | ||||
|     Py_REFCNT(self) = 1; | ||||
|     Py_SET_REFCNT(self, 1); | ||||
| 
 | ||||
|     PyObject_CallFinalizer(self); | ||||
| 
 | ||||
|  | @ -223,7 +223,8 @@ PyObject_CallFinalizerFromDealloc(PyObject *self) | |||
| 
 | ||||
|     /* Undo the temporary resurrection; can't use DECREF here, it would
 | ||||
|      * cause a recursive call. */ | ||||
|     if (--Py_REFCNT(self) == 0) { | ||||
|     Py_SET_REFCNT(self, Py_REFCNT(self) - 1); | ||||
|     if (Py_REFCNT(self) == 0) { | ||||
|         return 0;         /* this is the normal path out */ | ||||
|     } | ||||
| 
 | ||||
|  | @ -231,7 +232,7 @@ PyObject_CallFinalizerFromDealloc(PyObject *self) | |||
|      * never happened. */ | ||||
|     Py_ssize_t refcnt = Py_REFCNT(self); | ||||
|     _Py_NewReference(self); | ||||
|     Py_REFCNT(self) = refcnt; | ||||
|     Py_SET_REFCNT(self, refcnt); | ||||
| 
 | ||||
|     _PyObject_ASSERT(self, | ||||
|                      (!PyType_IS_GC(Py_TYPE(self)) | ||||
|  | @ -1818,7 +1819,7 @@ _Py_NewReference(PyObject *op) | |||
| #ifdef Py_REF_DEBUG | ||||
|     _Py_RefTotal++; | ||||
| #endif | ||||
|     Py_REFCNT(op) = 1; | ||||
|     Py_SET_REFCNT(op, 1); | ||||
| #ifdef Py_TRACE_REFS | ||||
|     _Py_AddToAllObjects(op, 1); | ||||
| #endif | ||||
|  |  | |||
|  | @ -1903,7 +1903,7 @@ unicode_dealloc(PyObject *unicode) | |||
| 
 | ||||
|     case SSTATE_INTERNED_MORTAL: | ||||
|         /* revive dead object temporarily for DelItem */ | ||||
|         Py_REFCNT(unicode) = 3; | ||||
|         Py_SET_REFCNT(unicode, 3); | ||||
|         if (PyDict_DelItem(interned, unicode) != 0) { | ||||
|             _PyErr_WriteUnraisableMsg("deletion of interned string failed", | ||||
|                                       NULL); | ||||
|  | @ -15367,7 +15367,7 @@ PyUnicode_InternInPlace(PyObject **p) | |||
|     } | ||||
|     /* The two references in interned are not counted by refcnt.
 | ||||
|        The deallocator will take care of this */ | ||||
|     Py_REFCNT(s) -= 2; | ||||
|     Py_SET_REFCNT(s, Py_REFCNT(s) - 2); | ||||
|     _PyUnicode_STATE(s).interned = SSTATE_INTERNED_MORTAL; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Victor Stinner
						Victor Stinner