diff --git a/Include/internal/pycore_uops.h b/Include/internal/pycore_uops.h index edb141cc79f752..20da3bbf6a6405 100644 --- a/Include/internal/pycore_uops.h +++ b/Include/internal/pycore_uops.h @@ -10,6 +10,8 @@ extern "C" { #define _Py_UOP_MAX_TRACE_LENGTH 32 +PyAPI_DATA(PyTypeObject) UOpExecutor_Type; + typedef struct { uint32_t opcode; uint32_t oparg; @@ -17,8 +19,9 @@ typedef struct { } _PyUOpInstruction; typedef struct { + PyObject_VAR_HEAD _PyExecutorObject base; - _PyUOpInstruction trace[_Py_UOP_MAX_TRACE_LENGTH]; // TODO: variable length + _PyUOpInstruction trace[1]; } _PyUOpExecutorObject; _PyInterpreterFrame *_PyUopExecute( @@ -26,6 +29,17 @@ _PyInterpreterFrame *_PyUopExecute( _PyInterpreterFrame *frame, PyObject **stack_pointer); +/* Cast argument to _PyUOpExecutorObject* type. */ +#define _PyUOpExecutor_CAST(op) \ + _Py_CAST(_PyUOpExecutorObject*, (op)) + +static inline Py_ssize_t PyUOpExecutor_GET_SIZE(PyObject *op) { + _PyUOpExecutorObject *executor = _PyUOpExecutor_CAST(op); + return Py_SIZE(executor); +} +#define PyUOpExecutor_GET_SIZE(op) PyUOpExecutor_GET_SIZE(_PyObject_CAST(op)) +PyAPI_FUNC(PyObject *) PyUOpExecutor_New(_PyUOpInstruction trace[], Py_ssize_t size); + #ifdef __cplusplus } #endif diff --git a/Python/executor.c b/Python/executor.c index 57525df202d861..38320e49bc7cf4 100644 --- a/Python/executor.c +++ b/Python/executor.c @@ -30,6 +30,30 @@ #undef ENABLE_SPECIALIZATION #define ENABLE_SPECIALIZATION 0 +static _PyUOpExecutorObject * +PyUOpExecutor_alloc(Py_ssize_t size) +{ + _PyUOpExecutorObject *op = PyObject_GC_NewVar(_PyUOpExecutorObject, &UOpExecutor_Type, size); + if (op == NULL) { + return NULL; + } + return op; +} + +PyObject * +PyUOpExecutor_New(_PyUOpInstruction trace[], Py_ssize_t size) +{ + _PyUOpExecutorObject *op; + op = PyUOpExecutor_alloc(size); + if (op == NULL) { + return NULL; + } + for (Py_ssize_t i = 0; i < size; i++) { + op->trace[i] = trace[i]; + } + _PyObject_GC_TRACK(op); + return (PyObject *) op; +} _PyInterpreterFrame * _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer) diff --git a/Python/optimizer.c b/Python/optimizer.c index 238ab02d09faa7..776debc0c172a0 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -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 PyUOpExecutor_GET_SIZE(self); } static PyObject * @@ -365,7 +359,7 @@ PySequenceMethods uop_as_sequence = { .sq_item = (ssizeargfunc)uop_item, }; -static PyTypeObject UOpExecutor_Type = { +PyTypeObject UOpExecutor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) .tp_name = "uop_executor", .tp_basicsize = sizeof(_PyUOpExecutorObject), @@ -699,15 +693,8 @@ uop_optimize( return trace_length; } OBJECT_STAT_INC(optimization_traces_created); - _PyUOpExecutorObject *executor = PyObject_New(_PyUOpExecutorObject, &UOpExecutor_Type); - if (executor == NULL) { - return -1; - } + _PyUOpExecutorObject *executor = (_PyUOpExecutorObject *) PyUOpExecutor_New(trace, trace_length); 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; }