https://github.com/python/cpython/commit/4242c2b8d073c740164b82725270fd691bda03c8
commit: 4242c2b8d073c740164b82725270fd691bda03c8
branch: main
author: Irit Katriel <[email protected]>
committer: iritkatriel <[email protected]>
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 -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]