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

Reply via email to