]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-130080: move _Py_EnsureArrayLargeEnough to a separate header so it can be used...
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Thu, 13 Mar 2025 16:02:58 +0000 (16:02 +0000)
committerGitHub <noreply@github.com>
Thu, 13 Mar 2025 16:02:58 +0000 (16:02 +0000)
Include/internal/pycore_c_array.h [new file with mode: 0644]
Include/internal/pycore_compile.h
Python/codegen.c
Python/flowgraph.c
Python/instruction_sequence.c

diff --git a/Include/internal/pycore_c_array.h b/Include/internal/pycore_c_array.h
new file mode 100644 (file)
index 0000000..7a10fc8
--- /dev/null
@@ -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 */
index b61ac8fccdca14d36f7d6d531d6215f014346ea7..5b08bb6f8a71352a83f4a670e25e74e82797f356 100644 (file)
@@ -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);
index 6ef3c63b33530ebcd6b9b44d8da6db7eac5af52a..a3eca2a6580c8e561d03d0b91d7adf6e90c95128 100644 (file)
@@ -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;
 }
 
index fdafafd76617a86c4d363c62a75be6df50c387c7..c8470aa2cc7a53f9cd3df6c3554c361a4f22ed19 100644 (file)
@@ -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++;
 }
 
index ed40c06715f1f325121b3f0a14f9365bb5c7bd76..4ca85eec345d38a5b710585fda615dac6bde95e1 100644 (file)
@@ -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 */