]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-106608: make uop trace variable length (#107531)
authorIvin Lee <62840497+rdrf2838@users.noreply.github.com>
Sat, 5 Aug 2023 04:10:46 +0000 (12:10 +0800)
committerGitHub <noreply@github.com>
Sat, 5 Aug 2023 04:10:46 +0000 (21:10 -0700)
Executors are now more like tuples.

Include/cpython/optimizer.h
Include/internal/pycore_uops.h
Misc/NEWS.d/next/Core and Builtins/2023-08-01-09-41-36.gh-issue-106608.OFZogw.rst [new file with mode: 0644]
Python/optimizer.c

index 2260501bfd608ea6b98b40149514b30bd4cc0297..da34ec1882a539bedbf04af98b0c5bae46249944 100644 (file)
@@ -12,7 +12,7 @@ typedef struct {
 } _PyVMData;
 
 typedef struct _PyExecutorObject {
-    PyObject_HEAD
+    PyObject_VAR_HEAD
     /* WARNING: execute consumes a reference to self. This is necessary to allow executors to tail call into each other. */
     struct _PyInterpreterFrame *(*execute)(struct _PyExecutorObject *self, struct _PyInterpreterFrame *frame, PyObject **stack_pointer);
     _PyVMData vm_data; /* Used by the VM, but opaque to the optimizer */
index edb141cc79f752ba279d6537ff4bd123a41090dd..57a5970353b3605f0ed9436040f5c9926209e3f6 100644 (file)
@@ -18,7 +18,7 @@ typedef struct {
 
 typedef struct {
     _PyExecutorObject base;
-    _PyUOpInstruction trace[_Py_UOP_MAX_TRACE_LENGTH];  // TODO: variable length
+    _PyUOpInstruction trace[1];
 } _PyUOpExecutorObject;
 
 _PyInterpreterFrame *_PyUopExecute(
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-08-01-09-41-36.gh-issue-106608.OFZogw.rst b/Misc/NEWS.d/next/Core and Builtins/2023-08-01-09-41-36.gh-issue-106608.OFZogw.rst
new file mode 100644 (file)
index 0000000..20d43a7
--- /dev/null
@@ -0,0 +1 @@
+Make ``_PyUOpExecutorObject`` variable length.
index 238ab02d09faa79e81ca830f0f1285828c99496b..d2ed8dfcd2cff20a3f73672059b0dda30be2d2db 100644 (file)
@@ -320,13 +320,7 @@ uop_name(int index) {
 static Py_ssize_t
 uop_len(_PyUOpExecutorObject *self)
 {
-    int count = 0;
-    for (; count < _Py_UOP_MAX_TRACE_LENGTH; count++) {
-        if (self->trace[count].opcode == 0) {
-            break;
-        }
-    }
-    return count;
+    return Py_SIZE(self);
 }
 
 static PyObject *
@@ -368,8 +362,8 @@ PySequenceMethods uop_as_sequence = {
 static PyTypeObject UOpExecutor_Type = {
     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     .tp_name = "uop_executor",
-    .tp_basicsize = sizeof(_PyUOpExecutorObject),
-    .tp_itemsize = 0,
+    .tp_basicsize = sizeof(_PyUOpExecutorObject) - sizeof(_PyUOpInstruction),
+    .tp_itemsize = sizeof(_PyUOpInstruction),
     .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
     .tp_dealloc = (destructor)uop_dealloc,
     .tp_as_sequence = &uop_as_sequence,
@@ -699,15 +693,12 @@ uop_optimize(
         return trace_length;
     }
     OBJECT_STAT_INC(optimization_traces_created);
-    _PyUOpExecutorObject *executor = PyObject_New(_PyUOpExecutorObject, &UOpExecutor_Type);
+    _PyUOpExecutorObject *executor = PyObject_NewVar(_PyUOpExecutorObject, &UOpExecutor_Type, trace_length);
     if (executor == NULL) {
         return -1;
     }
     executor->base.execute = _PyUopExecute;
     memcpy(executor->trace, trace, trace_length * sizeof(_PyUOpInstruction));
-        if (trace_length < _Py_UOP_MAX_TRACE_LENGTH) {
-            executor->trace[trace_length].opcode = 0;  // Sentinel
-        }
     *exec_ptr = (_PyExecutorObject *)executor;
     return 1;
 }