Skip to content

Commit 4e6fac7

Browse files
authored
gh-106608: make uop trace variable length (#107531)
Executors are now more like tuples.
1 parent 05a824f commit 4e6fac7

File tree

4 files changed

+7
-15
lines changed

4 files changed

+7
-15
lines changed

Include/cpython/optimizer.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ typedef struct {
1212
} _PyVMData;
1313

1414
typedef struct _PyExecutorObject {
15-
PyObject_HEAD
15+
PyObject_VAR_HEAD
1616
/* WARNING: execute consumes a reference to self. This is necessary to allow executors to tail call into each other. */
1717
struct _PyInterpreterFrame *(*execute)(struct _PyExecutorObject *self, struct _PyInterpreterFrame *frame, PyObject **stack_pointer);
1818
_PyVMData vm_data; /* Used by the VM, but opaque to the optimizer */

Include/internal/pycore_uops.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ typedef struct {
1818

1919
typedef struct {
2020
_PyExecutorObject base;
21-
_PyUOpInstruction trace[_Py_UOP_MAX_TRACE_LENGTH]; // TODO: variable length
21+
_PyUOpInstruction trace[1];
2222
} _PyUOpExecutorObject;
2323

2424
_PyInterpreterFrame *_PyUopExecute(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Make ``_PyUOpExecutorObject`` variable length.

Python/optimizer.c

+4-13
Original file line numberDiff line numberDiff line change
@@ -320,13 +320,7 @@ uop_name(int index) {
320320
static Py_ssize_t
321321
uop_len(_PyUOpExecutorObject *self)
322322
{
323-
int count = 0;
324-
for (; count < _Py_UOP_MAX_TRACE_LENGTH; count++) {
325-
if (self->trace[count].opcode == 0) {
326-
break;
327-
}
328-
}
329-
return count;
323+
return Py_SIZE(self);
330324
}
331325

332326
static PyObject *
@@ -368,8 +362,8 @@ PySequenceMethods uop_as_sequence = {
368362
static PyTypeObject UOpExecutor_Type = {
369363
PyVarObject_HEAD_INIT(&PyType_Type, 0)
370364
.tp_name = "uop_executor",
371-
.tp_basicsize = sizeof(_PyUOpExecutorObject),
372-
.tp_itemsize = 0,
365+
.tp_basicsize = sizeof(_PyUOpExecutorObject) - sizeof(_PyUOpInstruction),
366+
.tp_itemsize = sizeof(_PyUOpInstruction),
373367
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
374368
.tp_dealloc = (destructor)uop_dealloc,
375369
.tp_as_sequence = &uop_as_sequence,
@@ -699,15 +693,12 @@ uop_optimize(
699693
return trace_length;
700694
}
701695
OBJECT_STAT_INC(optimization_traces_created);
702-
_PyUOpExecutorObject *executor = PyObject_New(_PyUOpExecutorObject, &UOpExecutor_Type);
696+
_PyUOpExecutorObject *executor = PyObject_NewVar(_PyUOpExecutorObject, &UOpExecutor_Type, trace_length);
703697
if (executor == NULL) {
704698
return -1;
705699
}
706700
executor->base.execute = _PyUopExecute;
707701
memcpy(executor->trace, trace, trace_length * sizeof(_PyUOpInstruction));
708-
if (trace_length < _Py_UOP_MAX_TRACE_LENGTH) {
709-
executor->trace[trace_length].opcode = 0; // Sentinel
710-
}
711702
*exec_ptr = (_PyExecutorObject *)executor;
712703
return 1;
713704
}

0 commit comments

Comments
 (0)