mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	gh-131586: Avoid refcount contention in some "special" calls (#131588)
In the free threaded build, the `_PyObject_LookupSpecial()` call can lead to reference count contention on the returned function object becuase it doesn't use stackrefs. Refactor some of the callers to use `_PyObject_MaybeCallSpecialNoArgs`, which uses stackrefs internally. This fixes the scaling bottleneck in the "lookup_special" microbenchmark in `ftscalingbench.py`. However, the are still some uses of `_PyObject_LookupSpecial()` that need to be addressed in future PRs.
This commit is contained in:
		
							parent
							
								
									3d4ac1a2c2
								
							
						
					
					
						commit
						67fbfb42bd
					
				
					 16 changed files with 450 additions and 374 deletions
				
			
		|  | @ -592,7 +592,7 @@ PyStackRef_XCLOSE(_PyStackRef ref) | |||
| 
 | ||||
| // Note: this is a macro because MSVC (Windows) has trouble inlining it.
 | ||||
| 
 | ||||
| #define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_REFCNT)) == ((b).bits & (~Py_TAG_REFCNT))) | ||||
| #define PyStackRef_Is(a, b) (((a).bits & (~Py_TAG_BITS)) == ((b).bits & (~Py_TAG_BITS))) | ||||
| 
 | ||||
| #endif // !defined(Py_GIL_DISABLED) && defined(Py_STACKREF_DEBUG)
 | ||||
| 
 | ||||
|  | @ -640,6 +640,28 @@ PyStackRef_FunctionCheck(_PyStackRef stackref) | |||
|     return PyFunction_Check(PyStackRef_AsPyObjectBorrow(stackref)); | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| _PyThreadState_PushCStackRef(PyThreadState *tstate, _PyCStackRef *ref) | ||||
| { | ||||
| #ifdef Py_GIL_DISABLED | ||||
|     _PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate; | ||||
|     ref->next = tstate_impl->c_stack_refs; | ||||
|     tstate_impl->c_stack_refs = ref; | ||||
| #endif | ||||
|     ref->ref = PyStackRef_NULL; | ||||
| } | ||||
| 
 | ||||
| static inline void | ||||
| _PyThreadState_PopCStackRef(PyThreadState *tstate, _PyCStackRef *ref) | ||||
| { | ||||
| #ifdef Py_GIL_DISABLED | ||||
|     _PyThreadStateImpl *tstate_impl = (_PyThreadStateImpl *)tstate; | ||||
|     assert(tstate_impl->c_stack_refs == ref); | ||||
|     tstate_impl->c_stack_refs = ref->next; | ||||
| #endif | ||||
|     PyStackRef_XCLOSE(ref->ref); | ||||
| } | ||||
| 
 | ||||
| #ifdef Py_GIL_DISABLED | ||||
| 
 | ||||
| static inline int | ||||
|  | @ -656,6 +678,17 @@ _Py_TryIncrefCompareStackRef(PyObject **src, PyObject *op, _PyStackRef *out) | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| _Py_TryXGetStackRef(PyObject **src, _PyStackRef *out) | ||||
| { | ||||
|     PyObject *op = _Py_atomic_load_ptr_relaxed(src); | ||||
|     if (op == NULL) { | ||||
|         *out = PyStackRef_NULL; | ||||
|         return 1; | ||||
|     } | ||||
|     return _Py_TryIncrefCompareStackRef(src, op, out); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // Like Py_VISIT but for _PyStackRef fields
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sam Gross
						Sam Gross