mirror of
https://github.com/python/cpython.git
synced 2025-08-04 17:08:35 +00:00
gh-131586: Avoid refcount contention in context managers (gh-131851)
This avoid reference count contention in the free threading build when calling special methods like `__enter__` and `__exit__`.
This commit is contained in:
parent
8dfa840773
commit
da53660f35
11 changed files with 247 additions and 207 deletions
|
@ -950,7 +950,7 @@ extern int _PyObject_IsInstanceDictEmpty(PyObject *);
|
|||
|
||||
// Export for 'math' shared extension
|
||||
PyAPI_FUNC(PyObject*) _PyObject_LookupSpecial(PyObject *, PyObject *);
|
||||
PyAPI_FUNC(PyObject*) _PyObject_LookupSpecialMethod(PyObject *self, PyObject *attr, PyObject **self_or_null);
|
||||
PyAPI_FUNC(int) _PyObject_LookupSpecialMethod(PyObject *attr, _PyStackRef *method_and_self);
|
||||
|
||||
// Calls the method named `attr` on `self`, but does not set an exception if
|
||||
// the attribute does not exist.
|
||||
|
|
4
Include/internal/pycore_opcode_metadata.h
generated
4
Include/internal/pycore_opcode_metadata.h
generated
|
@ -1218,7 +1218,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = {
|
|||
[LOAD_LOCALS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
||||
[LOAD_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
||||
[LOAD_SMALL_INT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
||||
[LOAD_SPECIAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
||||
[LOAD_SPECIAL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
|
||||
[LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
||||
[LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
|
||||
[LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
|
||||
|
@ -1427,7 +1427,7 @@ _PyOpcode_macro_expansion[256] = {
|
|||
[LOAD_LOCALS] = { .nuops = 1, .uops = { { _LOAD_LOCALS, OPARG_SIMPLE, 0 } } },
|
||||
[LOAD_NAME] = { .nuops = 1, .uops = { { _LOAD_NAME, OPARG_SIMPLE, 0 } } },
|
||||
[LOAD_SMALL_INT] = { .nuops = 1, .uops = { { _LOAD_SMALL_INT, OPARG_SIMPLE, 0 } } },
|
||||
[LOAD_SPECIAL] = { .nuops = 1, .uops = { { _LOAD_SPECIAL, OPARG_SIMPLE, 0 } } },
|
||||
[LOAD_SPECIAL] = { .nuops = 2, .uops = { { _INSERT_NULL, OPARG_SIMPLE, 0 }, { _LOAD_SPECIAL, OPARG_SIMPLE, 0 } } },
|
||||
[LOAD_SUPER_ATTR_ATTR] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_ATTR, OPARG_SIMPLE, 1 } } },
|
||||
[LOAD_SUPER_ATTR_METHOD] = { .nuops = 1, .uops = { { _LOAD_SUPER_ATTR_METHOD, OPARG_SIMPLE, 1 } } },
|
||||
[MAKE_CELL] = { .nuops = 1, .uops = { { _MAKE_CELL, OPARG_SIMPLE, 0 } } },
|
||||
|
|
207
Include/internal/pycore_uop_ids.h
generated
207
Include/internal/pycore_uop_ids.h
generated
|
@ -151,6 +151,7 @@ extern "C" {
|
|||
#define _INIT_CALL_PY_EXACT_ARGS_2 401
|
||||
#define _INIT_CALL_PY_EXACT_ARGS_3 402
|
||||
#define _INIT_CALL_PY_EXACT_ARGS_4 403
|
||||
#define _INSERT_NULL 404
|
||||
#define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER
|
||||
#define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION
|
||||
#define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD
|
||||
|
@ -160,163 +161,163 @@ extern "C" {
|
|||
#define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE
|
||||
#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE
|
||||
#define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE
|
||||
#define _IS_NONE 404
|
||||
#define _IS_NONE 405
|
||||
#define _IS_OP IS_OP
|
||||
#define _ITER_CHECK_LIST 405
|
||||
#define _ITER_CHECK_RANGE 406
|
||||
#define _ITER_CHECK_TUPLE 407
|
||||
#define _ITER_JUMP_LIST 408
|
||||
#define _ITER_JUMP_RANGE 409
|
||||
#define _ITER_JUMP_TUPLE 410
|
||||
#define _ITER_NEXT_LIST 411
|
||||
#define _ITER_NEXT_LIST_TIER_TWO 412
|
||||
#define _ITER_NEXT_RANGE 413
|
||||
#define _ITER_NEXT_TUPLE 414
|
||||
#define _JUMP_TO_TOP 415
|
||||
#define _ITER_CHECK_LIST 406
|
||||
#define _ITER_CHECK_RANGE 407
|
||||
#define _ITER_CHECK_TUPLE 408
|
||||
#define _ITER_JUMP_LIST 409
|
||||
#define _ITER_JUMP_RANGE 410
|
||||
#define _ITER_JUMP_TUPLE 411
|
||||
#define _ITER_NEXT_LIST 412
|
||||
#define _ITER_NEXT_LIST_TIER_TWO 413
|
||||
#define _ITER_NEXT_RANGE 414
|
||||
#define _ITER_NEXT_TUPLE 415
|
||||
#define _JUMP_TO_TOP 416
|
||||
#define _LIST_APPEND LIST_APPEND
|
||||
#define _LIST_EXTEND LIST_EXTEND
|
||||
#define _LOAD_ATTR 416
|
||||
#define _LOAD_ATTR_CLASS 417
|
||||
#define _LOAD_ATTR 417
|
||||
#define _LOAD_ATTR_CLASS 418
|
||||
#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN
|
||||
#define _LOAD_ATTR_INSTANCE_VALUE 418
|
||||
#define _LOAD_ATTR_METHOD_LAZY_DICT 419
|
||||
#define _LOAD_ATTR_METHOD_NO_DICT 420
|
||||
#define _LOAD_ATTR_METHOD_WITH_VALUES 421
|
||||
#define _LOAD_ATTR_MODULE 422
|
||||
#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 423
|
||||
#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 424
|
||||
#define _LOAD_ATTR_PROPERTY_FRAME 425
|
||||
#define _LOAD_ATTR_SLOT 426
|
||||
#define _LOAD_ATTR_WITH_HINT 427
|
||||
#define _LOAD_ATTR_INSTANCE_VALUE 419
|
||||
#define _LOAD_ATTR_METHOD_LAZY_DICT 420
|
||||
#define _LOAD_ATTR_METHOD_NO_DICT 421
|
||||
#define _LOAD_ATTR_METHOD_WITH_VALUES 422
|
||||
#define _LOAD_ATTR_MODULE 423
|
||||
#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 424
|
||||
#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 425
|
||||
#define _LOAD_ATTR_PROPERTY_FRAME 426
|
||||
#define _LOAD_ATTR_SLOT 427
|
||||
#define _LOAD_ATTR_WITH_HINT 428
|
||||
#define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS
|
||||
#define _LOAD_BYTECODE 428
|
||||
#define _LOAD_BYTECODE 429
|
||||
#define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT
|
||||
#define _LOAD_CONST LOAD_CONST
|
||||
#define _LOAD_CONST_IMMORTAL LOAD_CONST_IMMORTAL
|
||||
#define _LOAD_CONST_INLINE 429
|
||||
#define _LOAD_CONST_INLINE_BORROW 430
|
||||
#define _LOAD_CONST_INLINE 430
|
||||
#define _LOAD_CONST_INLINE_BORROW 431
|
||||
#define _LOAD_CONST_MORTAL LOAD_CONST_MORTAL
|
||||
#define _LOAD_DEREF LOAD_DEREF
|
||||
#define _LOAD_FAST 431
|
||||
#define _LOAD_FAST_0 432
|
||||
#define _LOAD_FAST_1 433
|
||||
#define _LOAD_FAST_2 434
|
||||
#define _LOAD_FAST_3 435
|
||||
#define _LOAD_FAST_4 436
|
||||
#define _LOAD_FAST_5 437
|
||||
#define _LOAD_FAST_6 438
|
||||
#define _LOAD_FAST_7 439
|
||||
#define _LOAD_FAST 432
|
||||
#define _LOAD_FAST_0 433
|
||||
#define _LOAD_FAST_1 434
|
||||
#define _LOAD_FAST_2 435
|
||||
#define _LOAD_FAST_3 436
|
||||
#define _LOAD_FAST_4 437
|
||||
#define _LOAD_FAST_5 438
|
||||
#define _LOAD_FAST_6 439
|
||||
#define _LOAD_FAST_7 440
|
||||
#define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR
|
||||
#define _LOAD_FAST_BORROW 440
|
||||
#define _LOAD_FAST_BORROW_0 441
|
||||
#define _LOAD_FAST_BORROW_1 442
|
||||
#define _LOAD_FAST_BORROW_2 443
|
||||
#define _LOAD_FAST_BORROW_3 444
|
||||
#define _LOAD_FAST_BORROW_4 445
|
||||
#define _LOAD_FAST_BORROW_5 446
|
||||
#define _LOAD_FAST_BORROW_6 447
|
||||
#define _LOAD_FAST_BORROW_7 448
|
||||
#define _LOAD_FAST_BORROW 441
|
||||
#define _LOAD_FAST_BORROW_0 442
|
||||
#define _LOAD_FAST_BORROW_1 443
|
||||
#define _LOAD_FAST_BORROW_2 444
|
||||
#define _LOAD_FAST_BORROW_3 445
|
||||
#define _LOAD_FAST_BORROW_4 446
|
||||
#define _LOAD_FAST_BORROW_5 447
|
||||
#define _LOAD_FAST_BORROW_6 448
|
||||
#define _LOAD_FAST_BORROW_7 449
|
||||
#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW LOAD_FAST_BORROW_LOAD_FAST_BORROW
|
||||
#define _LOAD_FAST_CHECK LOAD_FAST_CHECK
|
||||
#define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST
|
||||
#define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF
|
||||
#define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS
|
||||
#define _LOAD_GLOBAL 449
|
||||
#define _LOAD_GLOBAL_BUILTINS 450
|
||||
#define _LOAD_GLOBAL_MODULE 451
|
||||
#define _LOAD_GLOBAL 450
|
||||
#define _LOAD_GLOBAL_BUILTINS 451
|
||||
#define _LOAD_GLOBAL_MODULE 452
|
||||
#define _LOAD_LOCALS LOAD_LOCALS
|
||||
#define _LOAD_NAME LOAD_NAME
|
||||
#define _LOAD_SMALL_INT 452
|
||||
#define _LOAD_SMALL_INT_0 453
|
||||
#define _LOAD_SMALL_INT_1 454
|
||||
#define _LOAD_SMALL_INT_2 455
|
||||
#define _LOAD_SMALL_INT_3 456
|
||||
#define _LOAD_SPECIAL LOAD_SPECIAL
|
||||
#define _LOAD_SMALL_INT 453
|
||||
#define _LOAD_SMALL_INT_0 454
|
||||
#define _LOAD_SMALL_INT_1 455
|
||||
#define _LOAD_SMALL_INT_2 456
|
||||
#define _LOAD_SMALL_INT_3 457
|
||||
#define _LOAD_SPECIAL 458
|
||||
#define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR
|
||||
#define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD
|
||||
#define _MAKE_CALLARGS_A_TUPLE 457
|
||||
#define _MAKE_CALLARGS_A_TUPLE 459
|
||||
#define _MAKE_CELL MAKE_CELL
|
||||
#define _MAKE_FUNCTION MAKE_FUNCTION
|
||||
#define _MAKE_WARM 458
|
||||
#define _MAKE_WARM 460
|
||||
#define _MAP_ADD MAP_ADD
|
||||
#define _MATCH_CLASS MATCH_CLASS
|
||||
#define _MATCH_KEYS MATCH_KEYS
|
||||
#define _MATCH_MAPPING MATCH_MAPPING
|
||||
#define _MATCH_SEQUENCE MATCH_SEQUENCE
|
||||
#define _MAYBE_EXPAND_METHOD 459
|
||||
#define _MAYBE_EXPAND_METHOD_KW 460
|
||||
#define _MONITOR_CALL 461
|
||||
#define _MONITOR_CALL_KW 462
|
||||
#define _MONITOR_JUMP_BACKWARD 463
|
||||
#define _MONITOR_RESUME 464
|
||||
#define _MAYBE_EXPAND_METHOD 461
|
||||
#define _MAYBE_EXPAND_METHOD_KW 462
|
||||
#define _MONITOR_CALL 463
|
||||
#define _MONITOR_CALL_KW 464
|
||||
#define _MONITOR_JUMP_BACKWARD 465
|
||||
#define _MONITOR_RESUME 466
|
||||
#define _NOP NOP
|
||||
#define _POP_EXCEPT POP_EXCEPT
|
||||
#define _POP_JUMP_IF_FALSE 465
|
||||
#define _POP_JUMP_IF_TRUE 466
|
||||
#define _POP_JUMP_IF_FALSE 467
|
||||
#define _POP_JUMP_IF_TRUE 468
|
||||
#define _POP_TOP POP_TOP
|
||||
#define _POP_TOP_LOAD_CONST_INLINE 467
|
||||
#define _POP_TOP_LOAD_CONST_INLINE_BORROW 468
|
||||
#define _POP_TWO_LOAD_CONST_INLINE_BORROW 469
|
||||
#define _POP_TOP_LOAD_CONST_INLINE 469
|
||||
#define _POP_TOP_LOAD_CONST_INLINE_BORROW 470
|
||||
#define _POP_TWO_LOAD_CONST_INLINE_BORROW 471
|
||||
#define _PUSH_EXC_INFO PUSH_EXC_INFO
|
||||
#define _PUSH_FRAME 470
|
||||
#define _PUSH_FRAME 472
|
||||
#define _PUSH_NULL PUSH_NULL
|
||||
#define _PUSH_NULL_CONDITIONAL 471
|
||||
#define _PY_FRAME_GENERAL 472
|
||||
#define _PY_FRAME_KW 473
|
||||
#define _QUICKEN_RESUME 474
|
||||
#define _REPLACE_WITH_TRUE 475
|
||||
#define _PUSH_NULL_CONDITIONAL 473
|
||||
#define _PY_FRAME_GENERAL 474
|
||||
#define _PY_FRAME_KW 475
|
||||
#define _QUICKEN_RESUME 476
|
||||
#define _REPLACE_WITH_TRUE 477
|
||||
#define _RESUME_CHECK RESUME_CHECK
|
||||
#define _RETURN_GENERATOR RETURN_GENERATOR
|
||||
#define _RETURN_VALUE RETURN_VALUE
|
||||
#define _SAVE_RETURN_OFFSET 476
|
||||
#define _SEND 477
|
||||
#define _SEND_GEN_FRAME 478
|
||||
#define _SAVE_RETURN_OFFSET 478
|
||||
#define _SEND 479
|
||||
#define _SEND_GEN_FRAME 480
|
||||
#define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS
|
||||
#define _SET_ADD SET_ADD
|
||||
#define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE
|
||||
#define _SET_UPDATE SET_UPDATE
|
||||
#define _START_EXECUTOR 479
|
||||
#define _STORE_ATTR 480
|
||||
#define _STORE_ATTR_INSTANCE_VALUE 481
|
||||
#define _STORE_ATTR_SLOT 482
|
||||
#define _STORE_ATTR_WITH_HINT 483
|
||||
#define _START_EXECUTOR 481
|
||||
#define _STORE_ATTR 482
|
||||
#define _STORE_ATTR_INSTANCE_VALUE 483
|
||||
#define _STORE_ATTR_SLOT 484
|
||||
#define _STORE_ATTR_WITH_HINT 485
|
||||
#define _STORE_DEREF STORE_DEREF
|
||||
#define _STORE_FAST 484
|
||||
#define _STORE_FAST_0 485
|
||||
#define _STORE_FAST_1 486
|
||||
#define _STORE_FAST_2 487
|
||||
#define _STORE_FAST_3 488
|
||||
#define _STORE_FAST_4 489
|
||||
#define _STORE_FAST_5 490
|
||||
#define _STORE_FAST_6 491
|
||||
#define _STORE_FAST_7 492
|
||||
#define _STORE_FAST 486
|
||||
#define _STORE_FAST_0 487
|
||||
#define _STORE_FAST_1 488
|
||||
#define _STORE_FAST_2 489
|
||||
#define _STORE_FAST_3 490
|
||||
#define _STORE_FAST_4 491
|
||||
#define _STORE_FAST_5 492
|
||||
#define _STORE_FAST_6 493
|
||||
#define _STORE_FAST_7 494
|
||||
#define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST
|
||||
#define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST
|
||||
#define _STORE_GLOBAL STORE_GLOBAL
|
||||
#define _STORE_NAME STORE_NAME
|
||||
#define _STORE_SLICE 493
|
||||
#define _STORE_SUBSCR 494
|
||||
#define _STORE_SUBSCR_DICT 495
|
||||
#define _STORE_SUBSCR_LIST_INT 496
|
||||
#define _STORE_SLICE 495
|
||||
#define _STORE_SUBSCR 496
|
||||
#define _STORE_SUBSCR_DICT 497
|
||||
#define _STORE_SUBSCR_LIST_INT 498
|
||||
#define _SWAP SWAP
|
||||
#define _TIER2_RESUME_CHECK 497
|
||||
#define _TO_BOOL 498
|
||||
#define _TIER2_RESUME_CHECK 499
|
||||
#define _TO_BOOL 500
|
||||
#define _TO_BOOL_BOOL TO_BOOL_BOOL
|
||||
#define _TO_BOOL_INT TO_BOOL_INT
|
||||
#define _TO_BOOL_LIST 499
|
||||
#define _TO_BOOL_LIST 501
|
||||
#define _TO_BOOL_NONE TO_BOOL_NONE
|
||||
#define _TO_BOOL_STR 500
|
||||
#define _TO_BOOL_STR 502
|
||||
#define _UNARY_INVERT UNARY_INVERT
|
||||
#define _UNARY_NEGATIVE UNARY_NEGATIVE
|
||||
#define _UNARY_NOT UNARY_NOT
|
||||
#define _UNPACK_EX UNPACK_EX
|
||||
#define _UNPACK_SEQUENCE 501
|
||||
#define _UNPACK_SEQUENCE_LIST 502
|
||||
#define _UNPACK_SEQUENCE_TUPLE 503
|
||||
#define _UNPACK_SEQUENCE_TWO_TUPLE 504
|
||||
#define _UNPACK_SEQUENCE 503
|
||||
#define _UNPACK_SEQUENCE_LIST 504
|
||||
#define _UNPACK_SEQUENCE_TUPLE 505
|
||||
#define _UNPACK_SEQUENCE_TWO_TUPLE 506
|
||||
#define _WITH_EXCEPT_START WITH_EXCEPT_START
|
||||
#define _YIELD_VALUE YIELD_VALUE
|
||||
#define MAX_UOP_ID 504
|
||||
#define MAX_UOP_ID 506
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
8
Include/internal/pycore_uop_metadata.h
generated
8
Include/internal/pycore_uop_metadata.h
generated
|
@ -209,7 +209,8 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
|
|||
[_GUARD_NOT_EXHAUSTED_RANGE] = HAS_EXIT_FLAG,
|
||||
[_ITER_NEXT_RANGE] = HAS_ERROR_FLAG,
|
||||
[_FOR_ITER_GEN_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
|
||||
[_LOAD_SPECIAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
|
||||
[_INSERT_NULL] = 0,
|
||||
[_LOAD_SPECIAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
|
||||
[_WITH_EXCEPT_START] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
|
||||
[_PUSH_EXC_INFO] = 0,
|
||||
[_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = HAS_DEOPT_FLAG,
|
||||
|
@ -445,6 +446,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
|
|||
[_INIT_CALL_PY_EXACT_ARGS_2] = "_INIT_CALL_PY_EXACT_ARGS_2",
|
||||
[_INIT_CALL_PY_EXACT_ARGS_3] = "_INIT_CALL_PY_EXACT_ARGS_3",
|
||||
[_INIT_CALL_PY_EXACT_ARGS_4] = "_INIT_CALL_PY_EXACT_ARGS_4",
|
||||
[_INSERT_NULL] = "_INSERT_NULL",
|
||||
[_IS_NONE] = "_IS_NONE",
|
||||
[_IS_OP] = "_IS_OP",
|
||||
[_ITER_CHECK_LIST] = "_ITER_CHECK_LIST",
|
||||
|
@ -970,8 +972,10 @@ int _PyUop_num_popped(int opcode, int oparg)
|
|||
return 0;
|
||||
case _FOR_ITER_GEN_FRAME:
|
||||
return 0;
|
||||
case _LOAD_SPECIAL:
|
||||
case _INSERT_NULL:
|
||||
return 1;
|
||||
case _LOAD_SPECIAL:
|
||||
return 0;
|
||||
case _WITH_EXCEPT_START:
|
||||
return 0;
|
||||
case _PUSH_EXC_INFO:
|
||||
|
|
|
@ -2794,32 +2794,37 @@ _PyObject_LookupSpecial(PyObject *self, PyObject *attr)
|
|||
return res;
|
||||
}
|
||||
|
||||
/* Steals a reference to self */
|
||||
PyObject *
|
||||
_PyObject_LookupSpecialMethod(PyObject *self, PyObject *attr, PyObject **self_or_null)
|
||||
// Lookup the method name `attr` on `self`. On entry, `method_and_self[0]`
|
||||
// is null and `method_and_self[1]` is `self`. On exit, `method_and_self[0]`
|
||||
// is the method object and `method_and_self[1]` is `self` if the method is
|
||||
// not bound.
|
||||
// Return 1 on success, -1 on error, and 0 if the method is missing.
|
||||
int
|
||||
_PyObject_LookupSpecialMethod(PyObject *attr, _PyStackRef *method_and_self)
|
||||
{
|
||||
PyObject *res;
|
||||
|
||||
res = _PyType_LookupRef(Py_TYPE(self), attr);
|
||||
if (res == NULL) {
|
||||
Py_DECREF(self);
|
||||
*self_or_null = NULL;
|
||||
return NULL;
|
||||
PyObject *self = PyStackRef_AsPyObjectBorrow(method_and_self[1]);
|
||||
_PyType_LookupStackRefAndVersion(Py_TYPE(self), attr, &method_and_self[0]);
|
||||
PyObject *method_o = PyStackRef_AsPyObjectBorrow(method_and_self[0]);
|
||||
if (method_o == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
|
||||
if (_PyType_HasFeature(Py_TYPE(method_o), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
|
||||
/* Avoid temporary PyMethodObject */
|
||||
*self_or_null = self;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
descrgetfunc f = Py_TYPE(res)->tp_descr_get;
|
||||
if (f != NULL) {
|
||||
Py_SETREF(res, f(res, self, (PyObject *)(Py_TYPE(self))));
|
||||
|
||||
descrgetfunc f = Py_TYPE(method_o)->tp_descr_get;
|
||||
if (f != NULL) {
|
||||
PyObject *func = f(method_o, self, (PyObject *)(Py_TYPE(self)));
|
||||
if (func == NULL) {
|
||||
return -1;
|
||||
}
|
||||
*self_or_null = NULL;
|
||||
Py_DECREF(self);
|
||||
PyStackRef_CLEAR(method_and_self[0]); // clear method
|
||||
method_and_self[0] = PyStackRef_FromPyObjectSteal(func);
|
||||
}
|
||||
return res;
|
||||
PyStackRef_CLEAR(method_and_self[1]); // clear self
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -3417,28 +3417,33 @@ dummy_func(
|
|||
_FOR_ITER_GEN_FRAME +
|
||||
_PUSH_FRAME;
|
||||
|
||||
inst(LOAD_SPECIAL, (owner -- attr, self_or_null)) {
|
||||
assert(oparg <= SPECIAL_MAX);
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectSteal(owner);
|
||||
op(_INSERT_NULL, (self -- method_and_self[2])) {
|
||||
method_and_self[1] = self;
|
||||
method_and_self[0] = PyStackRef_NULL;
|
||||
DEAD(self);
|
||||
}
|
||||
|
||||
op(_LOAD_SPECIAL, (method_and_self[2] -- method_and_self[2])) {
|
||||
PyObject *name = _Py_SpecialMethods[oparg].name;
|
||||
PyObject *self_or_null_o;
|
||||
PyObject *attr_o = _PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o);
|
||||
if (attr_o == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
const char *errfmt = _PyEval_SpecialMethodCanSuggest(owner_o, oparg)
|
||||
int err = _PyObject_LookupSpecialMethod(name, method_and_self);
|
||||
if (err <= 0) {
|
||||
if (err == 0) {
|
||||
PyObject *owner = PyStackRef_AsPyObjectBorrow(method_and_self[1]);
|
||||
const char *errfmt = _PyEval_SpecialMethodCanSuggest(owner, oparg)
|
||||
? _Py_SpecialMethods[oparg].error_suggestion
|
||||
: _Py_SpecialMethods[oparg].error;
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
assert(errfmt != NULL);
|
||||
_PyErr_Format(tstate, PyExc_TypeError, errfmt, owner_o);
|
||||
_PyErr_Format(tstate, PyExc_TypeError, errfmt, owner);
|
||||
}
|
||||
ERROR_IF(true, error);
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
attr = PyStackRef_FromPyObjectSteal(attr_o);
|
||||
self_or_null = self_or_null_o == NULL ?
|
||||
PyStackRef_NULL : PyStackRef_FromPyObjectSteal(self_or_null_o);
|
||||
}
|
||||
|
||||
macro(LOAD_SPECIAL) =
|
||||
_INSERT_NULL +
|
||||
_LOAD_SPECIAL;
|
||||
|
||||
inst(WITH_EXCEPT_START, (exit_func, exit_self, lasti, unused, val -- exit_func, exit_self, lasti, unused, val, res)) {
|
||||
/* At the top of the stack are 4 values:
|
||||
- val: TOP = exc_info()
|
||||
|
|
45
Python/executor_cases.c.h
generated
45
Python/executor_cases.c.h
generated
|
@ -4407,43 +4407,42 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _LOAD_SPECIAL: {
|
||||
_PyStackRef owner;
|
||||
_PyStackRef attr;
|
||||
_PyStackRef self_or_null;
|
||||
oparg = CURRENT_OPARG();
|
||||
owner = stack_pointer[-1];
|
||||
assert(oparg <= SPECIAL_MAX);
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectSteal(owner);
|
||||
PyObject *name = _Py_SpecialMethods[oparg].name;
|
||||
PyObject *self_or_null_o;
|
||||
stack_pointer += -1;
|
||||
case _INSERT_NULL: {
|
||||
_PyStackRef self;
|
||||
_PyStackRef *method_and_self;
|
||||
self = stack_pointer[-1];
|
||||
method_and_self = &stack_pointer[-1];
|
||||
method_and_self[1] = self;
|
||||
method_and_self[0] = PyStackRef_NULL;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_SPECIAL: {
|
||||
_PyStackRef *method_and_self;
|
||||
oparg = CURRENT_OPARG();
|
||||
method_and_self = &stack_pointer[-2];
|
||||
PyObject *name = _Py_SpecialMethods[oparg].name;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *attr_o = _PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o);
|
||||
int err = _PyObject_LookupSpecialMethod(name, method_and_self);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (attr_o == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
if (err <= 0) {
|
||||
if (err == 0) {
|
||||
PyObject *owner = PyStackRef_AsPyObjectBorrow(method_and_self[1]);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
const char *errfmt = _PyEval_SpecialMethodCanSuggest(owner_o, oparg)
|
||||
const char *errfmt = _PyEval_SpecialMethodCanSuggest(owner, oparg)
|
||||
? _Py_SpecialMethods[oparg].error_suggestion
|
||||
: _Py_SpecialMethods[oparg].error;
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
assert(errfmt != NULL);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyErr_Format(tstate, PyExc_TypeError, errfmt, owner_o);
|
||||
_PyErr_Format(tstate, PyExc_TypeError, errfmt, owner);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
JUMP_TO_ERROR();
|
||||
}
|
||||
attr = PyStackRef_FromPyObjectSteal(attr_o);
|
||||
self_or_null = self_or_null_o == NULL ?
|
||||
PyStackRef_NULL : PyStackRef_FromPyObjectSteal(self_or_null_o);
|
||||
stack_pointer[0] = attr;
|
||||
stack_pointer[1] = self_or_null;
|
||||
stack_pointer += 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
68
Python/generated_cases.c.h
generated
68
Python/generated_cases.c.h
generated
|
@ -9342,41 +9342,41 @@
|
|||
frame->instr_ptr = next_instr;
|
||||
next_instr += 1;
|
||||
INSTRUCTION_STATS(LOAD_SPECIAL);
|
||||
_PyStackRef owner;
|
||||
_PyStackRef attr;
|
||||
_PyStackRef self_or_null;
|
||||
owner = stack_pointer[-1];
|
||||
assert(oparg <= SPECIAL_MAX);
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectSteal(owner);
|
||||
PyObject *name = _Py_SpecialMethods[oparg].name;
|
||||
PyObject *self_or_null_o;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *attr_o = _PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (attr_o == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
const char *errfmt = _PyEval_SpecialMethodCanSuggest(owner_o, oparg)
|
||||
? _Py_SpecialMethods[oparg].error_suggestion
|
||||
: _Py_SpecialMethods[oparg].error;
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
assert(errfmt != NULL);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyErr_Format(tstate, PyExc_TypeError, errfmt, owner_o);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
JUMP_TO_LABEL(error);
|
||||
_PyStackRef self;
|
||||
_PyStackRef *method_and_self;
|
||||
// _INSERT_NULL
|
||||
{
|
||||
self = stack_pointer[-1];
|
||||
method_and_self = &stack_pointer[-1];
|
||||
method_and_self[1] = self;
|
||||
method_and_self[0] = PyStackRef_NULL;
|
||||
}
|
||||
// _LOAD_SPECIAL
|
||||
{
|
||||
method_and_self = &stack_pointer[-1];
|
||||
PyObject *name = _Py_SpecialMethods[oparg].name;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
int err = _PyObject_LookupSpecialMethod(name, method_and_self);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (err <= 0) {
|
||||
if (err == 0) {
|
||||
PyObject *owner = PyStackRef_AsPyObjectBorrow(method_and_self[1]);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
const char *errfmt = _PyEval_SpecialMethodCanSuggest(owner, oparg)
|
||||
? _Py_SpecialMethods[oparg].error_suggestion
|
||||
: _Py_SpecialMethods[oparg].error;
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
assert(errfmt != NULL);
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
_PyErr_Format(tstate, PyExc_TypeError, errfmt, owner);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
JUMP_TO_LABEL(error);
|
||||
}
|
||||
}
|
||||
attr = PyStackRef_FromPyObjectSteal(attr_o);
|
||||
self_or_null = self_or_null_o == NULL ?
|
||||
PyStackRef_NULL : PyStackRef_FromPyObjectSteal(self_or_null_o);
|
||||
stack_pointer[0] = attr;
|
||||
stack_pointer[1] = self_or_null;
|
||||
stack_pointer += 2;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
|
|
@ -897,9 +897,14 @@ dummy_func(void) {
|
|||
}
|
||||
}
|
||||
|
||||
op(_LOAD_SPECIAL, (owner -- attr, self_or_null)) {
|
||||
attr = sym_new_not_null(ctx);
|
||||
self_or_null = sym_new_unknown(ctx);
|
||||
op(_INSERT_NULL, (self -- method_and_self[2])) {
|
||||
method_and_self[0] = sym_new_null(ctx);
|
||||
method_and_self[1] = self;
|
||||
}
|
||||
|
||||
op(_LOAD_SPECIAL, (method_and_self[2] -- method_and_self[2])) {
|
||||
method_and_self[0] = sym_new_not_null(ctx);
|
||||
method_and_self[1] = sym_new_unknown(ctx);
|
||||
}
|
||||
|
||||
op(_JUMP_TO_TOP, (--)) {
|
||||
|
|
22
Python/optimizer_cases.c.h
generated
22
Python/optimizer_cases.c.h
generated
|
@ -1553,18 +1553,26 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _LOAD_SPECIAL: {
|
||||
JitOptSymbol *attr;
|
||||
JitOptSymbol *self_or_null;
|
||||
attr = sym_new_not_null(ctx);
|
||||
self_or_null = sym_new_unknown(ctx);
|
||||
stack_pointer[-1] = attr;
|
||||
stack_pointer[0] = self_or_null;
|
||||
case _INSERT_NULL: {
|
||||
JitOptSymbol *self;
|
||||
JitOptSymbol **method_and_self;
|
||||
self = stack_pointer[-1];
|
||||
method_and_self = &stack_pointer[-1];
|
||||
method_and_self[0] = sym_new_null(ctx);
|
||||
method_and_self[1] = self;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_SPECIAL: {
|
||||
JitOptSymbol **method_and_self;
|
||||
method_and_self = &stack_pointer[-2];
|
||||
method_and_self[0] = sym_new_not_null(ctx);
|
||||
method_and_self[1] = sym_new_unknown(ctx);
|
||||
break;
|
||||
}
|
||||
|
||||
case _WITH_EXCEPT_START: {
|
||||
JitOptSymbol *res;
|
||||
res = sym_new_not_null(ctx);
|
||||
|
|
|
@ -65,6 +65,19 @@ def object_lookup_special():
|
|||
for i in range(N):
|
||||
round(i / N)
|
||||
|
||||
class MyContextManager:
|
||||
def __enter__(self):
|
||||
pass
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
pass
|
||||
|
||||
@register_benchmark
|
||||
def context_manager():
|
||||
N = 1000 * WORK_SCALE
|
||||
for i in range(N):
|
||||
with MyContextManager():
|
||||
pass
|
||||
|
||||
@register_benchmark
|
||||
def mult_constant():
|
||||
x = 1.0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue