Skip to content

Commit 83ccaf4

Browse files
committed
method on type
1 parent 49a8be8 commit 83ccaf4

10 files changed

Lines changed: 89 additions & 91 deletions

File tree

Include/cpython/object.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ typedef struct {
143143
* backwards-compatibility */
144144
typedef Py_ssize_t printfunc;
145145

146+
/* Specialize a binary by setting the descriptor pointer */
147+
struct _BinaryOpSpecializationDescr;
148+
typedef int(*binop_specialize_func)(PyObject *v, PyObject *w, int oparg,
149+
struct _BinaryOpSpecializationDescr **descr);
150+
146151
// If this structure is modified, Doc/includes/typestruct.h should be updated
147152
// as well.
148153
struct _typeobject {
@@ -233,6 +238,9 @@ struct _typeobject {
233238
/* bitset of which type-watchers care about this type */
234239
unsigned char tp_watched;
235240

241+
/* callback that may specialize BINARY_OP */
242+
binop_specialize_func tp_binop_specialize;
243+
236244
/* Number of tp_version_tag values used.
237245
* Set to _Py_ATTR_CACHE_UNUSED if the attribute cache is
238246
* disabled for this type (e.g. due to custom MRO entries).

Include/internal/pycore_code.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -485,14 +485,12 @@ adaptive_counter_backoff(_Py_BackoffCounter counter) {
485485
typedef int (*binaryopguardfunc)(PyObject *lhs, PyObject *rhs);
486486
typedef PyObject *(*binaryopactionfunc)(PyObject *lhs, PyObject *rhs);
487487

488-
typedef struct {
488+
typedef struct _BinaryOpSpecializationDescr {
489489
int oparg;
490490
binaryopguardfunc guard;
491491
binaryopactionfunc action;
492492
} _PyBinaryOpSpecializationDescr;
493493

494-
PyAPI_DATA(int) _Py_Specialize_AddBinaryOpExtention(_PyBinaryOpSpecializationDescr* descr);
495-
496494
/* Comparison bit masks. */
497495

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

Include/typeslots.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,5 @@
9393
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030E0000
9494
/* New in 3.14 */
9595
#define Py_tp_token 83
96+
#define Py_tp_binop_specialize 84
9697
#endif

Lib/test/test_sys.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1776,7 +1776,7 @@ def delx(self): del self.__x
17761776
check((1,2,3), vsize('') + self.P + 3*self.P)
17771777
# type
17781778
# static type: PyTypeObject
1779-
fmt = 'P2nPI13Pl4Pn9Pn12PIPc'
1779+
fmt = 'P2nPI13Pl4Pn9Pn12PI3Pc'
17801780
s = vsize(fmt)
17811781
check(int, s)
17821782
typeid = 'n' if support.Py_GIL_DISABLED else ''

Modules/arraymodule.c

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,10 @@ array_richcompare(PyObject *v, PyObject *w, int op)
850850
return res;
851851
}
852852

853+
static int
854+
array_binop_specialize(PyObject *v, PyObject *w, int oparg,
855+
_PyBinaryOpSpecializationDescr **descr);
856+
853857
static Py_ssize_t
854858
array_length(PyObject *op)
855859
{
@@ -2966,6 +2970,7 @@ static PyType_Slot array_slots[] = {
29662970
{Py_tp_new, array_new},
29672971
{Py_tp_traverse, array_tp_traverse},
29682972
{Py_tp_token, Py_TP_USE_SPEC},
2973+
{Py_tp_binop_specialize, array_binop_specialize},
29692974

29702975
/* as sequence */
29712976
{Py_sq_length, array_length},
@@ -2998,6 +3003,61 @@ static PyType_Spec array_spec = {
29983003
.slots = array_slots,
29993004
};
30003005

3006+
static inline int
3007+
array_subscr_guard(PyObject *lhs, PyObject *rhs)
3008+
{
3009+
PyObject *exc = PyErr_GetRaisedException();
3010+
int ret = PyType_GetBaseByToken(Py_TYPE(lhs), &array_spec, NULL);
3011+
if (ret < 0) {
3012+
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
3013+
PyErr_Clear();
3014+
ret = 0;
3015+
}
3016+
}
3017+
_PyErr_ChainExceptions1(exc);
3018+
return ret;
3019+
}
3020+
3021+
static PyObject *
3022+
array_subscr_action(PyObject *lhs, PyObject *rhs)
3023+
{
3024+
return array_subscr(lhs, rhs);
3025+
}
3026+
3027+
static int
3028+
array_binop_specialize(PyObject *v, PyObject *w, int oparg,
3029+
_PyBinaryOpSpecializationDescr **descr)
3030+
{
3031+
array_state *state = find_array_state_by_type(Py_TYPE(v));
3032+
3033+
if (!array_Check(v, state)) {
3034+
return 0;
3035+
}
3036+
3037+
*descr = NULL;
3038+
switch(oparg) {
3039+
case NB_SUBSCR:
3040+
if (array_subscr_guard(v, w)) {
3041+
*descr = (_PyBinaryOpSpecializationDescr*)PyMem_Malloc(
3042+
sizeof(_PyBinaryOpSpecializationDescr));
3043+
if (*descr == NULL) {
3044+
PyErr_NoMemory();
3045+
return -1;
3046+
}
3047+
**descr = (_PyBinaryOpSpecializationDescr) {
3048+
.oparg = oparg,
3049+
.guard = array_subscr_guard,
3050+
.action = array_subscr_action,
3051+
};
3052+
return 1;
3053+
}
3054+
break;
3055+
}
3056+
3057+
return 0;
3058+
}
3059+
3060+
30013061
/*********************** Array Iterator **************************/
30023062

30033063
/*[clinic input]
@@ -3204,41 +3264,6 @@ do { \
32043264
state->str_ ## string = tmp; \
32053265
} while (0)
32063266

3207-
static inline int
3208-
array_subscr_guard(PyObject *lhs, PyObject *rhs)
3209-
{
3210-
PyObject *exc = PyErr_GetRaisedException();
3211-
int ret = PyType_GetBaseByToken(Py_TYPE(lhs), &array_spec, NULL);
3212-
if (ret < 0) {
3213-
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
3214-
PyErr_Clear();
3215-
ret = 0;
3216-
}
3217-
}
3218-
_PyErr_ChainExceptions1(exc);
3219-
return ret;
3220-
}
3221-
3222-
static PyObject *
3223-
array_subscr_action(PyObject *lhs, PyObject *rhs)
3224-
{
3225-
return array_subscr(lhs, rhs);
3226-
}
3227-
3228-
static int
3229-
array_register_specializations(void)
3230-
{
3231-
_PyBinaryOpSpecializationDescr descr = {
3232-
.oparg = NB_SUBSCR,
3233-
.guard = array_subscr_guard,
3234-
.action = array_subscr_action,
3235-
};
3236-
if (_Py_Specialize_AddBinaryOpExtention(&descr) < 0) {
3237-
return -1;
3238-
}
3239-
return 0;
3240-
}
3241-
32423267
static int
32433268
array_modexec(PyObject *m)
32443269
{
@@ -3278,10 +3303,6 @@ array_modexec(PyObject *m)
32783303
}
32793304
Py_DECREF(res);
32803305

3281-
if (array_register_specializations() < 0) {
3282-
return -1;
3283-
}
3284-
32853306
if (PyModule_AddType(m, state->ArrayType) < 0) {
32863307
return -1;
32873308
}

Objects/typeslots.inc

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/bytecodes.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,8 @@ dummy_func(
801801
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
802802
_PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr;
803803
assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5);
804-
assert(d && d->guard);
804+
assert(d);
805+
assert(d->guard);
805806
int res = d->guard(left_o, right_o);
806807
ERROR_IF(res < 0, error);
807808
DEOPT_IF(res == 0);

Python/executor_cases.c.h

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/specialize.c

Lines changed: 11 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2556,63 +2556,29 @@ static _PyBinaryOpSpecializationDescr binaryop_extend_builtins[] = {
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-
25772559
static int
2578-
binary_op_extended_specialization_from_list(
2579-
_PyBinaryOpSpecializationDescr *descrs, size_t size,
2580-
PyObject *lhs, PyObject *rhs, int oparg,
2581-
_PyBinaryOpSpecializationDescr **descr)
2560+
binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
2561+
_PyBinaryOpSpecializationDescr **descr)
25822562
{
2563+
typedef _PyBinaryOpSpecializationDescr descr_type;
2564+
size_t size = sizeof(binaryop_extend_builtins)/sizeof(descr_type);
25832565
for (size_t i = 0; i < size; i++) {
2584-
_PyBinaryOpSpecializationDescr *d = &descrs[i];
2566+
_PyBinaryOpSpecializationDescr *d = &binaryop_extend_builtins[i];
25852567
assert(d != NULL);
25862568
assert(d->guard != NULL);
25872569
if (d->oparg == oparg && d->guard(lhs, rhs)) {
25882570
*descr = d;
25892571
return 1;
25902572
}
25912573
}
2592-
return 0;
2593-
}
25942574

2595-
static int
2596-
binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
2597-
_PyBinaryOpSpecializationDescr **descr)
2598-
{
2599-
typedef _PyBinaryOpSpecializationDescr descr_type;
2600-
if (binary_op_extended_specialization_from_list(
2601-
binaryop_extend_builtins,
2602-
sizeof(binaryop_extend_builtins)/sizeof(descr_type),
2603-
lhs, rhs, oparg, descr))
2604-
{
2605-
return 1;
2606-
}
2575+
if (Py_TYPE(lhs)->tp_binop_specialize != NULL) {
2576+
int ret = Py_TYPE(lhs)->tp_binop_specialize(lhs, rhs, oparg, descr);
2577+
if (ret < 0) {
2578+
return -1;
2579+
}
26072580

2608-
PyThreadState *tstate = PyThreadState_Get();
2609-
_Py_c_array_t *extensions = &tstate->interp->binop_specializer_extentions;
2610-
if (binary_op_extended_specialization_from_list(
2611-
(descr_type*)extensions->array,
2612-
tstate->interp->num_binop_specializer_extentions,
2613-
lhs, rhs, oparg, descr))
2614-
{
2615-
return 1;
2581+
return ret;
26162582
}
26172583
return 0;
26182584
}

0 commit comments

Comments
 (0)