cpython/Tools/c-analyzer/cpython/_files.py
Dino Viehland 05f2f0ac92
gh-90815: Add mimalloc memory allocator (#109914)
* Add mimalloc v2.12

Modified src/alloc.c to remove include of alloc-override.c and not
compile new handler.

Did not include the following files:

 - include/mimalloc-new-delete.h
 - include/mimalloc-override.h
 - src/alloc-override-osx.c
 - src/alloc-override.c
 - src/static.c
 - src/region.c

mimalloc is thread safe and shares a single heap across all runtimes,
therefore finalization and getting global allocated blocks across all
runtimes is different.

* mimalloc: minimal changes for use in Python:

 - remove debug spam for freeing large allocations
 - use same bytes (0xDD) for freed allocations in CPython and mimalloc
   This is important for the test_capi debug memory tests

* Don't export mimalloc symbol in libpython.
* Enable mimalloc as Python allocator option.
* Add mimalloc MIT license.
* Log mimalloc in Lib/test/pythoninfo.py.
* Document new mimalloc support.
* Use macro defs for exports as done in:
  https://github.com/python/cpython/pull/31164/

Co-authored-by: Sam Gross <colesbury@gmail.com>
Co-authored-by: Christian Heimes <christian@python.org>
Co-authored-by: Victor Stinner <vstinner@python.org>
2023-10-30 15:43:11 +00:00

72 lines
2.1 KiB
Python

import os.path
from c_common.fsutil import expand_filenames, iter_files_by_suffix
from . import REPO_ROOT, INCLUDE_DIRS, SOURCE_DIRS
GLOBS = [
'Include/*.h',
# Technically, this is covered by "Include/*.h":
#'Include/cpython/*.h',
'Include/internal/*.h',
'Include/internal/mimalloc/**/*.h',
'Modules/**/*.h',
'Modules/**/*.c',
'Objects/**/*.h',
'Objects/**/*.c',
'Parser/**/*.h',
'Parser/**/*.c',
'Python/**/*.h',
'Python/**/*.c',
]
LEVEL_GLOBS = {
'stable': 'Include/*.h',
'cpython': 'Include/cpython/*.h',
'internal': 'Include/internal/*.h',
}
def resolve_filename(filename):
orig = filename
filename = os.path.normcase(os.path.normpath(filename))
if os.path.isabs(filename):
if os.path.relpath(filename, REPO_ROOT).startswith('.'):
raise Exception(f'{orig!r} is outside the repo ({REPO_ROOT})')
return filename
else:
return os.path.join(REPO_ROOT, filename)
def iter_filenames(*, search=False):
if search:
yield from iter_files_by_suffix(INCLUDE_DIRS, ('.h',))
yield from iter_files_by_suffix(SOURCE_DIRS, ('.c',))
else:
globs = (os.path.join(REPO_ROOT, file) for file in GLOBS)
yield from expand_filenames(globs)
def iter_header_files(filenames=None, *, levels=None):
if not filenames:
if levels:
levels = set(levels)
if 'private' in levels:
levels.add('stable')
levels.add('cpython')
for level, glob in LEVEL_GLOBS.items():
if level in levels:
yield from expand_filenames([glob])
else:
yield from iter_files_by_suffix(INCLUDE_DIRS, ('.h',))
return
for filename in filenames:
orig = filename
filename = resolve_filename(filename)
if filename.endswith(os.path.sep):
yield from iter_files_by_suffix(INCLUDE_DIRS, ('.h',))
elif filename.endswith('.h'):
yield filename
else:
# XXX Log it and continue instead?
raise ValueError(f'expected .h file, got {orig!r}')