Skip to content

Commit d42d2a6

Browse files
committed
method on type
1 parent 70ebe71 commit d42d2a6

File tree

13 files changed

+90
-99
lines changed

13 files changed

+90
-99
lines changed

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 _PyBinopSpecializationDescr;
148+
typedef int(*binop_specialize_func)(PyObject *v, PyObject *w, int oparg,
149+
struct _PyBinopSpecializationDescr **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_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; /* the capacity of the array */
17+
int allocated_entries; /* pointer to 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: 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 _PyBinopSpecializationDescr {
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/internal/pycore_interp_structs.h

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

1010
#include "pycore_ast_state.h" // struct ast_state
11-
#include "pycore_c_array.h" // _Py_c_array_t
1211
#include "pycore_llist.h" // struct llist_node
1312
#include "pycore_opcode_utils.h" // NUM_COMMON_CONSTANTS
1413
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
@@ -952,10 +951,6 @@ struct _is {
952951
# endif
953952
#endif
954953

955-
/* Specialization extensions */
956-
Py_ssize_t num_binop_specializer_extentions;
957-
_Py_c_array_t binop_specializer_extentions;
958-
959954
/* the initial PyInterpreterState.threads.head */
960955
_PyThreadStateImpl _initial_thread;
961956
// _initial_thread should be the last field of PyInterpreterState.

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.

0 commit comments

Comments
 (0)