https://github.com/python/cpython/commit/4242c2b8d073c740164b82725270fd691bda03c8 commit: 4242c2b8d073c740164b82725270fd691bda03c8 branch: main author: Irit Katriel <1055913+iritkatr...@users.noreply.github.com> committer: iritkatriel <1055913+iritkatr...@users.noreply.github.com> date: 2025-03-13T16:02:58Z summary:
gh-130080: move _Py_EnsureArrayLargeEnough to a separate header so it can be used outside of the compiler (#130930) files: A Include/internal/pycore_c_array.h M Include/internal/pycore_compile.h M Python/codegen.c M Python/flowgraph.c M Python/instruction_sequence.c diff --git a/Include/internal/pycore_c_array.h b/Include/internal/pycore_c_array.h new file mode 100644 index 00000000000000..7a10fc866c88f1 --- /dev/null +++ b/Include/internal/pycore_c_array.h @@ -0,0 +1,39 @@ +#ifndef Py_INTERNAL_C_ARRAY_H +#define Py_INTERNAL_C_ARRAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + + +/* Utility for a number of growing arrays */ + +typedef struct { + void *array; /* pointer to the array */ + int allocated_entries; /* pointer to the capacity of the array */ + size_t item_size; /* size of each element */ + int initial_num_entries; /* initial allocation size */ +} _Py_c_array_t; + + +int _Py_CArray_Init(_Py_c_array_t* array, int item_size, int initial_num_entries); +void _Py_CArray_Fini(_Py_c_array_t* array); + +/* If idx is out of bounds: + * If arr->array is NULL, allocate arr->initial_num_entries slots. + * Otherwise, double its size. + * + * Return 0 if successful and -1 (with exception set) otherwise. + */ +int _Py_CArray_EnsureCapacity(_Py_c_array_t *c_array, int idx); + + +#ifdef __cplusplus +} +#endif + +#endif /* !Py_INTERNAL_C_ARRAY_H */ diff --git a/Include/internal/pycore_compile.h b/Include/internal/pycore_compile.h index b61ac8fccdca14..5b08bb6f8a7135 100644 --- a/Include/internal/pycore_compile.h +++ b/Include/internal/pycore_compile.h @@ -183,14 +183,6 @@ int _PyCodegen_Expression(struct _PyCompiler *c, expr_ty e); int _PyCodegen_Body(struct _PyCompiler *c, _Py_SourceLocation loc, asdl_stmt_seq *stmts, bool is_interactive); -/* Utility for a number of growing arrays used in the compiler */ -int _PyCompile_EnsureArrayLargeEnough( - int idx, - void **array, - int *alloc, - int default_alloc, - size_t item_size); - int _PyCompile_ConstCacheMergeOne(PyObject *const_cache, PyObject **obj); PyCodeObject *_PyCompile_OptimizeAndAssemble(struct _PyCompiler *c, int addNone); diff --git a/Python/codegen.c b/Python/codegen.c index 6ef3c63b33530e..a3eca2a6580c8e 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -18,6 +18,7 @@ #define NEED_OPCODE_TABLES #include "pycore_opcode_utils.h" #undef NEED_OPCODE_TABLES +#include "pycore_c_array.h" // _Py_c_array_t #include "pycore_compile.h" #include "pycore_instruction_sequence.h" // _PyInstructionSequence_NewLabel() #include "pycore_intrinsics.h" @@ -100,40 +101,48 @@ static const int compare_masks[] = { [Py_GE] = COMPARISON_GREATER_THAN | COMPARISON_EQUALS, }; -/* - * Resize the array if index is out of range. - * - * idx: the index we want to access - * arr: pointer to the array - * alloc: pointer to the capacity of the array - * default_alloc: initial number of items - * item_size: size of each item - * - */ + +int +_Py_CArray_Init(_Py_c_array_t* array, int item_size, int initial_num_entries) { + memset(array, 0, sizeof(_Py_c_array_t)); + array->item_size = item_size; + array->initial_num_entries = initial_num_entries; + return 0; +} + +void +_Py_CArray_Fini(_Py_c_array_t* array) +{ + if (array->array) { + PyMem_Free(array->array); + array->allocated_entries = 0; + } +} + int -_PyCompile_EnsureArrayLargeEnough(int idx, void **array, int *alloc, - int default_alloc, size_t item_size) +_Py_CArray_EnsureCapacity(_Py_c_array_t *c_array, int idx) { - void *arr = *array; + void *arr = c_array->array; + int alloc = c_array->allocated_entries; if (arr == NULL) { - int new_alloc = default_alloc; + int new_alloc = c_array->initial_num_entries; if (idx >= new_alloc) { - new_alloc = idx + default_alloc; + new_alloc = idx + c_array->initial_num_entries; } - arr = PyMem_Calloc(new_alloc, item_size); + arr = PyMem_Calloc(new_alloc, c_array->item_size); if (arr == NULL) { PyErr_NoMemory(); return ERROR; } - *alloc = new_alloc; + alloc = new_alloc; } - else if (idx >= *alloc) { - size_t oldsize = *alloc * item_size; - int new_alloc = *alloc << 1; + else if (idx >= alloc) { + size_t oldsize = alloc * c_array->item_size; + int new_alloc = alloc << 1; if (idx >= new_alloc) { - new_alloc = idx + default_alloc; + new_alloc = idx + c_array->initial_num_entries; } - size_t newsize = new_alloc * item_size; + size_t newsize = new_alloc * c_array->item_size; if (oldsize > (SIZE_MAX >> 1)) { PyErr_NoMemory(); @@ -146,12 +155,13 @@ _PyCompile_EnsureArrayLargeEnough(int idx, void **array, int *alloc, PyErr_NoMemory(); return ERROR; } - *alloc = new_alloc; + alloc = new_alloc; arr = tmp; memset((char *)arr + oldsize, 0, newsize - oldsize); } - *array = arr; + c_array->array = arr; + c_array->allocated_entries = alloc; return SUCCESS; } diff --git a/Python/flowgraph.c b/Python/flowgraph.c index fdafafd76617a8..c8470aa2cc7a53 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -1,5 +1,6 @@ #include "Python.h" #include "opcode.h" +#include "pycore_c_array.h" // _Py_CArray_EnsureCapacity #include "pycore_flowgraph.h" #include "pycore_compile.h" #include "pycore_intrinsics.h" @@ -141,13 +142,16 @@ static int basicblock_next_instr(basicblock *b) { assert(b != NULL); - RETURN_IF_ERROR( - _PyCompile_EnsureArrayLargeEnough( - b->b_iused + 1, - (void**)&b->b_instr, - &b->b_ialloc, - DEFAULT_BLOCK_SIZE, - sizeof(cfg_instr))); + _Py_c_array_t array = { + .array = (void*)b->b_instr, + .allocated_entries = b->b_ialloc, + .item_size = sizeof(cfg_instr), + .initial_num_entries = DEFAULT_BLOCK_SIZE, + }; + + RETURN_IF_ERROR(_Py_CArray_EnsureCapacity(&array, b->b_iused + 1)); + b->b_instr = array.array; + b->b_ialloc = array.allocated_entries; return b->b_iused++; } diff --git a/Python/instruction_sequence.c b/Python/instruction_sequence.c index ed40c06715f1f3..4ca85eec345d38 100644 --- a/Python/instruction_sequence.c +++ b/Python/instruction_sequence.c @@ -7,7 +7,8 @@ #include "Python.h" -#include "pycore_compile.h" // _PyCompile_EnsureArrayLargeEnough +#include "pycore_c_array.h" // _Py_CArray_EnsureCapacity +#include "pycore_compile.h" // _PyInstruction #include "pycore_opcode_utils.h" #include "pycore_opcode_metadata.h" // OPCODE_HAS_ARG, etc @@ -36,12 +37,18 @@ static int instr_sequence_next_inst(instr_sequence *seq) { assert(seq->s_instrs != NULL || seq->s_used == 0); - RETURN_IF_ERROR( - _PyCompile_EnsureArrayLargeEnough(seq->s_used + 1, - (void**)&seq->s_instrs, - &seq->s_allocated, - INITIAL_INSTR_SEQUENCE_SIZE, - sizeof(instruction))); + + _Py_c_array_t array = { + .array = (void*)seq->s_instrs, + .allocated_entries = seq->s_allocated, + .item_size = sizeof(instruction), + .initial_num_entries = INITIAL_INSTR_SEQUENCE_SIZE, + }; + + RETURN_IF_ERROR(_Py_CArray_EnsureCapacity(&array, seq->s_used + 1)); + seq->s_instrs = array.array; + seq->s_allocated = array.allocated_entries; + assert(seq->s_allocated >= 0); assert(seq->s_used < seq->s_allocated); return seq->s_used++; @@ -58,12 +65,16 @@ int _PyInstructionSequence_UseLabel(instr_sequence *seq, int lbl) { int old_size = seq->s_labelmap_size; - RETURN_IF_ERROR( - _PyCompile_EnsureArrayLargeEnough(lbl, - (void**)&seq->s_labelmap, - &seq->s_labelmap_size, - INITIAL_INSTR_SEQUENCE_LABELS_MAP_SIZE, - sizeof(int))); + _Py_c_array_t array = { + .array = (void*)seq->s_labelmap, + .allocated_entries = seq->s_labelmap_size, + .item_size = sizeof(int), + .initial_num_entries = INITIAL_INSTR_SEQUENCE_LABELS_MAP_SIZE, + }; + + RETURN_IF_ERROR(_Py_CArray_EnsureCapacity(&array, lbl)); + seq->s_labelmap = array.array; + seq->s_labelmap_size = array.allocated_entries; for(int i = old_size; i < seq->s_labelmap_size; i++) { seq->s_labelmap[i] = -111; /* something weird, for debugging */ _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com