gh-115999: Enable BINARY_SUBSCR_GETITEM for free-threaded build (gh-127737)
This commit is contained in:
parent
f802c8bf87
commit
48c70b8f7d
4
Include/internal/pycore_opcode_metadata.h
generated
4
Include/internal/pycore_opcode_metadata.h
generated
@ -994,7 +994,7 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case BINARY_SUBSCR: {
|
case BINARY_SUBSCR: {
|
||||||
*effect = 0;
|
*effect = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case BINARY_SUBSCR_DICT: {
|
case BINARY_SUBSCR_DICT: {
|
||||||
@ -1002,7 +1002,7 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case BINARY_SUBSCR_GETITEM: {
|
case BINARY_SUBSCR_GETITEM: {
|
||||||
*effect = 0;
|
*effect = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case BINARY_SUBSCR_LIST_INT: {
|
case BINARY_SUBSCR_LIST_INT: {
|
||||||
|
@ -278,6 +278,7 @@ typedef int (*_py_validate_type)(PyTypeObject *);
|
|||||||
// and if the validation is passed, it will set the ``tp_version`` as valid
|
// and if the validation is passed, it will set the ``tp_version`` as valid
|
||||||
// tp_version_tag from the ``ty``.
|
// tp_version_tag from the ``ty``.
|
||||||
extern int _PyType_Validate(PyTypeObject *ty, _py_validate_type validate, unsigned int *tp_version);
|
extern int _PyType_Validate(PyTypeObject *ty, _py_validate_type validate, unsigned int *tp_version);
|
||||||
|
extern int _PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t tp_version);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
2
Include/internal/pycore_uop_metadata.h
generated
2
Include/internal/pycore_uop_metadata.h
generated
@ -722,7 +722,7 @@ int _PyUop_num_popped(int opcode, int oparg)
|
|||||||
case _BINARY_SUBSCR_CHECK_FUNC:
|
case _BINARY_SUBSCR_CHECK_FUNC:
|
||||||
return 0;
|
return 0;
|
||||||
case _BINARY_SUBSCR_INIT_CALL:
|
case _BINARY_SUBSCR_INIT_CALL:
|
||||||
return 2;
|
return 3;
|
||||||
case _LIST_APPEND:
|
case _LIST_APPEND:
|
||||||
return 1;
|
return 1;
|
||||||
case _SET_ADD:
|
case _SET_ADD:
|
||||||
|
@ -1069,7 +1069,7 @@ class TestRacesDoNotCrash(TestBase):
|
|||||||
opname = "STORE_SUBSCR_LIST_INT"
|
opname = "STORE_SUBSCR_LIST_INT"
|
||||||
self.assert_races_do_not_crash(opname, get_items, read, write)
|
self.assert_races_do_not_crash(opname, get_items, read, write)
|
||||||
|
|
||||||
@requires_specialization
|
@requires_specialization_ft
|
||||||
def test_unpack_sequence_list(self):
|
def test_unpack_sequence_list(self):
|
||||||
def get_items():
|
def get_items():
|
||||||
items = []
|
items = []
|
||||||
@ -1245,6 +1245,14 @@ class TestInstanceDict(unittest.TestCase):
|
|||||||
f(test_obj, 1)
|
f(test_obj, 1)
|
||||||
self.assertEqual(test_obj.b, 0)
|
self.assertEqual(test_obj.b, 0)
|
||||||
|
|
||||||
|
# gh-127274: BINARY_SUBSCR_GETITEM will only cache __getitem__ methods that
|
||||||
|
# are deferred. We only defer functions defined at the top-level.
|
||||||
|
class CGetItem:
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
def __getitem__(self, item):
|
||||||
|
return self.val
|
||||||
|
|
||||||
|
|
||||||
class TestSpecializer(TestBase):
|
class TestSpecializer(TestBase):
|
||||||
|
|
||||||
@ -1520,6 +1528,15 @@ class TestSpecializer(TestBase):
|
|||||||
self.assert_specialized(binary_subscr_str_int, "BINARY_SUBSCR_STR_INT")
|
self.assert_specialized(binary_subscr_str_int, "BINARY_SUBSCR_STR_INT")
|
||||||
self.assert_no_opcode(binary_subscr_str_int, "BINARY_SUBSCR")
|
self.assert_no_opcode(binary_subscr_str_int, "BINARY_SUBSCR")
|
||||||
|
|
||||||
|
def binary_subscr_getitems():
|
||||||
|
items = [CGetItem(i) for i in range(100)]
|
||||||
|
for i in range(100):
|
||||||
|
self.assertEqual(items[i][i], i)
|
||||||
|
|
||||||
|
binary_subscr_getitems()
|
||||||
|
self.assert_specialized(binary_subscr_getitems, "BINARY_SUBSCR_GETITEM")
|
||||||
|
self.assert_no_opcode(binary_subscr_getitems, "BINARY_SUBSCR")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -5679,6 +5679,31 @@ _PyType_CacheInitForSpecialization(PyHeapTypeObject *type, PyObject *init,
|
|||||||
return can_cache;
|
return can_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t tp_version)
|
||||||
|
{
|
||||||
|
if (!descriptor || !tp_version) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int can_cache;
|
||||||
|
BEGIN_TYPE_LOCK();
|
||||||
|
can_cache = ((PyTypeObject*)ht)->tp_version_tag == tp_version;
|
||||||
|
// This pointer is invalidated by PyType_Modified (see the comment on
|
||||||
|
// struct _specialization_cache):
|
||||||
|
PyFunctionObject *func = (PyFunctionObject *)descriptor;
|
||||||
|
uint32_t version = _PyFunction_GetVersionForCurrentState(func);
|
||||||
|
can_cache = can_cache && _PyFunction_IsVersionValid(version);
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
can_cache = can_cache && _PyObject_HasDeferredRefcount(descriptor);
|
||||||
|
#endif
|
||||||
|
if (can_cache) {
|
||||||
|
FT_ATOMIC_STORE_PTR_RELEASE(ht->_spec_cache.getitem, descriptor);
|
||||||
|
FT_ATOMIC_STORE_UINT32_RELAXED(ht->_spec_cache.getitem_version, version);
|
||||||
|
}
|
||||||
|
END_TYPE_LOCK();
|
||||||
|
return can_cache;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_flags(PyTypeObject *self, unsigned long mask, unsigned long flags)
|
set_flags(PyTypeObject *self, unsigned long mask, unsigned long flags)
|
||||||
{
|
{
|
||||||
|
2
Programs/test_frozenmain.h
generated
2
Programs/test_frozenmain.h
generated
@ -1,6 +1,6 @@
|
|||||||
// Auto-generated by Programs/freeze_test_frozenmain.py
|
// Auto-generated by Programs/freeze_test_frozenmain.py
|
||||||
unsigned char M_test_frozenmain[] = {
|
unsigned char M_test_frozenmain[] = {
|
||||||
227,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,
|
227,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,
|
||||||
0,0,0,0,0,243,168,0,0,0,149,0,89,0,79,0,
|
0,0,0,0,0,243,168,0,0,0,149,0,89,0,79,0,
|
||||||
70,0,111,0,89,0,79,0,70,1,111,1,88,2,31,0,
|
70,0,111,0,89,0,79,0,70,1,111,1,88,2,31,0,
|
||||||
79,1,49,1,0,0,0,0,0,0,29,0,88,2,31,0,
|
79,1,49,1,0,0,0,0,0,0,29,0,88,2,31,0,
|
||||||
|
@ -865,26 +865,24 @@ dummy_func(
|
|||||||
res = PyStackRef_FromPyObjectSteal(res_o);
|
res = PyStackRef_FromPyObjectSteal(res_o);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_BINARY_SUBSCR_CHECK_FUNC, (container, unused -- container, unused)) {
|
op(_BINARY_SUBSCR_CHECK_FUNC, (container, unused -- container, unused, getitem)) {
|
||||||
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
||||||
DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
|
DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE));
|
||||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
||||||
PyObject *getitem = ht->_spec_cache.getitem;
|
PyObject *getitem_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(ht->_spec_cache.getitem);
|
||||||
DEOPT_IF(getitem == NULL);
|
DEOPT_IF(getitem_o == NULL);
|
||||||
assert(PyFunction_Check(getitem));
|
assert(PyFunction_Check(getitem_o));
|
||||||
uint32_t cached_version = ht->_spec_cache.getitem_version;
|
uint32_t cached_version = FT_ATOMIC_LOAD_UINT32_RELAXED(ht->_spec_cache.getitem_version);
|
||||||
DEOPT_IF(((PyFunctionObject *)getitem)->func_version != cached_version);
|
DEOPT_IF(((PyFunctionObject *)getitem_o)->func_version != cached_version);
|
||||||
PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(getitem);
|
PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(getitem_o);
|
||||||
assert(code->co_argcount == 2);
|
assert(code->co_argcount == 2);
|
||||||
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
|
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
|
||||||
|
getitem = PyStackRef_FromPyObjectNew(getitem_o);
|
||||||
STAT_INC(BINARY_SUBSCR, hit);
|
STAT_INC(BINARY_SUBSCR, hit);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_BINARY_SUBSCR_INIT_CALL, (container, sub -- new_frame: _PyInterpreterFrame* )) {
|
op(_BINARY_SUBSCR_INIT_CALL, (container, sub, getitem -- new_frame: _PyInterpreterFrame* )) {
|
||||||
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame);
|
||||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
|
||||||
PyObject *getitem = ht->_spec_cache.getitem;
|
|
||||||
new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(getitem), 2, frame);
|
|
||||||
new_frame->localsplus[0] = container;
|
new_frame->localsplus[0] = container;
|
||||||
new_frame->localsplus[1] = sub;
|
new_frame->localsplus[1] = sub;
|
||||||
INPUTS_DEAD();
|
INPUTS_DEAD();
|
||||||
|
32
Python/executor_cases.c.h
generated
32
Python/executor_cases.c.h
generated
@ -1125,6 +1125,7 @@
|
|||||||
|
|
||||||
case _BINARY_SUBSCR_CHECK_FUNC: {
|
case _BINARY_SUBSCR_CHECK_FUNC: {
|
||||||
_PyStackRef container;
|
_PyStackRef container;
|
||||||
|
_PyStackRef getitem;
|
||||||
container = stack_pointer[-2];
|
container = stack_pointer[-2];
|
||||||
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
||||||
if (!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
|
if (!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE)) {
|
||||||
@ -1132,42 +1133,45 @@
|
|||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
||||||
PyObject *getitem = ht->_spec_cache.getitem;
|
PyObject *getitem_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(ht->_spec_cache.getitem);
|
||||||
if (getitem == NULL) {
|
if (getitem_o == NULL) {
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
assert(PyFunction_Check(getitem));
|
assert(PyFunction_Check(getitem_o));
|
||||||
uint32_t cached_version = ht->_spec_cache.getitem_version;
|
uint32_t cached_version = FT_ATOMIC_LOAD_UINT32_RELAXED(ht->_spec_cache.getitem_version);
|
||||||
if (((PyFunctionObject *)getitem)->func_version != cached_version) {
|
if (((PyFunctionObject *)getitem_o)->func_version != cached_version) {
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(getitem);
|
PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(getitem_o);
|
||||||
assert(code->co_argcount == 2);
|
assert(code->co_argcount == 2);
|
||||||
if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) {
|
if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) {
|
||||||
UOP_STAT_INC(uopcode, miss);
|
UOP_STAT_INC(uopcode, miss);
|
||||||
JUMP_TO_JUMP_TARGET();
|
JUMP_TO_JUMP_TARGET();
|
||||||
}
|
}
|
||||||
|
getitem = PyStackRef_FromPyObjectNew(getitem_o);
|
||||||
STAT_INC(BINARY_SUBSCR, hit);
|
STAT_INC(BINARY_SUBSCR, hit);
|
||||||
|
stack_pointer[0] = getitem;
|
||||||
|
stack_pointer += 1;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _BINARY_SUBSCR_INIT_CALL: {
|
case _BINARY_SUBSCR_INIT_CALL: {
|
||||||
|
_PyStackRef getitem;
|
||||||
_PyStackRef sub;
|
_PyStackRef sub;
|
||||||
_PyStackRef container;
|
_PyStackRef container;
|
||||||
_PyInterpreterFrame *new_frame;
|
_PyInterpreterFrame *new_frame;
|
||||||
sub = stack_pointer[-1];
|
getitem = stack_pointer[-1];
|
||||||
container = stack_pointer[-2];
|
sub = stack_pointer[-2];
|
||||||
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
container = stack_pointer[-3];
|
||||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame);
|
||||||
PyObject *getitem = ht->_spec_cache.getitem;
|
|
||||||
new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(getitem), 2, frame);
|
|
||||||
new_frame->localsplus[0] = container;
|
new_frame->localsplus[0] = container;
|
||||||
new_frame->localsplus[1] = sub;
|
new_frame->localsplus[1] = sub;
|
||||||
frame->return_offset = 2 ;
|
frame->return_offset = 2 ;
|
||||||
stack_pointer[-2].bits = (uintptr_t)new_frame;
|
stack_pointer[-3].bits = (uintptr_t)new_frame;
|
||||||
stack_pointer += -1;
|
stack_pointer += -2;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
19
Python/generated_cases.c.h
generated
19
Python/generated_cases.c.h
generated
@ -505,6 +505,7 @@
|
|||||||
INSTRUCTION_STATS(BINARY_SUBSCR_GETITEM);
|
INSTRUCTION_STATS(BINARY_SUBSCR_GETITEM);
|
||||||
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
|
||||||
_PyStackRef container;
|
_PyStackRef container;
|
||||||
|
_PyStackRef getitem;
|
||||||
_PyStackRef sub;
|
_PyStackRef sub;
|
||||||
_PyInterpreterFrame *new_frame;
|
_PyInterpreterFrame *new_frame;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
@ -518,23 +519,21 @@
|
|||||||
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
||||||
DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE), BINARY_SUBSCR);
|
DEOPT_IF(!PyType_HasFeature(tp, Py_TPFLAGS_HEAPTYPE), BINARY_SUBSCR);
|
||||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
||||||
PyObject *getitem = ht->_spec_cache.getitem;
|
PyObject *getitem_o = FT_ATOMIC_LOAD_PTR_ACQUIRE(ht->_spec_cache.getitem);
|
||||||
DEOPT_IF(getitem == NULL, BINARY_SUBSCR);
|
DEOPT_IF(getitem_o == NULL, BINARY_SUBSCR);
|
||||||
assert(PyFunction_Check(getitem));
|
assert(PyFunction_Check(getitem_o));
|
||||||
uint32_t cached_version = ht->_spec_cache.getitem_version;
|
uint32_t cached_version = FT_ATOMIC_LOAD_UINT32_RELAXED(ht->_spec_cache.getitem_version);
|
||||||
DEOPT_IF(((PyFunctionObject *)getitem)->func_version != cached_version, BINARY_SUBSCR);
|
DEOPT_IF(((PyFunctionObject *)getitem_o)->func_version != cached_version, BINARY_SUBSCR);
|
||||||
PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(getitem);
|
PyCodeObject *code = (PyCodeObject *)PyFunction_GET_CODE(getitem_o);
|
||||||
assert(code->co_argcount == 2);
|
assert(code->co_argcount == 2);
|
||||||
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), BINARY_SUBSCR);
|
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), BINARY_SUBSCR);
|
||||||
|
getitem = PyStackRef_FromPyObjectNew(getitem_o);
|
||||||
STAT_INC(BINARY_SUBSCR, hit);
|
STAT_INC(BINARY_SUBSCR, hit);
|
||||||
}
|
}
|
||||||
// _BINARY_SUBSCR_INIT_CALL
|
// _BINARY_SUBSCR_INIT_CALL
|
||||||
{
|
{
|
||||||
sub = stack_pointer[-1];
|
sub = stack_pointer[-1];
|
||||||
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
|
new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame);
|
||||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
|
|
||||||
PyObject *getitem = ht->_spec_cache.getitem;
|
|
||||||
new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(getitem), 2, frame);
|
|
||||||
new_frame->localsplus[0] = container;
|
new_frame->localsplus[0] = container;
|
||||||
new_frame->localsplus[1] = sub;
|
new_frame->localsplus[1] = sub;
|
||||||
frame->return_offset = 2 ;
|
frame->return_offset = 2 ;
|
||||||
|
@ -349,9 +349,10 @@ dummy_func(void) {
|
|||||||
GETLOCAL(this_instr->operand0) = res;
|
GETLOCAL(this_instr->operand0) = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_BINARY_SUBSCR_INIT_CALL, (container, sub -- new_frame: _Py_UOpsAbstractFrame *)) {
|
op(_BINARY_SUBSCR_INIT_CALL, (container, sub, getitem -- new_frame: _Py_UOpsAbstractFrame *)) {
|
||||||
(void)container;
|
(void)container;
|
||||||
(void)sub;
|
(void)sub;
|
||||||
|
(void)getitem;
|
||||||
new_frame = NULL;
|
new_frame = NULL;
|
||||||
ctx->done = true;
|
ctx->done = true;
|
||||||
}
|
}
|
||||||
|
16
Python/optimizer_cases.c.h
generated
16
Python/optimizer_cases.c.h
generated
@ -592,21 +592,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
case _BINARY_SUBSCR_CHECK_FUNC: {
|
case _BINARY_SUBSCR_CHECK_FUNC: {
|
||||||
|
_Py_UopsSymbol *getitem;
|
||||||
|
getitem = sym_new_not_null(ctx);
|
||||||
|
stack_pointer[0] = getitem;
|
||||||
|
stack_pointer += 1;
|
||||||
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case _BINARY_SUBSCR_INIT_CALL: {
|
case _BINARY_SUBSCR_INIT_CALL: {
|
||||||
|
_Py_UopsSymbol *getitem;
|
||||||
_Py_UopsSymbol *sub;
|
_Py_UopsSymbol *sub;
|
||||||
_Py_UopsSymbol *container;
|
_Py_UopsSymbol *container;
|
||||||
_Py_UOpsAbstractFrame *new_frame;
|
_Py_UOpsAbstractFrame *new_frame;
|
||||||
sub = stack_pointer[-1];
|
getitem = stack_pointer[-1];
|
||||||
container = stack_pointer[-2];
|
sub = stack_pointer[-2];
|
||||||
|
container = stack_pointer[-3];
|
||||||
(void)container;
|
(void)container;
|
||||||
(void)sub;
|
(void)sub;
|
||||||
|
(void)getitem;
|
||||||
new_frame = NULL;
|
new_frame = NULL;
|
||||||
ctx->done = true;
|
ctx->done = true;
|
||||||
stack_pointer[-2] = (_Py_UopsSymbol *)new_frame;
|
stack_pointer[-3] = (_Py_UopsSymbol *)new_frame;
|
||||||
stack_pointer += -1;
|
stack_pointer += -2;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1096,6 +1096,7 @@ specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* na
|
|||||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
|
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_METHOD);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
/* Don't specialize if PEP 523 is active */
|
||||||
if (_PyInterpreterState_GET()->eval_frame) {
|
if (_PyInterpreterState_GET()->eval_frame) {
|
||||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
|
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1165,6 +1166,7 @@ specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* na
|
|||||||
if (version == 0) {
|
if (version == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
/* Don't specialize if PEP 523 is active */
|
||||||
if (_PyInterpreterState_GET()->eval_frame) {
|
if (_PyInterpreterState_GET()->eval_frame) {
|
||||||
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
|
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1781,12 +1783,12 @@ _Py_Specialize_BinarySubscr(
|
|||||||
specialized_op = BINARY_SUBSCR_DICT;
|
specialized_op = BINARY_SUBSCR_DICT;
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
#ifndef Py_GIL_DISABLED
|
unsigned int tp_version;
|
||||||
PyTypeObject *cls = Py_TYPE(container);
|
PyObject *descriptor = _PyType_LookupRefAndVersion(container_type, &_Py_ID(__getitem__), &tp_version);
|
||||||
PyObject *descriptor = _PyType_Lookup(cls, &_Py_ID(__getitem__));
|
|
||||||
if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
|
if (descriptor && Py_TYPE(descriptor) == &PyFunction_Type) {
|
||||||
if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
|
if (!(container_type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
|
||||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_SUBSCR_NOT_HEAP_TYPE);
|
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_SUBSCR_NOT_HEAP_TYPE);
|
||||||
|
Py_DECREF(descriptor);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
PyFunctionObject *func = (PyFunctionObject *)descriptor;
|
PyFunctionObject *func = (PyFunctionObject *)descriptor;
|
||||||
@ -1794,30 +1796,29 @@ _Py_Specialize_BinarySubscr(
|
|||||||
int kind = function_kind(fcode);
|
int kind = function_kind(fcode);
|
||||||
if (kind != SIMPLE_FUNCTION) {
|
if (kind != SIMPLE_FUNCTION) {
|
||||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, kind);
|
SPECIALIZATION_FAIL(BINARY_SUBSCR, kind);
|
||||||
|
Py_DECREF(descriptor);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (fcode->co_argcount != 2) {
|
if (fcode->co_argcount != 2) {
|
||||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
|
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
|
||||||
|
Py_DECREF(descriptor);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
uint32_t version = _PyFunction_GetVersionForCurrentState(func);
|
|
||||||
if (!_PyFunction_IsVersionValid(version)) {
|
PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type;
|
||||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OUT_OF_VERSIONS);
|
/* Don't specialize if PEP 523 is active */
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (_PyInterpreterState_GET()->eval_frame) {
|
if (_PyInterpreterState_GET()->eval_frame) {
|
||||||
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OTHER);
|
SPECIALIZATION_FAIL(BINARY_SUBSCR, SPEC_FAIL_OTHER);
|
||||||
|
Py_DECREF(descriptor);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
PyHeapTypeObject *ht = (PyHeapTypeObject *)container_type;
|
if (_PyType_CacheGetItemForSpecialization(ht, descriptor, (uint32_t)tp_version)) {
|
||||||
// This pointer is invalidated by PyType_Modified (see the comment on
|
|
||||||
// struct _specialization_cache):
|
|
||||||
ht->_spec_cache.getitem = descriptor;
|
|
||||||
ht->_spec_cache.getitem_version = version;
|
|
||||||
specialized_op = BINARY_SUBSCR_GETITEM;
|
specialized_op = BINARY_SUBSCR_GETITEM;
|
||||||
|
Py_DECREF(descriptor);
|
||||||
goto success;
|
goto success;
|
||||||
}
|
}
|
||||||
#endif // Py_GIL_DISABLED
|
}
|
||||||
|
Py_XDECREF(descriptor);
|
||||||
SPECIALIZATION_FAIL(BINARY_SUBSCR,
|
SPECIALIZATION_FAIL(BINARY_SUBSCR,
|
||||||
binary_subscr_fail_kind(container_type, sub));
|
binary_subscr_fail_kind(container_type, sub));
|
||||||
fail:
|
fail:
|
||||||
@ -2617,6 +2618,7 @@ _Py_Specialize_ForIter(_PyStackRef iter, _Py_CODEUNIT *instr, int oparg)
|
|||||||
assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR ||
|
assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR ||
|
||||||
instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
|
instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == INSTRUMENTED_END_FOR
|
||||||
);
|
);
|
||||||
|
/* Don't specialize if PEP 523 is active */
|
||||||
if (_PyInterpreterState_GET()->eval_frame) {
|
if (_PyInterpreterState_GET()->eval_frame) {
|
||||||
SPECIALIZATION_FAIL(FOR_ITER, SPEC_FAIL_OTHER);
|
SPECIALIZATION_FAIL(FOR_ITER, SPEC_FAIL_OTHER);
|
||||||
goto failure;
|
goto failure;
|
||||||
@ -2645,6 +2647,7 @@ _Py_Specialize_Send(_PyStackRef receiver_st, _Py_CODEUNIT *instr)
|
|||||||
assert(_PyOpcode_Caches[SEND] == INLINE_CACHE_ENTRIES_SEND);
|
assert(_PyOpcode_Caches[SEND] == INLINE_CACHE_ENTRIES_SEND);
|
||||||
PyTypeObject *tp = Py_TYPE(receiver);
|
PyTypeObject *tp = Py_TYPE(receiver);
|
||||||
if (tp == &PyGen_Type || tp == &PyCoro_Type) {
|
if (tp == &PyGen_Type || tp == &PyCoro_Type) {
|
||||||
|
/* Don't specialize if PEP 523 is active */
|
||||||
if (_PyInterpreterState_GET()->eval_frame) {
|
if (_PyInterpreterState_GET()->eval_frame) {
|
||||||
SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER);
|
SPECIALIZATION_FAIL(SEND, SPEC_FAIL_OTHER);
|
||||||
goto failure;
|
goto failure;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user