Skip to content

Commit b331381

Browse files
authored
gh-112529: Track if debug allocator is used as underlying allocator (#113747)
* gh-112529: Track if debug allocator is used as underlying allocator The GC implementation for free-threaded builds will need to accurately detect if the debug allocator is used because it affects the offset of the Python object from the beginning of the memory allocation. The current implementation of `_PyMem_DebugEnabled` only considers if the debug allocator is the outer-most allocator; it doesn't handle the case of "hooks" like tracemalloc being used on top of the debug allocator. This change enables more accurate detection of the debug allocator by tracking when debug hooks are enabled. * Simplify _PyMem_DebugEnabled
1 parent c86571e commit b331381

File tree

4 files changed

+21
-6
lines changed

4 files changed

+21
-6
lines changed

Include/internal/pycore_pymem.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct _pymem_allocators {
4444
debug_alloc_api_t mem;
4545
debug_alloc_api_t obj;
4646
} debug;
47+
int is_debug_enabled;
4748
PyObjectArenaAllocator obj_arena;
4849
};
4950

@@ -106,6 +107,8 @@ extern int _PyMem_GetAllocatorName(
106107
PYMEM_ALLOCATOR_NOT_SET does nothing. */
107108
extern int _PyMem_SetupAllocators(PyMemAllocatorName allocator);
108109

110+
/* Is the debug allocator enabled? */
111+
extern int _PyMem_DebugEnabled(void);
109112

110113
#ifdef __cplusplus
111114
}

Include/internal/pycore_pymem_init.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,15 @@ extern void _PyMem_ArenaFree(void *, void *, size_t);
7070
PYDBGMEM_ALLOC(runtime), \
7171
PYDBGOBJ_ALLOC(runtime), \
7272
}
73+
# define _pymem_is_debug_enabled_INIT 1
7374
#else
7475
# define _pymem_allocators_standard_INIT(runtime) \
7576
{ \
7677
PYRAW_ALLOC, \
7778
PYMEM_ALLOC, \
7879
PYOBJ_ALLOC, \
7980
}
81+
# define _pymem_is_debug_enabled_INIT 0
8082
#endif
8183

8284
#define _pymem_allocators_debug_INIT \

Include/internal/pycore_runtime_init.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ extern PyTypeObject _PyExc_MemoryError;
8686
.standard = _pymem_allocators_standard_INIT(runtime), \
8787
.debug = _pymem_allocators_debug_INIT, \
8888
.obj_arena = _pymem_allocators_obj_arena_INIT, \
89+
.is_debug_enabled = _pymem_is_debug_enabled_INIT, \
8990
}, \
9091
.obmalloc = _obmalloc_global_state_INIT, \
9192
.pyhash_state = pyhash_state_INIT, \

Objects/obmalloc.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -439,12 +439,14 @@ set_up_allocators_unlocked(PyMemAllocatorName allocator)
439439
(void)set_default_allocator_unlocked(PYMEM_DOMAIN_RAW, pydebug, NULL);
440440
(void)set_default_allocator_unlocked(PYMEM_DOMAIN_MEM, pydebug, NULL);
441441
(void)set_default_allocator_unlocked(PYMEM_DOMAIN_OBJ, pydebug, NULL);
442+
_PyRuntime.allocators.is_debug_enabled = pydebug;
442443
break;
443444

444445
case PYMEM_ALLOCATOR_DEBUG:
445446
(void)set_default_allocator_unlocked(PYMEM_DOMAIN_RAW, 1, NULL);
446447
(void)set_default_allocator_unlocked(PYMEM_DOMAIN_MEM, 1, NULL);
447448
(void)set_default_allocator_unlocked(PYMEM_DOMAIN_OBJ, 1, NULL);
449+
_PyRuntime.allocators.is_debug_enabled = 1;
448450
break;
449451

450452
#ifdef WITH_PYMALLOC
@@ -458,7 +460,9 @@ set_up_allocators_unlocked(PyMemAllocatorName allocator)
458460
set_allocator_unlocked(PYMEM_DOMAIN_MEM, &pymalloc);
459461
set_allocator_unlocked(PYMEM_DOMAIN_OBJ, &pymalloc);
460462

461-
if (allocator == PYMEM_ALLOCATOR_PYMALLOC_DEBUG) {
463+
int is_debug = (allocator == PYMEM_ALLOCATOR_PYMALLOC_DEBUG);
464+
_PyRuntime.allocators.is_debug_enabled = is_debug;
465+
if (is_debug) {
462466
set_up_debug_hooks_unlocked();
463467
}
464468
break;
@@ -477,7 +481,9 @@ set_up_allocators_unlocked(PyMemAllocatorName allocator)
477481
PyMemAllocatorEx objmalloc = MIMALLOC_OBJALLOC;
478482
set_allocator_unlocked(PYMEM_DOMAIN_OBJ, &objmalloc);
479483

480-
if (allocator == PYMEM_ALLOCATOR_MIMALLOC_DEBUG) {
484+
int is_debug = (allocator == PYMEM_ALLOCATOR_MIMALLOC_DEBUG);
485+
_PyRuntime.allocators.is_debug_enabled = is_debug;
486+
if (is_debug) {
481487
set_up_debug_hooks_unlocked();
482488
}
483489

@@ -493,7 +499,9 @@ set_up_allocators_unlocked(PyMemAllocatorName allocator)
493499
set_allocator_unlocked(PYMEM_DOMAIN_MEM, &malloc_alloc);
494500
set_allocator_unlocked(PYMEM_DOMAIN_OBJ, &malloc_alloc);
495501

496-
if (allocator == PYMEM_ALLOCATOR_MALLOC_DEBUG) {
502+
int is_debug = (allocator == PYMEM_ALLOCATOR_MALLOC_DEBUG);
503+
_PyRuntime.allocators.is_debug_enabled = is_debug;
504+
if (is_debug) {
497505
set_up_debug_hooks_unlocked();
498506
}
499507
break;
@@ -604,13 +612,13 @@ _PyMem_GetCurrentAllocatorName(void)
604612
}
605613

606614

607-
#ifdef WITH_PYMALLOC
608-
static int
615+
int
609616
_PyMem_DebugEnabled(void)
610617
{
611-
return (_PyObject.malloc == _PyMem_DebugMalloc);
618+
return _PyRuntime.allocators.is_debug_enabled;
612619
}
613620

621+
#ifdef WITH_PYMALLOC
614622
static int
615623
_PyMem_PymallocEnabled(void)
616624
{
@@ -695,6 +703,7 @@ set_up_debug_hooks_unlocked(void)
695703
set_up_debug_hooks_domain_unlocked(PYMEM_DOMAIN_RAW);
696704
set_up_debug_hooks_domain_unlocked(PYMEM_DOMAIN_MEM);
697705
set_up_debug_hooks_domain_unlocked(PYMEM_DOMAIN_OBJ);
706+
_PyRuntime.allocators.is_debug_enabled = 1;
698707
}
699708

700709
void

0 commit comments

Comments
 (0)