Skip to content

Commit 79e45a1

Browse files
committed
plumbing for registering specialization
1 parent 0a1fedb commit 79e45a1

File tree

7 files changed

+93
-7
lines changed

7 files changed

+93
-7
lines changed

Include/internal/pycore_c_array.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ extern "C" {
1414

1515
typedef struct {
1616
void *array; /* pointer to the array */
17-
int allocated_entries; /* pointer to the capacity of the array */
17+
int allocated_entries; /* the capacity of the array */
1818
size_t item_size; /* size of each element */
1919
int initial_num_entries; /* initial allocation size */
2020
} _Py_c_array_t;

Include/internal/pycore_code.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,8 @@ typedef struct {
491491
binaryopactionfunc action;
492492
} _PyBinaryOpSpecializationDescr;
493493

494+
PyAPI_DATA(int) _Py_Specialize_AddBinaryOpExtention(_PyBinaryOpSpecializationDescr* descr);
495+
494496
/* Comparison bit masks. */
495497

496498
/* Note this evaluates its arguments twice each */

Include/internal/pycore_interp_structs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern "C" {
88
#endif
99

1010
#include "pycore_ast_state.h" // struct ast_state
11+
#include "pycore_c_array.h" // _Py_c_array_t
1112
#include "pycore_llist.h" // struct llist_node
1213
#include "pycore_opcode_utils.h" // NUM_COMMON_CONSTANTS
1314
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
@@ -951,6 +952,10 @@ struct _is {
951952
# endif
952953
#endif
953954

955+
/* Specialization extensions */
956+
Py_ssize_t num_binop_specializer_extentions;
957+
_Py_c_array_t binop_specializer_extentions;
958+
954959
/* the initial PyInterpreterState.threads.head */
955960
_PyThreadStateImpl _initial_thread;
956961
// _initial_thread should be the last field of PyInterpreterState.

Include/object.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ typedef int (*objobjproc)(PyObject *, PyObject *);
348348
typedef int (*visitproc)(PyObject *, void *);
349349
typedef int (*traverseproc)(PyObject *, visitproc, void *);
350350

351+
struct _PyBinaryOpSpecializationDescr;
352+
typedef int (*binopspecfunc)(PyObject *lhs, PyObject *rhs, int oparg, struct _PyBinaryOpSpecializationDescr* descr);
351353

352354
typedef void (*freefunc)(void *);
353355
typedef void (*destructor)(PyObject *);

Modules/arraymodule.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include "pycore_modsupport.h" // _PyArg_NoKeywords()
1515
#include "pycore_moduleobject.h" // _PyModule_GetState()
1616

17+
#include "opcode.h" // binary op opargs (NB_*)
18+
1719
#include <stddef.h> // offsetof()
1820
#include <stdbool.h>
1921

@@ -3201,6 +3203,33 @@ do { \
32013203
state->str_ ## string = tmp; \
32023204
} while (0)
32033205

3206+
static inline int
3207+
array_guard(PyObject *lhs, PyObject *rhs)
3208+
{
3209+
fprintf(stderr, "array_guard\n");
3210+
return 0;
3211+
}
3212+
3213+
static PyObject *
3214+
array_action(PyObject *lhs, PyObject *rhs)
3215+
{
3216+
return NULL;
3217+
}
3218+
3219+
static int
3220+
array_register_specializations(void)
3221+
{
3222+
_PyBinaryOpSpecializationDescr descr = {
3223+
.oparg = NB_MULTIPLY,
3224+
.guard = array_guard,
3225+
.action = array_action,
3226+
};
3227+
if (_Py_Specialize_AddBinaryOpExtention(&descr) < 0) {
3228+
return -1;
3229+
}
3230+
return 0;
3231+
}
3232+
32043233
static int
32053234
array_modexec(PyObject *m)
32063235
{
@@ -3240,6 +3269,10 @@ array_modexec(PyObject *m)
32403269
}
32413270
Py_DECREF(res);
32423271

3272+
if (array_register_specializations() < 0) {
3273+
return -1;
3274+
}
3275+
32433276
if (PyModule_AddType(m, state->ArrayType) < 0) {
32443277
return -1;
32453278
}
@@ -3252,7 +3285,6 @@ array_modexec(PyObject *m)
32523285
if (PyModule_Add(m, "typecodes", typecodes) < 0) {
32533286
return -1;
32543287
}
3255-
32563288
return 0;
32573289
}
32583290

Python/pystate.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,8 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
873873
interp->ceval.instrumentation_version = 0;
874874
tstate->eval_breaker = 0;
875875

876+
_Py_CArray_Fini(&interp->binop_specializer_extentions);
877+
876878
for (int i = 0; i < _PY_MONITORING_UNGROUPED_EVENTS; i++) {
877879
interp->monitors.tools[i] = 0;
878880
}

Python/specialize.c

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2556,13 +2556,32 @@ static _PyBinaryOpSpecializationDescr binaryop_extend_descrs[] = {
25562556
{NB_MULTIPLY, compactlong_float_guard, compactlong_float_multiply},
25572557
};
25582558

2559+
int
2560+
_Py_Specialize_AddBinaryOpExtention(_PyBinaryOpSpecializationDescr* descr)
2561+
{
2562+
PyThreadState *tstate = PyThreadState_Get();
2563+
_Py_c_array_t *extensions = &tstate->interp->binop_specializer_extentions;
2564+
Py_ssize_t idx = tstate->interp->num_binop_specializer_extentions;
2565+
if (idx == 0) {
2566+
_Py_CArray_Init(extensions, sizeof(_PyBinaryOpSpecializationDescr), 10);
2567+
}
2568+
if (_Py_CArray_EnsureCapacity(extensions, idx) < 0) {
2569+
return -1;
2570+
}
2571+
_PyBinaryOpSpecializationDescr* descrs = (_PyBinaryOpSpecializationDescr*)extensions->array;
2572+
descrs[idx] = *descr;
2573+
tstate->interp->num_binop_specializer_extentions++;
2574+
return 0;
2575+
}
2576+
25592577
static int
2560-
binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
2561-
_PyBinaryOpSpecializationDescr **descr)
2578+
binary_op_extended_specialization_from_list(
2579+
_PyBinaryOpSpecializationDescr *descrs, size_t size,
2580+
PyObject *lhs, PyObject *rhs, int oparg,
2581+
_PyBinaryOpSpecializationDescr **descr)
25622582
{
2563-
size_t n = sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr);
2564-
for (size_t i = 0; i < n; i++) {
2565-
_PyBinaryOpSpecializationDescr *d = &binaryop_extend_descrs[i];
2583+
for (size_t i = 0; i < size; i++) {
2584+
_PyBinaryOpSpecializationDescr *d = &descrs[i];
25662585
if (d->oparg == oparg && d->guard(lhs, rhs)) {
25672586
*descr = d;
25682587
return 1;
@@ -2571,6 +2590,30 @@ binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
25712590
return 0;
25722591
}
25732592

2593+
static int
2594+
binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
2595+
_PyBinaryOpSpecializationDescr **descr)
2596+
{
2597+
if (binary_op_extended_specialization_from_list(
2598+
binaryop_extend_descrs,
2599+
sizeof(binaryop_extend_descrs)/sizeof(_PyBinaryOpSpecializationDescr),
2600+
lhs, rhs, oparg, descr))
2601+
{
2602+
return 1;
2603+
}
2604+
2605+
PyThreadState *tstate = PyThreadState_Get();
2606+
_Py_c_array_t *extensions = &tstate->interp->binop_specializer_extentions;
2607+
if (binary_op_extended_specialization_from_list(
2608+
(_PyBinaryOpSpecializationDescr *)extensions->array,
2609+
tstate->interp->num_binop_specializer_extentions,
2610+
lhs, rhs, oparg, descr))
2611+
{
2612+
return 1;
2613+
}
2614+
return 0;
2615+
}
2616+
25742617
Py_NO_INLINE void
25752618
_Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *instr,
25762619
int oparg, _PyStackRef *locals)

0 commit comments

Comments
 (0)