diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index 8e1415f27b63f3..c1368d07b09257 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -313,6 +313,7 @@ extern void _Py_Specialize_CompareOp(_PyStackRef lhs, _PyStackRef rhs, _Py_CODEUNIT *instr, int oparg); extern void _Py_Specialize_UnpackSequence(_PyStackRef seq, _Py_CODEUNIT *instr, int oparg); +extern void _Py_Specialize_GetIter(_PyStackRef iter, _Py_CODEUNIT *instr); extern void _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT *instr, int oparg); extern void _Py_Specialize_Send(_PyStackRef receiver, _Py_CODEUNIT *instr); extern void _Py_Specialize_ToBool(_PyStackRef value, _Py_CODEUNIT *instr); diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index 347d9762f26bff..17f1d4c26a52a1 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -281,6 +281,7 @@ Known values: Python 3.15a1 3651 (Simplify LOAD_CONST) Python 3.15a1 3652 (Virtual iterators) Python 3.15a1 3653 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST) + Python 3.15a1 3654 (Specialize GET_ITER) Python 3.16 will start with 3700 @@ -294,7 +295,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3653 +#define PYC_MAGIC_NUMBER 3654 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 00e918cb8f0cd1..d243bd9038c899 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -222,6 +222,12 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 1; case GET_ITER: return 1; + case GET_ITER_LIST_OR_TUPLE: + return 1; + case GET_ITER_RANGE: + return 1; + case GET_ITER_SELF: + return 1; case GET_LEN: return 1; case GET_YIELD_FROM_ITER: @@ -705,6 +711,12 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 1; case GET_ITER: return 2; + case GET_ITER_LIST_OR_TUPLE: + return 2; + case GET_ITER_RANGE: + return 2; + case GET_ITER_SELF: + return 2; case GET_LEN: return 2; case GET_YIELD_FROM_ITER: @@ -1156,12 +1168,15 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG }, [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG }, - [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG }, + [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG }, [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG }, [GET_AITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [GET_ANEXT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [GET_AWAITABLE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, - [GET_ITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [GET_ITER] = { true, INSTR_FMT_IXC, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [GET_ITER_LIST_OR_TUPLE] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, + [GET_ITER_RANGE] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG }, + [GET_ITER_SELF] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG }, [GET_LEN] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [GET_YIELD_FROM_ITER] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, @@ -1403,6 +1418,9 @@ _PyOpcode_macro_expansion[256] = { [GET_ANEXT] = { .nuops = 1, .uops = { { _GET_ANEXT, OPARG_SIMPLE, 0 } } }, [GET_AWAITABLE] = { .nuops = 1, .uops = { { _GET_AWAITABLE, OPARG_SIMPLE, 0 } } }, [GET_ITER] = { .nuops = 1, .uops = { { _GET_ITER, OPARG_SIMPLE, 0 } } }, + [GET_ITER_LIST_OR_TUPLE] = { .nuops = 1, .uops = { { _GET_ITER_LIST_OR_TUPLE, OPARG_SIMPLE, 1 } } }, + [GET_ITER_RANGE] = { .nuops = 1, .uops = { { _GET_ITER_RANGE, OPARG_SIMPLE, 1 } } }, + [GET_ITER_SELF] = { .nuops = 1, .uops = { { _GET_ITER_SELF, OPARG_SIMPLE, 1 } } }, [GET_LEN] = { .nuops = 1, .uops = { { _GET_LEN, OPARG_SIMPLE, 0 } } }, [GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { _GET_YIELD_FROM_ITER, OPARG_SIMPLE, 0 } } }, [IMPORT_FROM] = { .nuops = 1, .uops = { { _IMPORT_FROM, OPARG_SIMPLE, 0 } } }, @@ -1600,6 +1618,9 @@ const char *_PyOpcode_OpName[267] = { [GET_ANEXT] = "GET_ANEXT", [GET_AWAITABLE] = "GET_AWAITABLE", [GET_ITER] = "GET_ITER", + [GET_ITER_LIST_OR_TUPLE] = "GET_ITER_LIST_OR_TUPLE", + [GET_ITER_RANGE] = "GET_ITER_RANGE", + [GET_ITER_SELF] = "GET_ITER_SELF", [GET_LEN] = "GET_LEN", [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", [IMPORT_FROM] = "IMPORT_FROM", @@ -1764,6 +1785,7 @@ const uint8_t _PyOpcode_Caches[256] = { [POP_JUMP_IF_FALSE] = 1, [POP_JUMP_IF_NONE] = 1, [POP_JUMP_IF_NOT_NONE] = 1, + [GET_ITER] = 1, [FOR_ITER] = 1, [CALL] = 3, [CALL_KW] = 3, @@ -1781,9 +1803,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [125] = 125, [126] = 126, [127] = 127, - [210] = 210, - [211] = 211, - [212] = 212, [213] = 213, [214] = 214, [215] = 215, @@ -1897,6 +1916,9 @@ const uint8_t _PyOpcode_Deopt[256] = { [GET_ANEXT] = GET_ANEXT, [GET_AWAITABLE] = GET_AWAITABLE, [GET_ITER] = GET_ITER, + [GET_ITER_LIST_OR_TUPLE] = GET_ITER, + [GET_ITER_RANGE] = GET_ITER, + [GET_ITER_SELF] = GET_ITER, [GET_LEN] = GET_LEN, [GET_YIELD_FROM_ITER] = GET_YIELD_FROM_ITER, [IMPORT_FROM] = IMPORT_FROM, @@ -2042,9 +2064,6 @@ const uint8_t _PyOpcode_Deopt[256] = { case 125: \ case 126: \ case 127: \ - case 210: \ - case 211: \ - case 212: \ case 213: \ case 214: \ case 215: \ diff --git a/Include/internal/pycore_range.h b/Include/internal/pycore_range.h index bf045ec4fd8332..b547dff6a10dca 100644 --- a/Include/internal/pycore_range.h +++ b/Include/internal/pycore_range.h @@ -8,6 +8,14 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif +typedef struct { + PyObject_HEAD + PyObject *start; + PyObject *stop; + PyObject *step; + PyObject *length; +} rangeobject; + typedef struct { PyObject_HEAD long start; @@ -15,6 +23,37 @@ typedef struct { long len; } _PyRangeIterObject; +// Does this range have step == 1 and both start and stop in compact int range? +static inline int +_PyRange_IsSimpleCompact(PyObject *range) { + assert(PyRange_Check(range)); + rangeobject *r = (rangeobject*)range; + if (_PyLong_IsCompact((PyLongObject *)r->start) && + _PyLong_IsCompact((PyLongObject *)r->stop) && + r->step == _PyLong_GetOne() + ) { + return 1; + } + return 0; +} + +static inline Py_ssize_t +_PyRange_GetStartIfCompact(PyObject *range) +{ + assert(PyRange_Check(range)); + rangeobject *r = (rangeobject*)range; + assert(_PyLong_IsCompact((PyLongObject *)r->start)); + return _PyLong_CompactValue((PyLongObject *)r->start); +} + +static inline Py_ssize_t +_PyRange_GetStopIfCompact(PyObject *range) { + assert(PyRange_Check(range)); + rangeobject *r = (rangeobject*)range; + assert(_PyLong_IsCompact((PyLongObject *)r->stop)); + return _PyLong_CompactValue((PyLongObject *)r->stop); +} + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_stackref.h b/Include/internal/pycore_stackref.h index 8791476725289c..a466903d367128 100644 --- a/Include/internal/pycore_stackref.h +++ b/Include/internal/pycore_stackref.h @@ -115,6 +115,14 @@ PyStackRef_IsTaggedInt(_PyStackRef ref) return (ref.index & 1) == 1; } +static inline bool +PyStackRef_TaggedIntLessThan(_PyStackRef a, _PyStackRef b) +{ + assert(PyStackRef_IsTaggedInt(a)); + assert(PyStackRef_IsTaggedInt(b)); + return ((intptr_t)a.bits) < ((intptr_t)b.bits); +} + static inline PyObject * _PyStackRef_AsPyObjectBorrow(_PyStackRef ref, const char *filename, int linenumber) { @@ -303,10 +311,18 @@ static inline _PyStackRef PyStackRef_IncrementTaggedIntNoOverflow(_PyStackRef ref) { assert((ref.bits & Py_TAG_BITS) == Py_INT_TAG); // Is tagged int - assert((ref.bits & (~Py_TAG_BITS)) != (INT_MAX & (~Py_TAG_BITS))); // Isn't about to overflow + assert((ref.bits & (~Py_TAG_BITS)) != (INTPTR_MAX & (~Py_TAG_BITS))); // Isn't about to overflow return (_PyStackRef){ .bits = ref.bits + 4 }; } +static inline bool +PyStackRef_TaggedIntLessThan(_PyStackRef a, _PyStackRef b) +{ + assert(PyStackRef_IsTaggedInt(a)); + assert(PyStackRef_IsTaggedInt(b)); + return ((intptr_t)a.bits) < ((intptr_t)b.bits); +} + #define PyStackRef_IsDeferredOrTaggedInt(ref) (((ref).bits & Py_TAG_REFCNT) != 0) #ifdef Py_GIL_DISABLED @@ -823,6 +839,20 @@ _Py_TryXGetStackRef(PyObject **src, _PyStackRef *out) } \ } while (0) + +static inline _PyStackRef +PyStackRef_BoxInt(_PyStackRef i) +{ + assert(PyStackRef_IsTaggedInt(i)); + intptr_t val = PyStackRef_UntagInt(i); + PyObject *boxed = PyLong_FromSsize_t(val); + if (boxed == NULL) { + return PyStackRef_ERROR; + } + return PyStackRef_FromPyObjectSteal(boxed); +} + + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 2b845527cf2ed5..b771b56858e8bd 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -116,56 +116,59 @@ extern "C" { #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE -#define _GET_ITER GET_ITER +#define _GET_ITER 376 +#define _GET_ITER_LIST_OR_TUPLE GET_ITER_LIST_OR_TUPLE +#define _GET_ITER_RANGE GET_ITER_RANGE +#define _GET_ITER_SELF GET_ITER_SELF #define _GET_LEN GET_LEN #define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER -#define _GUARD_BINARY_OP_EXTEND 376 -#define _GUARD_CALLABLE_ISINSTANCE 377 -#define _GUARD_CALLABLE_LEN 378 -#define _GUARD_CALLABLE_LIST_APPEND 379 -#define _GUARD_CALLABLE_STR_1 380 -#define _GUARD_CALLABLE_TUPLE_1 381 -#define _GUARD_CALLABLE_TYPE_1 382 -#define _GUARD_DORV_NO_DICT 383 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 384 -#define _GUARD_GLOBALS_VERSION 385 -#define _GUARD_IS_FALSE_POP 386 -#define _GUARD_IS_NONE_POP 387 -#define _GUARD_IS_NOT_NONE_POP 388 -#define _GUARD_IS_TRUE_POP 389 -#define _GUARD_KEYS_VERSION 390 -#define _GUARD_NOS_DICT 391 -#define _GUARD_NOS_FLOAT 392 -#define _GUARD_NOS_INT 393 -#define _GUARD_NOS_LIST 394 -#define _GUARD_NOS_NOT_NULL 395 -#define _GUARD_NOS_NULL 396 -#define _GUARD_NOS_TUPLE 397 -#define _GUARD_NOS_UNICODE 398 -#define _GUARD_NOT_EXHAUSTED_LIST 399 -#define _GUARD_NOT_EXHAUSTED_RANGE 400 -#define _GUARD_NOT_EXHAUSTED_TUPLE 401 -#define _GUARD_THIRD_NULL 402 -#define _GUARD_TOS_ANY_SET 403 -#define _GUARD_TOS_DICT 404 -#define _GUARD_TOS_FLOAT 405 -#define _GUARD_TOS_INT 406 -#define _GUARD_TOS_LIST 407 -#define _GUARD_TOS_SLICE 408 -#define _GUARD_TOS_TUPLE 409 -#define _GUARD_TOS_UNICODE 410 -#define _GUARD_TYPE_VERSION 411 -#define _GUARD_TYPE_VERSION_AND_LOCK 412 +#define _GUARD_BINARY_OP_EXTEND 377 +#define _GUARD_CALLABLE_ISINSTANCE 378 +#define _GUARD_CALLABLE_LEN 379 +#define _GUARD_CALLABLE_LIST_APPEND 380 +#define _GUARD_CALLABLE_STR_1 381 +#define _GUARD_CALLABLE_TUPLE_1 382 +#define _GUARD_CALLABLE_TYPE_1 383 +#define _GUARD_DORV_NO_DICT 384 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 385 +#define _GUARD_GLOBALS_VERSION 386 +#define _GUARD_IS_FALSE_POP 387 +#define _GUARD_IS_NONE_POP 388 +#define _GUARD_IS_NOT_NONE_POP 389 +#define _GUARD_IS_TRUE_POP 390 +#define _GUARD_KEYS_VERSION 391 +#define _GUARD_NOS_DICT 392 +#define _GUARD_NOS_FLOAT 393 +#define _GUARD_NOS_INT 394 +#define _GUARD_NOS_LIST 395 +#define _GUARD_NOS_NOT_NULL 396 +#define _GUARD_NOS_NULL 397 +#define _GUARD_NOS_TUPLE 398 +#define _GUARD_NOS_UNICODE 399 +#define _GUARD_NOT_EXHAUSTED_LIST 400 +#define _GUARD_NOT_EXHAUSTED_RANGE 401 +#define _GUARD_NOT_EXHAUSTED_TUPLE 402 +#define _GUARD_THIRD_NULL 403 +#define _GUARD_TOS_ANY_SET 404 +#define _GUARD_TOS_DICT 405 +#define _GUARD_TOS_FLOAT 406 +#define _GUARD_TOS_INT 407 +#define _GUARD_TOS_LIST 408 +#define _GUARD_TOS_SLICE 409 +#define _GUARD_TOS_TUPLE 410 +#define _GUARD_TOS_UNICODE 411 +#define _GUARD_TYPE_VERSION 412 +#define _GUARD_TYPE_VERSION_AND_LOCK 413 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 413 -#define _INIT_CALL_PY_EXACT_ARGS 414 -#define _INIT_CALL_PY_EXACT_ARGS_0 415 -#define _INIT_CALL_PY_EXACT_ARGS_1 416 -#define _INIT_CALL_PY_EXACT_ARGS_2 417 -#define _INIT_CALL_PY_EXACT_ARGS_3 418 -#define _INIT_CALL_PY_EXACT_ARGS_4 419 -#define _INSERT_NULL 420 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 414 +#define _INIT_CALL_PY_EXACT_ARGS 415 +#define _INIT_CALL_PY_EXACT_ARGS_0 416 +#define _INIT_CALL_PY_EXACT_ARGS_1 417 +#define _INIT_CALL_PY_EXACT_ARGS_2 418 +#define _INIT_CALL_PY_EXACT_ARGS_3 419 +#define _INIT_CALL_PY_EXACT_ARGS_4 420 +#define _INSERT_NULL 421 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -175,171 +178,171 @@ 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 421 +#define _IS_NONE 422 #define _IS_OP IS_OP -#define _ITER_CHECK_LIST 422 -#define _ITER_CHECK_RANGE 423 -#define _ITER_CHECK_TUPLE 424 -#define _ITER_JUMP_LIST 425 -#define _ITER_JUMP_RANGE 426 -#define _ITER_JUMP_TUPLE 427 -#define _ITER_NEXT_LIST 428 -#define _ITER_NEXT_LIST_TIER_TWO 429 -#define _ITER_NEXT_RANGE 430 -#define _ITER_NEXT_TUPLE 431 -#define _JUMP_TO_TOP 432 +#define _ITER_CHECK_LIST 423 +#define _ITER_CHECK_RANGE 424 +#define _ITER_CHECK_TUPLE 425 +#define _ITER_JUMP_LIST 426 +#define _ITER_JUMP_RANGE 427 +#define _ITER_JUMP_TUPLE 428 +#define _ITER_NEXT_LIST 429 +#define _ITER_NEXT_LIST_TIER_TWO 430 +#define _ITER_NEXT_RANGE 431 +#define _ITER_NEXT_TUPLE 432 +#define _JUMP_TO_TOP 433 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 433 -#define _LOAD_ATTR_CLASS 434 +#define _LOAD_ATTR 434 +#define _LOAD_ATTR_CLASS 435 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 435 -#define _LOAD_ATTR_METHOD_LAZY_DICT 436 -#define _LOAD_ATTR_METHOD_NO_DICT 437 -#define _LOAD_ATTR_METHOD_WITH_VALUES 438 -#define _LOAD_ATTR_MODULE 439 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 440 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 441 -#define _LOAD_ATTR_PROPERTY_FRAME 442 -#define _LOAD_ATTR_SLOT 443 -#define _LOAD_ATTR_WITH_HINT 444 +#define _LOAD_ATTR_INSTANCE_VALUE 436 +#define _LOAD_ATTR_METHOD_LAZY_DICT 437 +#define _LOAD_ATTR_METHOD_NO_DICT 438 +#define _LOAD_ATTR_METHOD_WITH_VALUES 439 +#define _LOAD_ATTR_MODULE 440 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 441 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 442 +#define _LOAD_ATTR_PROPERTY_FRAME 443 +#define _LOAD_ATTR_SLOT 444 +#define _LOAD_ATTR_WITH_HINT 445 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 445 +#define _LOAD_BYTECODE 446 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST -#define _LOAD_CONST_INLINE 446 -#define _LOAD_CONST_INLINE_BORROW 447 -#define _LOAD_CONST_UNDER_INLINE 448 -#define _LOAD_CONST_UNDER_INLINE_BORROW 449 +#define _LOAD_CONST_INLINE 447 +#define _LOAD_CONST_INLINE_BORROW 448 +#define _LOAD_CONST_UNDER_INLINE 449 +#define _LOAD_CONST_UNDER_INLINE_BORROW 450 #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 450 -#define _LOAD_FAST_0 451 -#define _LOAD_FAST_1 452 -#define _LOAD_FAST_2 453 -#define _LOAD_FAST_3 454 -#define _LOAD_FAST_4 455 -#define _LOAD_FAST_5 456 -#define _LOAD_FAST_6 457 -#define _LOAD_FAST_7 458 +#define _LOAD_FAST 451 +#define _LOAD_FAST_0 452 +#define _LOAD_FAST_1 453 +#define _LOAD_FAST_2 454 +#define _LOAD_FAST_3 455 +#define _LOAD_FAST_4 456 +#define _LOAD_FAST_5 457 +#define _LOAD_FAST_6 458 +#define _LOAD_FAST_7 459 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 459 -#define _LOAD_FAST_BORROW_0 460 -#define _LOAD_FAST_BORROW_1 461 -#define _LOAD_FAST_BORROW_2 462 -#define _LOAD_FAST_BORROW_3 463 -#define _LOAD_FAST_BORROW_4 464 -#define _LOAD_FAST_BORROW_5 465 -#define _LOAD_FAST_BORROW_6 466 -#define _LOAD_FAST_BORROW_7 467 +#define _LOAD_FAST_BORROW 460 +#define _LOAD_FAST_BORROW_0 461 +#define _LOAD_FAST_BORROW_1 462 +#define _LOAD_FAST_BORROW_2 463 +#define _LOAD_FAST_BORROW_3 464 +#define _LOAD_FAST_BORROW_4 465 +#define _LOAD_FAST_BORROW_5 466 +#define _LOAD_FAST_BORROW_6 467 +#define _LOAD_FAST_BORROW_7 468 #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 468 -#define _LOAD_GLOBAL_BUILTINS 469 -#define _LOAD_GLOBAL_MODULE 470 +#define _LOAD_GLOBAL 469 +#define _LOAD_GLOBAL_BUILTINS 470 +#define _LOAD_GLOBAL_MODULE 471 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 471 -#define _LOAD_SMALL_INT_0 472 -#define _LOAD_SMALL_INT_1 473 -#define _LOAD_SMALL_INT_2 474 -#define _LOAD_SMALL_INT_3 475 -#define _LOAD_SPECIAL 476 +#define _LOAD_SMALL_INT 472 +#define _LOAD_SMALL_INT_0 473 +#define _LOAD_SMALL_INT_1 474 +#define _LOAD_SMALL_INT_2 475 +#define _LOAD_SMALL_INT_3 476 +#define _LOAD_SPECIAL 477 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 477 +#define _MAKE_CALLARGS_A_TUPLE 478 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 478 +#define _MAKE_WARM 479 #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 479 -#define _MAYBE_EXPAND_METHOD_KW 480 -#define _MONITOR_CALL 481 -#define _MONITOR_CALL_KW 482 -#define _MONITOR_JUMP_BACKWARD 483 -#define _MONITOR_RESUME 484 +#define _MAYBE_EXPAND_METHOD 480 +#define _MAYBE_EXPAND_METHOD_KW 481 +#define _MONITOR_CALL 482 +#define _MONITOR_CALL_KW 483 +#define _MONITOR_JUMP_BACKWARD 484 +#define _MONITOR_RESUME 485 #define _NOP NOP -#define _POP_CALL 485 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW 486 -#define _POP_CALL_ONE 487 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 488 -#define _POP_CALL_TWO 489 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 490 +#define _POP_CALL 486 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 487 +#define _POP_CALL_ONE 488 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 489 +#define _POP_CALL_TWO 490 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 491 #define _POP_EXCEPT POP_EXCEPT #define _POP_ITER POP_ITER -#define _POP_JUMP_IF_FALSE 491 -#define _POP_JUMP_IF_TRUE 492 +#define _POP_JUMP_IF_FALSE 492 +#define _POP_JUMP_IF_TRUE 493 #define _POP_TOP POP_TOP -#define _POP_TOP_LOAD_CONST_INLINE 493 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 494 -#define _POP_TWO 495 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 496 +#define _POP_TOP_LOAD_CONST_INLINE 494 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 495 +#define _POP_TWO 496 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 497 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 497 +#define _PUSH_FRAME 498 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 498 -#define _PY_FRAME_GENERAL 499 -#define _PY_FRAME_KW 500 -#define _QUICKEN_RESUME 501 -#define _REPLACE_WITH_TRUE 502 +#define _PUSH_NULL_CONDITIONAL 499 +#define _PY_FRAME_GENERAL 500 +#define _PY_FRAME_KW 501 +#define _QUICKEN_RESUME 502 +#define _REPLACE_WITH_TRUE 503 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 503 -#define _SEND 504 -#define _SEND_GEN_FRAME 505 +#define _SAVE_RETURN_OFFSET 504 +#define _SEND 505 +#define _SEND_GEN_FRAME 506 #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 506 -#define _STORE_ATTR 507 -#define _STORE_ATTR_INSTANCE_VALUE 508 -#define _STORE_ATTR_SLOT 509 -#define _STORE_ATTR_WITH_HINT 510 +#define _START_EXECUTOR 507 +#define _STORE_ATTR 508 +#define _STORE_ATTR_INSTANCE_VALUE 509 +#define _STORE_ATTR_SLOT 510 +#define _STORE_ATTR_WITH_HINT 511 #define _STORE_DEREF STORE_DEREF -#define _STORE_FAST 511 -#define _STORE_FAST_0 512 -#define _STORE_FAST_1 513 -#define _STORE_FAST_2 514 -#define _STORE_FAST_3 515 -#define _STORE_FAST_4 516 -#define _STORE_FAST_5 517 -#define _STORE_FAST_6 518 -#define _STORE_FAST_7 519 +#define _STORE_FAST 512 +#define _STORE_FAST_0 513 +#define _STORE_FAST_1 514 +#define _STORE_FAST_2 515 +#define _STORE_FAST_3 516 +#define _STORE_FAST_4 517 +#define _STORE_FAST_5 518 +#define _STORE_FAST_6 519 +#define _STORE_FAST_7 520 #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 520 -#define _STORE_SUBSCR 521 -#define _STORE_SUBSCR_DICT 522 -#define _STORE_SUBSCR_LIST_INT 523 +#define _STORE_SLICE 521 +#define _STORE_SUBSCR 522 +#define _STORE_SUBSCR_DICT 523 +#define _STORE_SUBSCR_LIST_INT 524 #define _SWAP SWAP -#define _TIER2_RESUME_CHECK 524 -#define _TO_BOOL 525 +#define _TIER2_RESUME_CHECK 525 +#define _TO_BOOL 526 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 526 +#define _TO_BOOL_LIST 527 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 527 +#define _TO_BOOL_STR 528 #define _UNARY_INVERT UNARY_INVERT #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 528 -#define _UNPACK_SEQUENCE_LIST 529 -#define _UNPACK_SEQUENCE_TUPLE 530 -#define _UNPACK_SEQUENCE_TWO_TUPLE 531 +#define _UNPACK_SEQUENCE 529 +#define _UNPACK_SEQUENCE_LIST 530 +#define _UNPACK_SEQUENCE_TUPLE 531 +#define _UNPACK_SEQUENCE_TWO_TUPLE 532 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 531 +#define MAX_UOP_ID 532 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index b08909e72c4f43..45e2d5bb60cb56 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -202,6 +202,9 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_MATCH_SEQUENCE] = 0, [_MATCH_KEYS] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_GET_ITER] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_GET_ITER_SELF] = HAS_DEOPT_FLAG, + [_GET_ITER_LIST_OR_TUPLE] = HAS_DEOPT_FLAG, + [_GET_ITER_RANGE] = HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG, [_GET_YIELD_FROM_ITER] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_FOR_ITER_TIER_TWO] = HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_ITER_CHECK_LIST] = HAS_EXIT_FLAG, @@ -212,7 +215,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_ITER_NEXT_TUPLE] = 0, [_ITER_CHECK_RANGE] = HAS_EXIT_FLAG, [_GUARD_NOT_EXHAUSTED_RANGE] = HAS_EXIT_FLAG, - [_ITER_NEXT_RANGE] = HAS_ERROR_FLAG, + [_ITER_NEXT_RANGE] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG, [_FOR_ITER_GEN_FRAME] = HAS_ARG_FLAG | HAS_DEOPT_FLAG, [_INSERT_NULL] = 0, [_LOAD_SPECIAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, @@ -435,6 +438,9 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { [_GET_ANEXT] = "_GET_ANEXT", [_GET_AWAITABLE] = "_GET_AWAITABLE", [_GET_ITER] = "_GET_ITER", + [_GET_ITER_LIST_OR_TUPLE] = "_GET_ITER_LIST_OR_TUPLE", + [_GET_ITER_RANGE] = "_GET_ITER_RANGE", + [_GET_ITER_SELF] = "_GET_ITER_SELF", [_GET_LEN] = "_GET_LEN", [_GET_YIELD_FROM_ITER] = "_GET_YIELD_FROM_ITER", [_GUARD_BINARY_OP_EXTEND] = "_GUARD_BINARY_OP_EXTEND", @@ -1004,6 +1010,12 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _GET_ITER: return 1; + case _GET_ITER_SELF: + return 0; + case _GET_ITER_LIST_OR_TUPLE: + return 0; + case _GET_ITER_RANGE: + return 1; case _GET_YIELD_FROM_ITER: return 1; case _FOR_ITER_TIER_TWO: diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index 1d5c74adefcd35..1a2c1754ad7e13 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -178,41 +178,44 @@ extern "C" { #define FOR_ITER_LIST 172 #define FOR_ITER_RANGE 173 #define FOR_ITER_TUPLE 174 -#define JUMP_BACKWARD_JIT 175 -#define JUMP_BACKWARD_NO_JIT 176 -#define LOAD_ATTR_CLASS 177 -#define LOAD_ATTR_CLASS_WITH_METACLASS_CHECK 178 -#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 179 -#define LOAD_ATTR_INSTANCE_VALUE 180 -#define LOAD_ATTR_METHOD_LAZY_DICT 181 -#define LOAD_ATTR_METHOD_NO_DICT 182 -#define LOAD_ATTR_METHOD_WITH_VALUES 183 -#define LOAD_ATTR_MODULE 184 -#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 185 -#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 186 -#define LOAD_ATTR_PROPERTY 187 -#define LOAD_ATTR_SLOT 188 -#define LOAD_ATTR_WITH_HINT 189 -#define LOAD_GLOBAL_BUILTIN 190 -#define LOAD_GLOBAL_MODULE 191 -#define LOAD_SUPER_ATTR_ATTR 192 -#define LOAD_SUPER_ATTR_METHOD 193 -#define RESUME_CHECK 194 -#define SEND_GEN 195 -#define STORE_ATTR_INSTANCE_VALUE 196 -#define STORE_ATTR_SLOT 197 -#define STORE_ATTR_WITH_HINT 198 -#define STORE_SUBSCR_DICT 199 -#define STORE_SUBSCR_LIST_INT 200 -#define TO_BOOL_ALWAYS_TRUE 201 -#define TO_BOOL_BOOL 202 -#define TO_BOOL_INT 203 -#define TO_BOOL_LIST 204 -#define TO_BOOL_NONE 205 -#define TO_BOOL_STR 206 -#define UNPACK_SEQUENCE_LIST 207 -#define UNPACK_SEQUENCE_TUPLE 208 -#define UNPACK_SEQUENCE_TWO_TUPLE 209 +#define GET_ITER_LIST_OR_TUPLE 175 +#define GET_ITER_RANGE 176 +#define GET_ITER_SELF 177 +#define JUMP_BACKWARD_JIT 178 +#define JUMP_BACKWARD_NO_JIT 179 +#define LOAD_ATTR_CLASS 180 +#define LOAD_ATTR_CLASS_WITH_METACLASS_CHECK 181 +#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 182 +#define LOAD_ATTR_INSTANCE_VALUE 183 +#define LOAD_ATTR_METHOD_LAZY_DICT 184 +#define LOAD_ATTR_METHOD_NO_DICT 185 +#define LOAD_ATTR_METHOD_WITH_VALUES 186 +#define LOAD_ATTR_MODULE 187 +#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 188 +#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 189 +#define LOAD_ATTR_PROPERTY 190 +#define LOAD_ATTR_SLOT 191 +#define LOAD_ATTR_WITH_HINT 192 +#define LOAD_GLOBAL_BUILTIN 193 +#define LOAD_GLOBAL_MODULE 194 +#define LOAD_SUPER_ATTR_ATTR 195 +#define LOAD_SUPER_ATTR_METHOD 196 +#define RESUME_CHECK 197 +#define SEND_GEN 198 +#define STORE_ATTR_INSTANCE_VALUE 199 +#define STORE_ATTR_SLOT 200 +#define STORE_ATTR_WITH_HINT 201 +#define STORE_SUBSCR_DICT 202 +#define STORE_SUBSCR_LIST_INT 203 +#define TO_BOOL_ALWAYS_TRUE 204 +#define TO_BOOL_BOOL 205 +#define TO_BOOL_INT 206 +#define TO_BOOL_LIST 207 +#define TO_BOOL_NONE 208 +#define TO_BOOL_STR 209 +#define UNPACK_SEQUENCE_LIST 210 +#define UNPACK_SEQUENCE_TUPLE 211 +#define UNPACK_SEQUENCE_TWO_TUPLE 212 #define INSTRUMENTED_END_FOR 234 #define INSTRUMENTED_POP_ITER 235 #define INSTRUMENTED_END_SEND 236 diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index f168d169a32948..78cf06d73db5c4 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -84,6 +84,11 @@ "JUMP_BACKWARD_NO_JIT", "JUMP_BACKWARD_JIT", ], + "GET_ITER": [ + "GET_ITER_LIST_OR_TUPLE", + "GET_ITER_SELF", + "GET_ITER_RANGE", + ], "FOR_ITER": [ "FOR_ITER_LIST", "FOR_ITER_TUPLE", @@ -167,41 +172,44 @@ 'FOR_ITER_LIST': 172, 'FOR_ITER_RANGE': 173, 'FOR_ITER_TUPLE': 174, - 'JUMP_BACKWARD_JIT': 175, - 'JUMP_BACKWARD_NO_JIT': 176, - 'LOAD_ATTR_CLASS': 177, - 'LOAD_ATTR_CLASS_WITH_METACLASS_CHECK': 178, - 'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 179, - 'LOAD_ATTR_INSTANCE_VALUE': 180, - 'LOAD_ATTR_METHOD_LAZY_DICT': 181, - 'LOAD_ATTR_METHOD_NO_DICT': 182, - 'LOAD_ATTR_METHOD_WITH_VALUES': 183, - 'LOAD_ATTR_MODULE': 184, - 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 185, - 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 186, - 'LOAD_ATTR_PROPERTY': 187, - 'LOAD_ATTR_SLOT': 188, - 'LOAD_ATTR_WITH_HINT': 189, - 'LOAD_GLOBAL_BUILTIN': 190, - 'LOAD_GLOBAL_MODULE': 191, - 'LOAD_SUPER_ATTR_ATTR': 192, - 'LOAD_SUPER_ATTR_METHOD': 193, - 'RESUME_CHECK': 194, - 'SEND_GEN': 195, - 'STORE_ATTR_INSTANCE_VALUE': 196, - 'STORE_ATTR_SLOT': 197, - 'STORE_ATTR_WITH_HINT': 198, - 'STORE_SUBSCR_DICT': 199, - 'STORE_SUBSCR_LIST_INT': 200, - 'TO_BOOL_ALWAYS_TRUE': 201, - 'TO_BOOL_BOOL': 202, - 'TO_BOOL_INT': 203, - 'TO_BOOL_LIST': 204, - 'TO_BOOL_NONE': 205, - 'TO_BOOL_STR': 206, - 'UNPACK_SEQUENCE_LIST': 207, - 'UNPACK_SEQUENCE_TUPLE': 208, - 'UNPACK_SEQUENCE_TWO_TUPLE': 209, + 'GET_ITER_LIST_OR_TUPLE': 175, + 'GET_ITER_RANGE': 176, + 'GET_ITER_SELF': 177, + 'JUMP_BACKWARD_JIT': 178, + 'JUMP_BACKWARD_NO_JIT': 179, + 'LOAD_ATTR_CLASS': 180, + 'LOAD_ATTR_CLASS_WITH_METACLASS_CHECK': 181, + 'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 182, + 'LOAD_ATTR_INSTANCE_VALUE': 183, + 'LOAD_ATTR_METHOD_LAZY_DICT': 184, + 'LOAD_ATTR_METHOD_NO_DICT': 185, + 'LOAD_ATTR_METHOD_WITH_VALUES': 186, + 'LOAD_ATTR_MODULE': 187, + 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 188, + 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 189, + 'LOAD_ATTR_PROPERTY': 190, + 'LOAD_ATTR_SLOT': 191, + 'LOAD_ATTR_WITH_HINT': 192, + 'LOAD_GLOBAL_BUILTIN': 193, + 'LOAD_GLOBAL_MODULE': 194, + 'LOAD_SUPER_ATTR_ATTR': 195, + 'LOAD_SUPER_ATTR_METHOD': 196, + 'RESUME_CHECK': 197, + 'SEND_GEN': 198, + 'STORE_ATTR_INSTANCE_VALUE': 199, + 'STORE_ATTR_SLOT': 200, + 'STORE_ATTR_WITH_HINT': 201, + 'STORE_SUBSCR_DICT': 202, + 'STORE_SUBSCR_LIST_INT': 203, + 'TO_BOOL_ALWAYS_TRUE': 204, + 'TO_BOOL_BOOL': 205, + 'TO_BOOL_INT': 206, + 'TO_BOOL_LIST': 207, + 'TO_BOOL_NONE': 208, + 'TO_BOOL_STR': 209, + 'UNPACK_SEQUENCE_LIST': 210, + 'UNPACK_SEQUENCE_TUPLE': 211, + 'UNPACK_SEQUENCE_TWO_TUPLE': 212, } opmap = { diff --git a/Lib/opcode.py b/Lib/opcode.py index 0e9520b6832499..ecce6d1ac2702a 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -68,6 +68,9 @@ "FOR_ITER": { "counter": 1, }, + "GET_ITER": { + "counter": 1, + }, "LOAD_SUPER_ATTR": { "counter": 1, }, diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 355990ed58ee09..f34504dd4f8c85 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -906,7 +906,7 @@ def loop_test(): LIST_EXTEND 1 LOAD_SMALL_INT 3 BINARY_OP 5 (*) - GET_ITER + GET_ITER_LIST_OR_TUPLE L1: FOR_ITER_LIST 14 (to L2) STORE_FAST 0 (i) @@ -1404,7 +1404,7 @@ def test_show_caches(self): caches = list(self.get_cached_values(quickened, adaptive)) for cache in caches: self.assertRegex(cache, pattern) - total_caches = 21 + total_caches = 22 empty_caches = 7 self.assertEqual(caches.count(""), empty_caches) self.assertEqual(len(caches), total_caches) @@ -1820,131 +1820,131 @@ def _prepare_test_cases(): make_inst(opname='LOAD_GLOBAL', arg=1, argval='range', argrepr='range + NULL', offset=2, start_offset=2, starts_line=True, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), make_inst(opname='LOAD_SMALL_INT', arg=10, argval=10, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=3), make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='GET_ITER', arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3), - make_inst(opname='FOR_ITER', arg=33, argval=94, argrepr='to L4', offset=24, start_offset=24, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=28, start_offset=28, starts_line=False, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=40, start_offset=40, starts_line=False, line_number=4), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=4), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=52, start_offset=52, starts_line=True, line_number=5), - make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=54, start_offset=54, starts_line=False, line_number=5), - make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=56, start_offset=56, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=70, argrepr='to L2', offset=60, start_offset=60, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=64, start_offset=64, starts_line=False, line_number=5), - make_inst(opname='JUMP_BACKWARD', arg=23, argval=24, argrepr='to L1', offset=66, start_offset=66, starts_line=True, line_number=6, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=70, start_offset=70, starts_line=True, line_number=7, label=2), - make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=72, start_offset=72, starts_line=False, line_number=7), - make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=74, start_offset=74, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=88, argrepr='to L3', offset=78, start_offset=78, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=82, start_offset=82, starts_line=False, line_number=7), - make_inst(opname='JUMP_BACKWARD', arg=32, argval=24, argrepr='to L1', offset=84, start_offset=84, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=88, start_offset=88, starts_line=True, line_number=8, label=3), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=False, line_number=8), - make_inst(opname='JUMP_FORWARD', arg=13, argval=120, argrepr='to L5', offset=92, start_offset=92, starts_line=False, line_number=8), - make_inst(opname='END_FOR', arg=None, argval=None, argrepr='', offset=94, start_offset=94, starts_line=True, line_number=3, label=4), - make_inst(opname='POP_ITER', arg=None, argval=None, argrepr='', offset=96, start_offset=96, starts_line=False, line_number=3), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=98, start_offset=98, starts_line=True, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=108, start_offset=108, starts_line=False, line_number=10), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=110, start_offset=110, starts_line=False, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=118, start_offset=118, starts_line=False, line_number=10), - make_inst(opname='LOAD_FAST_CHECK', arg=0, argval='i', argrepr='i', offset=120, start_offset=120, starts_line=True, line_number=11, label=5), - make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=122, start_offset=122, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=40, argval=214, argrepr='to L8', offset=130, start_offset=130, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=134, start_offset=134, starts_line=False, line_number=11), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=136, start_offset=136, starts_line=True, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=146, start_offset=146, starts_line=False, line_number=12), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=148, start_offset=148, starts_line=False, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=156, start_offset=156, starts_line=False, line_number=12), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=158, start_offset=158, starts_line=True, line_number=13), - make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=160, start_offset=160, starts_line=False, line_number=13), - make_inst(opname='BINARY_OP', arg=23, argval=23, argrepr='-=', offset=162, start_offset=162, starts_line=False, line_number=13, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), - make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=174, start_offset=174, starts_line=False, line_number=13), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=176, start_offset=176, starts_line=True, line_number=14), - make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=178, start_offset=178, starts_line=False, line_number=14), - make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=180, start_offset=180, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=194, argrepr='to L6', offset=184, start_offset=184, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=188, start_offset=188, starts_line=False, line_number=14), - make_inst(opname='JUMP_BACKWARD', arg=37, argval=120, argrepr='to L5', offset=190, start_offset=190, starts_line=True, line_number=15, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=194, start_offset=194, starts_line=True, line_number=16, label=6), - make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=196, start_offset=196, starts_line=False, line_number=16), - make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=198, start_offset=198, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=212, argrepr='to L7', offset=202, start_offset=202, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=206, start_offset=206, starts_line=False, line_number=16), - make_inst(opname='JUMP_BACKWARD', arg=46, argval=120, argrepr='to L5', offset=208, start_offset=208, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='JUMP_FORWARD', arg=11, argval=236, argrepr='to L9', offset=212, start_offset=212, starts_line=True, line_number=17, label=7), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=214, start_offset=214, starts_line=True, line_number=19, label=8, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=224, start_offset=224, starts_line=False, line_number=19), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=226, start_offset=226, starts_line=False, line_number=19, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=234, start_offset=234, starts_line=False, line_number=19), - make_inst(opname='NOP', arg=None, argval=None, argrepr='', offset=236, start_offset=236, starts_line=True, line_number=20, label=9), - make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=238, start_offset=238, starts_line=True, line_number=21), - make_inst(opname='LOAD_SMALL_INT', arg=0, argval=0, argrepr='', offset=240, start_offset=240, starts_line=False, line_number=21), - make_inst(opname='BINARY_OP', arg=11, argval=11, argrepr='/', offset=242, start_offset=242, starts_line=False, line_number=21, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=254, start_offset=254, starts_line=False, line_number=21), - make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=256, start_offset=256, starts_line=True, line_number=25), - make_inst(opname='COPY', arg=1, argval=1, argrepr='', offset=258, start_offset=258, starts_line=False, line_number=25), - make_inst(opname='LOAD_SPECIAL', arg=1, argval=1, argrepr='__exit__', offset=260, start_offset=260, starts_line=False, line_number=25), - make_inst(opname='SWAP', arg=2, argval=2, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=25), - make_inst(opname='SWAP', arg=3, argval=3, argrepr='', offset=264, start_offset=264, starts_line=False, line_number=25), - make_inst(opname='LOAD_SPECIAL', arg=0, argval=0, argrepr='__enter__', offset=266, start_offset=266, starts_line=False, line_number=25), - make_inst(opname='CALL', arg=0, argval=0, argrepr='', offset=268, start_offset=268, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='STORE_FAST', arg=1, argval='dodgy', argrepr='dodgy', offset=276, start_offset=276, starts_line=False, line_number=25), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=278, start_offset=278, starts_line=True, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=288, start_offset=288, starts_line=False, line_number=26), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=290, start_offset=290, starts_line=False, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=298, start_offset=298, starts_line=False, line_number=26), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=300, start_offset=300, starts_line=True, line_number=25), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=302, start_offset=302, starts_line=False, line_number=25), + make_inst(opname='GET_ITER', arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='FOR_ITER', arg=33, argval=96, argrepr='to L4', offset=26, start_offset=26, starts_line=False, line_number=3, label=1, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=30, start_offset=30, starts_line=False, line_number=3), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=32, start_offset=32, starts_line=True, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=42, start_offset=42, starts_line=False, line_number=4), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=4, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=52, start_offset=52, starts_line=False, line_number=4), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=54, start_offset=54, starts_line=True, line_number=5), + make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=5), + make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=58, start_offset=58, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=72, argrepr='to L2', offset=62, start_offset=62, starts_line=False, line_number=5, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=66, start_offset=66, starts_line=False, line_number=5), + make_inst(opname='JUMP_BACKWARD', arg=23, argval=26, argrepr='to L1', offset=68, start_offset=68, starts_line=True, line_number=6, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=72, start_offset=72, starts_line=True, line_number=7, label=2), + make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=74, start_offset=74, starts_line=False, line_number=7), + make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=76, start_offset=76, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=90, argrepr='to L3', offset=80, start_offset=80, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=84, start_offset=84, starts_line=False, line_number=7), + make_inst(opname='JUMP_BACKWARD', arg=32, argval=26, argrepr='to L1', offset=86, start_offset=86, starts_line=False, line_number=7, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=True, line_number=8, label=3), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=92, start_offset=92, starts_line=False, line_number=8), + make_inst(opname='JUMP_FORWARD', arg=13, argval=122, argrepr='to L5', offset=94, start_offset=94, starts_line=False, line_number=8), + make_inst(opname='END_FOR', arg=None, argval=None, argrepr='', offset=96, start_offset=96, starts_line=True, line_number=3, label=4), + make_inst(opname='POP_ITER', arg=None, argval=None, argrepr='', offset=98, start_offset=98, starts_line=False, line_number=3), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=100, start_offset=100, starts_line=True, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=110, start_offset=110, starts_line=False, line_number=10), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=112, start_offset=112, starts_line=False, line_number=10, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=120, start_offset=120, starts_line=False, line_number=10), + make_inst(opname='LOAD_FAST_CHECK', arg=0, argval='i', argrepr='i', offset=122, start_offset=122, starts_line=True, line_number=11, label=5), + make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=124, start_offset=124, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=40, argval=216, argrepr='to L8', offset=132, start_offset=132, starts_line=False, line_number=11, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=136, start_offset=136, starts_line=False, line_number=11), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=138, start_offset=138, starts_line=True, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=148, start_offset=148, starts_line=False, line_number=12), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=150, start_offset=150, starts_line=False, line_number=12, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=158, start_offset=158, starts_line=False, line_number=12), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=160, start_offset=160, starts_line=True, line_number=13), + make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=162, start_offset=162, starts_line=False, line_number=13), + make_inst(opname='BINARY_OP', arg=23, argval=23, argrepr='-=', offset=164, start_offset=164, starts_line=False, line_number=13, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + make_inst(opname='STORE_FAST', arg=0, argval='i', argrepr='i', offset=176, start_offset=176, starts_line=False, line_number=13), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=178, start_offset=178, starts_line=True, line_number=14), + make_inst(opname='LOAD_SMALL_INT', arg=6, argval=6, argrepr='', offset=180, start_offset=180, starts_line=False, line_number=14), + make_inst(opname='COMPARE_OP', arg=148, argval='>', argrepr='bool(>)', offset=182, start_offset=182, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_FALSE', arg=3, argval=196, argrepr='to L6', offset=186, start_offset=186, starts_line=False, line_number=14, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=190, start_offset=190, starts_line=False, line_number=14), + make_inst(opname='JUMP_BACKWARD', arg=37, argval=122, argrepr='to L5', offset=192, start_offset=192, starts_line=True, line_number=15, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=196, start_offset=196, starts_line=True, line_number=16, label=6), + make_inst(opname='LOAD_SMALL_INT', arg=4, argval=4, argrepr='', offset=198, start_offset=198, starts_line=False, line_number=16), + make_inst(opname='COMPARE_OP', arg=18, argval='<', argrepr='bool(<)', offset=200, start_offset=200, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=3, argval=214, argrepr='to L7', offset=204, start_offset=204, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=208, start_offset=208, starts_line=False, line_number=16), + make_inst(opname='JUMP_BACKWARD', arg=46, argval=122, argrepr='to L5', offset=210, start_offset=210, starts_line=False, line_number=16, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='JUMP_FORWARD', arg=11, argval=238, argrepr='to L9', offset=214, start_offset=214, starts_line=True, line_number=17, label=7), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=216, start_offset=216, starts_line=True, line_number=19, label=8, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=226, start_offset=226, starts_line=False, line_number=19), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=228, start_offset=228, starts_line=False, line_number=19, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=236, start_offset=236, starts_line=False, line_number=19), + make_inst(opname='NOP', arg=None, argval=None, argrepr='', offset=238, start_offset=238, starts_line=True, line_number=20, label=9), + make_inst(opname='LOAD_SMALL_INT', arg=1, argval=1, argrepr='', offset=240, start_offset=240, starts_line=True, line_number=21), + make_inst(opname='LOAD_SMALL_INT', arg=0, argval=0, argrepr='', offset=242, start_offset=242, starts_line=False, line_number=21), + make_inst(opname='BINARY_OP', arg=11, argval=11, argrepr='/', offset=244, start_offset=244, starts_line=False, line_number=21, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=256, start_offset=256, starts_line=False, line_number=21), + make_inst(opname='LOAD_FAST_BORROW', arg=0, argval='i', argrepr='i', offset=258, start_offset=258, starts_line=True, line_number=25), + make_inst(opname='COPY', arg=1, argval=1, argrepr='', offset=260, start_offset=260, starts_line=False, line_number=25), + make_inst(opname='LOAD_SPECIAL', arg=1, argval=1, argrepr='__exit__', offset=262, start_offset=262, starts_line=False, line_number=25), + make_inst(opname='SWAP', arg=2, argval=2, argrepr='', offset=264, start_offset=264, starts_line=False, line_number=25), + make_inst(opname='SWAP', arg=3, argval=3, argrepr='', offset=266, start_offset=266, starts_line=False, line_number=25), + make_inst(opname='LOAD_SPECIAL', arg=0, argval=0, argrepr='__enter__', offset=268, start_offset=268, starts_line=False, line_number=25), + make_inst(opname='CALL', arg=0, argval=0, argrepr='', offset=270, start_offset=270, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='STORE_FAST', arg=1, argval='dodgy', argrepr='dodgy', offset=278, start_offset=278, starts_line=False, line_number=25), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=280, start_offset=280, starts_line=True, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=290, start_offset=290, starts_line=False, line_number=26), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=292, start_offset=292, starts_line=False, line_number=26, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=300, start_offset=300, starts_line=False, line_number=26), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=302, start_offset=302, starts_line=True, line_number=25), make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=304, start_offset=304, starts_line=False, line_number=25), - make_inst(opname='CALL', arg=3, argval=3, argrepr='', offset=306, start_offset=306, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=314, start_offset=314, starts_line=False, line_number=25), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=316, start_offset=316, starts_line=True, line_number=28, label=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=326, start_offset=326, starts_line=False, line_number=28), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=328, start_offset=328, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=336, start_offset=336, starts_line=False, line_number=28), - make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=338, start_offset=338, starts_line=False, line_number=28), - make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=340, start_offset=340, starts_line=False, line_number=28), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=True, line_number=25), - make_inst(opname='WITH_EXCEPT_START', arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=False, line_number=25), - make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_JUMP_IF_TRUE', arg=2, argval=362, argrepr='to L11', offset=354, start_offset=354, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=358, start_offset=358, starts_line=False, line_number=25), - make_inst(opname='RERAISE', arg=2, argval=2, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=25), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25, label=11), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=306, start_offset=306, starts_line=False, line_number=25), + make_inst(opname='CALL', arg=3, argval=3, argrepr='', offset=308, start_offset=308, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=316, start_offset=316, starts_line=False, line_number=25), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=318, start_offset=318, starts_line=True, line_number=28, label=10, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=328, start_offset=328, starts_line=False, line_number=28), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=330, start_offset=330, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=338, start_offset=338, starts_line=False, line_number=28), + make_inst(opname='LOAD_CONST', arg=4, argval=None, argrepr='None', offset=340, start_offset=340, starts_line=False, line_number=28), + make_inst(opname='RETURN_VALUE', arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=False, line_number=28), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=344, start_offset=344, starts_line=True, line_number=25), + make_inst(opname='WITH_EXCEPT_START', arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=False, line_number=25), + make_inst(opname='TO_BOOL', arg=None, argval=None, argrepr='', offset=348, start_offset=348, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_JUMP_IF_TRUE', arg=2, argval=364, argrepr='to L11', offset=356, start_offset=356, starts_line=False, line_number=25, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=25), + make_inst(opname='RERAISE', arg=2, argval=2, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=25), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25, label=11), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25), make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=25), make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=370, start_offset=370, starts_line=False, line_number=25), - make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=29, argval=316, argrepr='to L10', offset=372, start_offset=372, starts_line=False, line_number=25), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=374, start_offset=374, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=376, start_offset=376, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=None), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=None), - make_inst(opname='LOAD_GLOBAL', arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=382, start_offset=382, starts_line=True, line_number=22, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='CHECK_EXC_MATCH', arg=None, argval=None, argrepr='', offset=392, start_offset=392, starts_line=False, line_number=22), - make_inst(opname='POP_JUMP_IF_FALSE', arg=15, argval=428, argrepr='to L12', offset=394, start_offset=394, starts_line=False, line_number=22, cache_info=[('counter', 1, b'\x00\x00')]), - make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=398, start_offset=398, starts_line=False, line_number=22), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=400, start_offset=400, starts_line=False, line_number=22), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=402, start_offset=402, starts_line=True, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=5, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=412, start_offset=412, starts_line=False, line_number=23), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=414, start_offset=414, starts_line=False, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=422, start_offset=422, starts_line=False, line_number=23), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=424, start_offset=424, starts_line=False, line_number=23), - make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=56, argval=316, argrepr='to L10', offset=426, start_offset=426, starts_line=False, line_number=23), - make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=428, start_offset=428, starts_line=True, line_number=22, label=12), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=430, start_offset=430, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=432, start_offset=432, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None), - make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=436, start_offset=436, starts_line=False, line_number=None), - make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=438, start_offset=438, starts_line=True, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), - make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=448, start_offset=448, starts_line=False, line_number=28), - make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=450, start_offset=450, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=458, start_offset=458, starts_line=False, line_number=28), - make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=460, start_offset=460, starts_line=False, line_number=28), - make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=462, start_offset=462, starts_line=True, line_number=None), - make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=464, start_offset=464, starts_line=False, line_number=None), - make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=466, start_offset=466, starts_line=False, line_number=None), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=372, start_offset=372, starts_line=False, line_number=25), + make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=29, argval=318, argrepr='to L10', offset=374, start_offset=374, starts_line=False, line_number=25), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=376, start_offset=376, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=None), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=382, start_offset=382, starts_line=False, line_number=None), + make_inst(opname='LOAD_GLOBAL', arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=384, start_offset=384, starts_line=True, line_number=22, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='CHECK_EXC_MATCH', arg=None, argval=None, argrepr='', offset=394, start_offset=394, starts_line=False, line_number=22), + make_inst(opname='POP_JUMP_IF_FALSE', arg=15, argval=430, argrepr='to L12', offset=396, start_offset=396, starts_line=False, line_number=22, cache_info=[('counter', 1, b'\x00\x00')]), + make_inst(opname='NOT_TAKEN', arg=None, argval=None, argrepr='', offset=400, start_offset=400, starts_line=False, line_number=22), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=402, start_offset=402, starts_line=False, line_number=22), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=404, start_offset=404, starts_line=True, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=5, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=414, start_offset=414, starts_line=False, line_number=23), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=416, start_offset=416, starts_line=False, line_number=23, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=424, start_offset=424, starts_line=False, line_number=23), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=426, start_offset=426, starts_line=False, line_number=23), + make_inst(opname='JUMP_BACKWARD_NO_INTERRUPT', arg=56, argval=318, argrepr='to L10', offset=428, start_offset=428, starts_line=False, line_number=23), + make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=430, start_offset=430, starts_line=True, line_number=22, label=12), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=432, start_offset=432, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=436, start_offset=436, starts_line=False, line_number=None), + make_inst(opname='PUSH_EXC_INFO', arg=None, argval=None, argrepr='', offset=438, start_offset=438, starts_line=False, line_number=None), + make_inst(opname='LOAD_GLOBAL', arg=3, argval='print', argrepr='print + NULL', offset=440, start_offset=440, starts_line=True, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), + make_inst(opname='LOAD_CONST', arg=6, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=450, start_offset=450, starts_line=False, line_number=28), + make_inst(opname='CALL', arg=1, argval=1, argrepr='', offset=452, start_offset=452, starts_line=False, line_number=28, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + make_inst(opname='POP_TOP', arg=None, argval=None, argrepr='', offset=460, start_offset=460, starts_line=False, line_number=28), + make_inst(opname='RERAISE', arg=0, argval=0, argrepr='', offset=462, start_offset=462, starts_line=False, line_number=28), + make_inst(opname='COPY', arg=3, argval=3, argrepr='', offset=464, start_offset=464, starts_line=True, line_number=None), + make_inst(opname='POP_EXCEPT', arg=None, argval=None, argrepr='', offset=466, start_offset=466, starts_line=False, line_number=None), + make_inst(opname='RERAISE', arg=1, argval=1, argrepr='', offset=468, start_offset=468, starts_line=False, line_number=None), ] # One last piece of inspect fodder to check the default line number handling diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index a932ac80117d27..35d3fe46a1b8bd 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1589,11 +1589,11 @@ def whilefunc(n=0): ('branch right', 'whilefunc', 1, 3)]) self.check_events(func, recorders = BRANCH_OFFSET_RECORDERS, expected = [ - ('branch left', 'func', 28, 32), - ('branch right', 'func', 44, 58), - ('branch left', 'func', 28, 32), - ('branch left', 'func', 44, 50), - ('branch right', 'func', 28, 70)]) + ('branch left', 'func', 30, 34), + ('branch right', 'func', 46, 60), + ('branch left', 'func', 30, 34), + ('branch left', 'func', 46, 52), + ('branch right', 'func', 30, 72)]) def test_except_star(self): diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py index 30baa09048616c..915b9ba139e636 100644 --- a/Lib/test/test_opcache.py +++ b/Lib/test/test_opcache.py @@ -1832,23 +1832,101 @@ def for_iter_tuple(): self.assert_specialized(for_iter_tuple, "FOR_ITER_TUPLE") self.assert_no_opcode(for_iter_tuple, "FOR_ITER") + def for_iter_generator(): + for i in (i for i in range(10)): + i + 1 + + for_iter_generator() + self.assert_specialized(for_iter_generator, "FOR_ITER_GEN") + self.assert_no_opcode(for_iter_generator, "FOR_ITER") + + @cpython_only + @requires_specialization_ft + def test_for_iter_range(self): r = range(10) - def for_iter_range(): + def for_iter1(): for i in r: self.assertIn(i, r) - for_iter_range() - self.assert_specialized(for_iter_range, "FOR_ITER_RANGE") - self.assert_no_opcode(for_iter_range, "FOR_ITER") + for_iter1() + self.assert_specialized(for_iter1, "FOR_ITER_RANGE") + self.assert_no_opcode(for_iter1, "FOR_ITER") + + r = range(-20, -10) + def for_iter2(): + for i in r: + self.assertIn(i, r) + + for_iter2() + self.assert_specialized(for_iter2, "FOR_ITER_RANGE") + self.assert_no_opcode(for_iter2, "FOR_ITER") + + r = range(100_000, 100_010) + def for_iter3(): + for i in r: + self.assertIn(i, r) + + for_iter3() + self.assert_specialized(for_iter3, "FOR_ITER_RANGE") + self.assert_no_opcode(for_iter3, "FOR_ITER") + + r = range((1 << 65), (1 << 65)+10) + def for_iter4(): + for i in r: + self.assertIn(i, r) + + for_iter4() + self.assert_specialized(for_iter4, "FOR_ITER") + + @cpython_only + @requires_specialization_ft + def test_get_iter(self): + + L = list(range(2)) + def for_iter_list(): + n = 0 + while n < _testinternalcapi.SPECIALIZATION_THRESHOLD: + n += 1 + for i in L: + self.assertIn(i, L) + + for_iter_list() + self.assert_specialized(for_iter_list, "GET_ITER_LIST_OR_TUPLE") + self.assert_no_opcode(for_iter_list, "GET_ITER") + + t = tuple(range(2)) + def for_iter_tuple(): + n = 0 + while n < _testinternalcapi.SPECIALIZATION_THRESHOLD: + n += 1 + for i in t: + self.assertIn(i, t) + + for_iter_tuple() + self.assert_specialized(for_iter_tuple, "GET_ITER_LIST_OR_TUPLE") + self.assert_no_opcode(for_iter_tuple, "GET_ITER") def for_iter_generator(): - for i in (i for i in range(10)): - i + 1 + n = 0 + while n < _testinternalcapi.SPECIALIZATION_THRESHOLD: + n += 1 + for i in (i for i in range(2)): + i + 1 for_iter_generator() - self.assert_specialized(for_iter_generator, "FOR_ITER_GEN") - self.assert_no_opcode(for_iter_generator, "FOR_ITER") + self.assert_specialized(for_iter_generator, "GET_ITER_SELF") + self.assert_no_opcode(for_iter_generator, "GET_ITER") + def for_iter_range(): + n = 0 + while n < _testinternalcapi.SPECIALIZATION_THRESHOLD: + n += 1 + for i in range(2): + i + 1 + + for_iter_range() + self.assert_specialized(for_iter_range, "GET_ITER_RANGE") + self.assert_no_opcode(for_iter_range, "GET_ITER") if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-30-12-41-14.gh-issue-132554.7yVP6_.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-30-12-41-14.gh-issue-132554.7yVP6_.rst new file mode 100644 index 00000000000000..9f815c42152c9e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-30-12-41-14.gh-issue-132554.7yVP6_.rst @@ -0,0 +1 @@ +Specialize :opcode:`GET_ITER` for lists, tuples and any iterator. diff --git a/Objects/longobject.c b/Objects/longobject.c index 2b533312fee673..c99a6e995515c6 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -10,6 +10,7 @@ #include "pycore_long.h" // _Py_SmallInts #include "pycore_object.h" // _PyObject_Init() #include "pycore_runtime.h" // _PY_NSMALLPOSINTS +#include "pycore_stackref.h" #include "pycore_structseq.h" // _PyStructSequence_FiniBuiltin() #include "pycore_unicodeobject.h" // _PyUnicode_Equal() diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index f8cdfe68a6435e..d074b1b1ce70ff 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -10,21 +10,6 @@ #include "pycore_tuple.h" // _PyTuple_ITEMS() -/* Support objects whose length is > PY_SSIZE_T_MAX. - - This could be sped up for small PyLongs if they fit in a Py_ssize_t. - This only matters on Win64. Though we could use long long which - would presumably help perf. -*/ - -typedef struct { - PyObject_HEAD - PyObject *start; - PyObject *stop; - PyObject *step; - PyObject *length; -} rangeobject; - /* Helper function for validating step. Always returns a new reference or NULL on error. */ @@ -156,6 +141,7 @@ range_vectorcall(PyObject *rangetype, PyObject *const *args, return range_from_array((PyTypeObject *)rangetype, args, nargs); } + PyDoc_STRVAR(range_doc, "range(stop) -> range object\n\ range(start, stop[, step]) -> range object\n\ diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index dbeedb7ffe0ce6..f962a56cd47c09 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,7 +1,7 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0, - 0,0,0,0,0,243,184,0,0,0,128,0,94,0,82,1, + 0,0,0,0,0,243,186,0,0,0,128,0,94,0,82,1, 73,0,116,0,94,0,82,1,73,1,116,1,93,2,33,0, 82,2,52,1,0,0,0,0,0,0,31,0,93,2,33,0, 82,3,93,0,80,6,0,0,0,0,0,0,0,0,0,0, @@ -9,31 +9,31 @@ unsigned char M_test_frozenmain[] = { 31,0,93,1,80,8,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,33,0,52,0,0,0,0,0, 0,0,82,4,44,26,0,0,0,0,0,0,0,0,0,0, - 116,5,82,7,16,0,70,24,0,0,116,6,93,2,33,0, - 82,5,93,6,12,0,82,6,93,5,93,6,44,26,0,0, - 0,0,0,0,0,0,0,0,12,0,50,4,52,1,0,0, - 0,0,0,0,31,0,75,26,0,0,9,0,30,0,82,1, - 35,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122, - 101,110,32,72,101,108,108,111,32,87,111,114,108,100,122,8, - 115,121,115,46,97,114,103,118,218,6,99,111,110,102,105,103, - 122,7,99,111,110,102,105,103,32,122,2,58,32,41,5,218, - 12,112,114,111,103,114,97,109,95,110,97,109,101,218,10,101, - 120,101,99,117,116,97,98,108,101,218,15,117,115,101,95,101, - 110,118,105,114,111,110,109,101,110,116,218,17,99,111,110,102, - 105,103,117,114,101,95,99,95,115,116,100,105,111,218,14,98, - 117,102,102,101,114,101,100,95,115,116,100,105,111,41,7,218, - 3,115,121,115,218,17,95,116,101,115,116,105,110,116,101,114, - 110,97,108,99,97,112,105,218,5,112,114,105,110,116,218,4, - 97,114,103,118,218,11,103,101,116,95,99,111,110,102,105,103, - 115,114,3,0,0,0,218,3,107,101,121,169,0,243,0,0, - 0,0,218,18,116,101,115,116,95,102,114,111,122,101,110,109, - 97,105,110,46,112,121,218,8,60,109,111,100,117,108,101,62, - 114,18,0,0,0,1,0,0,0,115,94,0,0,0,240,3, - 1,1,1,243,8,0,1,11,219,0,24,225,0,5,208,6, - 26,212,0,27,217,0,5,128,106,144,35,151,40,145,40,212, - 0,27,216,9,26,215,9,38,210,9,38,211,9,40,168,24, - 213,9,50,128,6,243,2,6,12,2,128,67,241,14,0,5, - 10,136,71,144,67,144,53,152,2,152,54,160,35,157,59,152, - 45,208,10,40,214,4,41,243,15,6,12,2,114,16,0,0, - 0, + 116,5,82,7,16,0,0,0,70,24,0,0,116,6,93,2, + 33,0,82,5,93,6,12,0,82,6,93,5,93,6,44,26, + 0,0,0,0,0,0,0,0,0,0,12,0,50,4,52,1, + 0,0,0,0,0,0,31,0,75,26,0,0,9,0,30,0, + 82,1,35,0,41,8,233,0,0,0,0,78,122,18,70,114, + 111,122,101,110,32,72,101,108,108,111,32,87,111,114,108,100, + 122,8,115,121,115,46,97,114,103,118,218,6,99,111,110,102, + 105,103,122,7,99,111,110,102,105,103,32,122,2,58,32,41, + 5,218,12,112,114,111,103,114,97,109,95,110,97,109,101,218, + 10,101,120,101,99,117,116,97,98,108,101,218,15,117,115,101, + 95,101,110,118,105,114,111,110,109,101,110,116,218,17,99,111, + 110,102,105,103,117,114,101,95,99,95,115,116,100,105,111,218, + 14,98,117,102,102,101,114,101,100,95,115,116,100,105,111,41, + 7,218,3,115,121,115,218,17,95,116,101,115,116,105,110,116, + 101,114,110,97,108,99,97,112,105,218,5,112,114,105,110,116, + 218,4,97,114,103,118,218,11,103,101,116,95,99,111,110,102, + 105,103,115,114,3,0,0,0,218,3,107,101,121,169,0,243, + 0,0,0,0,218,18,116,101,115,116,95,102,114,111,122,101, + 110,109,97,105,110,46,112,121,218,8,60,109,111,100,117,108, + 101,62,114,18,0,0,0,1,0,0,0,115,94,0,0,0, + 240,3,1,1,1,243,8,0,1,11,219,0,24,225,0,5, + 208,6,26,212,0,27,217,0,5,128,106,144,35,151,40,145, + 40,212,0,27,216,9,26,215,9,38,210,9,38,211,9,40, + 168,24,213,9,50,128,6,244,2,6,12,2,128,67,241,14, + 0,5,10,136,71,144,67,144,53,152,2,152,54,160,35,157, + 59,152,45,208,10,40,214,4,41,243,15,6,12,2,114,16, + 0,0,0, }; diff --git a/Python/bytecodes.c b/Python/bytecodes.c index c4b13da5db41d8..79b5ddb2d77e10 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3048,7 +3048,26 @@ dummy_func( values_or_none = PyStackRef_FromPyObjectSteal(values_or_none_o); } - inst(GET_ITER, (iterable -- iter, index_or_null)) { + + family(GET_ITER, 1) = { + GET_ITER_LIST_OR_TUPLE, + GET_ITER_SELF, + GET_ITER_RANGE, + }; + + specializing op(_SPECIALIZE_GET_ITER, (counter/1, iter -- iter)) { + #if ENABLE_SPECIALIZATION_FT + if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { + next_instr = this_instr; + _Py_Specialize_GetIter(iter, next_instr); + DISPATCH_SAME_OPARG(); + } + OPCODE_DEFERRED_INC(GET_ITER); + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + #endif /* ENABLE_SPECIALIZATION_FT */ + } + + op(_GET_ITER, (iterable -- iter, index_or_null)) { #ifdef Py_STATS _Py_GatherStats_GetIter(iterable); #endif @@ -3060,14 +3079,50 @@ dummy_func( index_or_null = PyStackRef_TagInt(0); } else { - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - PyStackRef_CLOSE(iterable); - ERROR_IF(iter_o == NULL); - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iterable); + if (tp == &PyRange_Type && _PyRange_IsSimpleCompact(iter_o)) { + Py_ssize_t start = _PyRange_GetStartIfCompact(iter_o); + Py_ssize_t stop = _PyRange_GetStopIfCompact(iter_o); + PyStackRef_CLOSE(iterable); + iter = PyStackRef_TagInt(stop); + index_or_null = PyStackRef_TagInt(start); + } + else { + iter_o = PyObject_GetIter(iter_o); + PyStackRef_CLOSE(iterable); + ERROR_IF(iter_o == NULL); + iter = PyStackRef_FromPyObjectSteal(iter_o); + index_or_null = PyStackRef_NULL; + } } } + macro(GET_ITER) = _SPECIALIZE_GET_ITER + _GET_ITER; + + inst(GET_ITER_SELF, (unused/1, iter -- iter, null)) { + PyTypeObject *tp = PyStackRef_TYPE(iter); + DEOPT_IF(tp->tp_iter != PyObject_SelfIter); + null = PyStackRef_NULL; + } + + inst(GET_ITER_LIST_OR_TUPLE, (unused/1, iter -- iter, index0)) { + PyTypeObject *tp = PyStackRef_TYPE(iter); + if (tp != &PyList_Type) { + DEOPT_IF(tp != &PyTuple_Type); + } + index0 = PyStackRef_TagInt(0); + } + + inst(GET_ITER_RANGE, (unused/1, iter -- stop, index)) { + PyTypeObject *tp = PyStackRef_TYPE(iter); + DEOPT_IF(tp != &PyRange_Type); + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + DEOPT_IF(!_PyRange_IsSimpleCompact(iter_o)); + index = PyStackRef_TagInt(_PyRange_GetStartIfCompact(iter_o)); + stop = PyStackRef_TagInt(_PyRange_GetStopIfCompact(iter_o)); + PyStackRef_CLOSE(iter); + } + inst(GET_YIELD_FROM_ITER, (iterable -- iter)) { /* before: [obj]; after [getiter(obj)] */ PyObject *iterable_o = PyStackRef_AsPyObjectBorrow(iterable); @@ -3169,10 +3224,10 @@ dummy_func( } op(_ITER_CHECK_LIST, (iter, null_or_index -- iter, null_or_index)) { - PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); - EXIT_IF(Py_TYPE(iter_o) != &PyList_Type); + EXIT_IF(PyStackRef_TYPE(iter) != &PyList_Type); assert(PyStackRef_IsTaggedInt(null_or_index)); #ifdef Py_GIL_DISABLED + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); EXIT_IF(!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)); #endif } @@ -3254,8 +3309,7 @@ dummy_func( _ITER_NEXT_LIST; op(_ITER_CHECK_TUPLE, (iter, null_or_index -- iter, null_or_index)) { - PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); - EXIT_IF(Py_TYPE(iter_o) != &PyTuple_Type); + EXIT_IF(PyStackRef_TYPE(iter) != &PyTuple_Type); assert(PyStackRef_IsTaggedInt(null_or_index)); } @@ -3295,21 +3349,11 @@ dummy_func( _ITER_NEXT_TUPLE; op(_ITER_CHECK_RANGE, (iter, null_or_index -- iter, null_or_index)) { - _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); - EXIT_IF(Py_TYPE(r) != &PyRangeIter_Type); -#ifdef Py_GIL_DISABLED - EXIT_IF(!_PyObject_IsUniquelyReferenced((PyObject *)r)); -#endif + EXIT_IF(!PyStackRef_IsTaggedInt(iter)); } replaced op(_ITER_JUMP_RANGE, (iter, null_or_index -- iter, null_or_index)) { - _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); - assert(Py_TYPE(r) == &PyRangeIter_Type); -#ifdef Py_GIL_DISABLED - assert(_PyObject_IsUniquelyReferenced((PyObject *)r)); -#endif - STAT_INC(FOR_ITER, hit); - if (r->len <= 0) { + if (!PyStackRef_TaggedIntLessThan(null_or_index, iter)) { // Jump over END_FOR instruction. JUMPBY(oparg + 1); DISPATCH(); @@ -3318,24 +3362,15 @@ dummy_func( // Only used by Tier 2 op(_GUARD_NOT_EXHAUSTED_RANGE, (iter, null_or_index -- iter, null_or_index)) { - _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); - assert(Py_TYPE(r) == &PyRangeIter_Type); - EXIT_IF(r->len <= 0); + EXIT_IF(!PyStackRef_TaggedIntLessThan(null_or_index, iter)); } op(_ITER_NEXT_RANGE, (iter, null_or_index -- iter, null_or_index, next)) { - _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); - assert(Py_TYPE(r) == &PyRangeIter_Type); -#ifdef Py_GIL_DISABLED - assert(_PyObject_IsUniquelyReferenced((PyObject *)r)); -#endif - assert(r->len > 0); - long value = r->start; - r->start = value + r->step; - r->len--; - PyObject *res = PyLong_FromLong(value); - ERROR_IF(res == NULL); - next = PyStackRef_FromPyObjectSteal(res); + next = PyStackRef_BoxInt(null_or_index); + if (PyStackRef_IsNull(next)) { + ERROR_NO_POP(); + } + null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index); } macro(FOR_ITER_RANGE) = @@ -3345,8 +3380,8 @@ dummy_func( _ITER_NEXT_RANGE; op(_FOR_ITER_GEN_FRAME, (iter, null -- iter, null, gen_frame: _PyInterpreterFrame*)) { + DEOPT_IF(PyStackRef_TYPE(iter) != &PyGen_Type); PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter); - DEOPT_IF(Py_TYPE(gen) != &PyGen_Type); #ifdef Py_GIL_DISABLED // Since generators can't be used by multiple threads anyway we // don't need to deopt here, but this lets us work on making diff --git a/Python/ceval.c b/Python/ceval.c index 4cfe4bb88f4e48..491dffea667a2d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3459,14 +3459,27 @@ foriter_next(PyObject *seq, _PyStackRef index) return PyStackRef_FromPyObjectSteal(item); } -_PyStackRef _PyForIter_VirtualIteratorNext(PyThreadState* tstate, _PyInterpreterFrame* frame, _PyStackRef iter, _PyStackRef* index_ptr) -{ - PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); +_PyStackRef +_PyForIter_VirtualIteratorNext( + PyThreadState* tstate, _PyInterpreterFrame* frame, + _PyStackRef iter, _PyStackRef* index_ptr +) { _PyStackRef index = *index_ptr; if (PyStackRef_IsTaggedInt(index)) { - *index_ptr = PyStackRef_IncrementTaggedIntNoOverflow(index); - return foriter_next(iter_o, index); + if (PyStackRef_IsTaggedInt(iter)) { + if (!PyStackRef_TaggedIntLessThan(index, iter)) { + return PyStackRef_NULL; + } + *index_ptr = PyStackRef_IncrementTaggedIntNoOverflow(index); + return PyStackRef_BoxInt(index); + } + else { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + *index_ptr = PyStackRef_IncrementTaggedIntNoOverflow(index); + return foriter_next(iter_o, index); + } } + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); if (next_o == NULL) { if (_PyErr_Occurred(tstate)) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index d19605169d5e55..3e5d5ac8be903a 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4200,19 +4200,35 @@ index_or_null = PyStackRef_TagInt(0); } else { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); - _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_ERROR(); + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iterable); + if (tp == &PyRange_Type && _PyRange_IsSimpleCompact(iter_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_ssize_t start = _PyRange_GetStartIfCompact(iter_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + Py_ssize_t stop = _PyRange_GetStopIfCompact(iter_o); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); + iter = PyStackRef_TagInt(stop); + index_or_null = PyStackRef_TagInt(start); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + iter_o = PyObject_GetIter(iter_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (iter_o == NULL) { + JUMP_TO_ERROR(); + } + iter = PyStackRef_FromPyObjectSteal(iter_o); + index_or_null = PyStackRef_NULL; } - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; stack_pointer += 1; } stack_pointer[-1] = iter; @@ -4222,6 +4238,69 @@ break; } + case _GET_ITER_SELF: { + _PyStackRef iter; + _PyStackRef null; + iter = stack_pointer[-1]; + PyTypeObject *tp = PyStackRef_TYPE(iter); + if (tp->tp_iter != PyObject_SelfIter) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + null = PyStackRef_NULL; + stack_pointer[0] = null; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + + case _GET_ITER_LIST_OR_TUPLE: { + _PyStackRef iter; + _PyStackRef index0; + iter = stack_pointer[-1]; + PyTypeObject *tp = PyStackRef_TYPE(iter); + if (tp != &PyList_Type) { + if (tp != &PyTuple_Type) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + } + index0 = PyStackRef_TagInt(0); + stack_pointer[0] = index0; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + + case _GET_ITER_RANGE: { + _PyStackRef iter; + _PyStackRef stop; + _PyStackRef index; + iter = stack_pointer[-1]; + PyTypeObject *tp = PyStackRef_TYPE(iter); + if (tp != &PyRange_Type) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (!_PyRange_IsSimpleCompact(iter_o)) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + index = PyStackRef_TagInt(_PyRange_GetStartIfCompact(iter_o)); + stack_pointer = _PyFrame_GetStackPointer(frame); + stop = PyStackRef_TagInt(_PyRange_GetStopIfCompact(iter_o)); + stack_pointer[-1] = stop; + stack_pointer[0] = index; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iter); + stack_pointer = _PyFrame_GetStackPointer(frame); + break; + } + case _GET_YIELD_FROM_ITER: { _PyStackRef iterable; _PyStackRef iter; @@ -4295,13 +4374,13 @@ _PyStackRef iter; null_or_index = stack_pointer[-1]; iter = stack_pointer[-2]; - PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); - if (Py_TYPE(iter_o) != &PyList_Type) { + if (PyStackRef_TYPE(iter) != &PyList_Type) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } assert(PyStackRef_IsTaggedInt(null_or_index)); #ifdef Py_GIL_DISABLED + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); @@ -4366,8 +4445,7 @@ _PyStackRef iter; null_or_index = stack_pointer[-1]; iter = stack_pointer[-2]; - PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); - if (Py_TYPE(iter_o) != &PyTuple_Type) { + if (PyStackRef_TYPE(iter) != &PyTuple_Type) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } @@ -4413,28 +4491,21 @@ case _ITER_CHECK_RANGE: { _PyStackRef iter; iter = stack_pointer[-2]; - _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); - if (Py_TYPE(r) != &PyRangeIter_Type) { + if (!PyStackRef_IsTaggedInt(iter)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } - #ifdef Py_GIL_DISABLED - if (!_PyObject_IsUniquelyReferenced((PyObject *)r)) { - UOP_STAT_INC(uopcode, miss); - JUMP_TO_JUMP_TARGET(); - } - #endif break; } /* _ITER_JUMP_RANGE is not a viable micro-op for tier 2 because it is replaced */ case _GUARD_NOT_EXHAUSTED_RANGE: { + _PyStackRef null_or_index; _PyStackRef iter; + null_or_index = stack_pointer[-1]; iter = stack_pointer[-2]; - _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); - assert(Py_TYPE(r) == &PyRangeIter_Type); - if (r->len <= 0) { + if (!PyStackRef_TaggedIntLessThan(null_or_index, iter)) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } @@ -4442,23 +4513,15 @@ } case _ITER_NEXT_RANGE: { - _PyStackRef iter; + _PyStackRef null_or_index; _PyStackRef next; - iter = stack_pointer[-2]; - _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); - assert(Py_TYPE(r) == &PyRangeIter_Type); - #ifdef Py_GIL_DISABLED - assert(_PyObject_IsUniquelyReferenced((PyObject *)r)); - #endif - assert(r->len > 0); - long value = r->start; - r->start = value + r->step; - r->len--; - PyObject *res = PyLong_FromLong(value); - if (res == NULL) { + null_or_index = stack_pointer[-1]; + next = PyStackRef_BoxInt(null_or_index); + if (PyStackRef_IsNull(next)) { JUMP_TO_ERROR(); } - next = PyStackRef_FromPyObjectSteal(res); + null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index); + stack_pointer[-1] = null_or_index; stack_pointer[0] = next; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -4470,11 +4533,11 @@ _PyInterpreterFrame *gen_frame; oparg = CURRENT_OPARG(); iter = stack_pointer[-2]; - PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter); - if (Py_TYPE(gen) != &PyGen_Type) { + if (PyStackRef_TYPE(iter) != &PyGen_Type) { UOP_STAT_INC(uopcode, miss); JUMP_TO_JUMP_TARGET(); } + PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter); #ifdef Py_GIL_DISABLED if (!_PyObject_IsUniquelyReferenced((PyObject *)gen)) { diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index c8825df3ade5a5..e8dbc37150899d 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -5799,12 +5799,12 @@ // _FOR_ITER_GEN_FRAME { iter = stack_pointer[-2]; - PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter); - if (Py_TYPE(gen) != &PyGen_Type) { + if (PyStackRef_TYPE(iter) != &PyGen_Type) { UPDATE_MISS_STATS(FOR_ITER); assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); JUMP_TO_PREDICTED(FOR_ITER); } + PyGenObject *gen = (PyGenObject *)PyStackRef_AsPyObjectBorrow(iter); #ifdef Py_GIL_DISABLED if (!_PyObject_IsUniquelyReferenced((PyObject *)gen)) { UPDATE_MISS_STATS(FOR_ITER); @@ -5862,14 +5862,14 @@ { null_or_index = stack_pointer[-1]; iter = stack_pointer[-2]; - PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); - if (Py_TYPE(iter_o) != &PyList_Type) { + if (PyStackRef_TYPE(iter) != &PyList_Type) { UPDATE_MISS_STATS(FOR_ITER); assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); JUMP_TO_PREDICTED(FOR_ITER); } assert(PyStackRef_IsTaggedInt(null_or_index)); #ifdef Py_GIL_DISABLED + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) { UPDATE_MISS_STATS(FOR_ITER); assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); @@ -5939,55 +5939,35 @@ INSTRUCTION_STATS(FOR_ITER_RANGE); static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache size"); _PyStackRef iter; + _PyStackRef null_or_index; _PyStackRef next; /* Skip 1 cache entry */ // _ITER_CHECK_RANGE { iter = stack_pointer[-2]; - _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); - if (Py_TYPE(r) != &PyRangeIter_Type) { + if (!PyStackRef_IsTaggedInt(iter)) { UPDATE_MISS_STATS(FOR_ITER); assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); JUMP_TO_PREDICTED(FOR_ITER); } - #ifdef Py_GIL_DISABLED - if (!_PyObject_IsUniquelyReferenced((PyObject *)r)) { - UPDATE_MISS_STATS(FOR_ITER); - assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); - JUMP_TO_PREDICTED(FOR_ITER); - } - #endif } // _ITER_JUMP_RANGE { - _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); - assert(Py_TYPE(r) == &PyRangeIter_Type); - #ifdef Py_GIL_DISABLED - assert(_PyObject_IsUniquelyReferenced((PyObject *)r)); - #endif - STAT_INC(FOR_ITER, hit); - if (r->len <= 0) { + null_or_index = stack_pointer[-1]; + if (!PyStackRef_TaggedIntLessThan(null_or_index, iter)) { JUMPBY(oparg + 1); DISPATCH(); } } // _ITER_NEXT_RANGE { - _PyRangeIterObject *r = (_PyRangeIterObject *)PyStackRef_AsPyObjectBorrow(iter); - assert(Py_TYPE(r) == &PyRangeIter_Type); - #ifdef Py_GIL_DISABLED - assert(_PyObject_IsUniquelyReferenced((PyObject *)r)); - #endif - assert(r->len > 0); - long value = r->start; - r->start = value + r->step; - r->len--; - PyObject *res = PyLong_FromLong(value); - if (res == NULL) { + next = PyStackRef_BoxInt(null_or_index); + if (PyStackRef_IsNull(next)) { JUMP_TO_LABEL(error); } - next = PyStackRef_FromPyObjectSteal(res); + null_or_index = PyStackRef_IncrementTaggedIntNoOverflow(null_or_index); } + stack_pointer[-1] = null_or_index; stack_pointer[0] = next; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -6013,8 +5993,7 @@ { null_or_index = stack_pointer[-1]; iter = stack_pointer[-2]; - PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); - if (Py_TYPE(iter_o) != &PyTuple_Type) { + if (PyStackRef_TYPE(iter) != &PyTuple_Type) { UPDATE_MISS_STATS(FOR_ITER); assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); JUMP_TO_PREDICTED(FOR_ITER); @@ -6170,38 +6149,77 @@ (void)(opcode); #endif frame->instr_ptr = next_instr; - next_instr += 1; + next_instr += 2; INSTRUCTION_STATS(GET_ITER); - _PyStackRef iterable; + PREDICTED_GET_ITER:; + _Py_CODEUNIT* const this_instr = next_instr - 2; + (void)this_instr; _PyStackRef iter; + _PyStackRef iterable; _PyStackRef index_or_null; - iterable = stack_pointer[-1]; - #ifdef Py_STATS - _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_GatherStats_GetIter(iterable); - stack_pointer = _PyFrame_GetStackPointer(frame); - #endif - - PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { - iter = iterable; - index_or_null = PyStackRef_TagInt(0); + // _SPECIALIZE_GET_ITER + { + iter = stack_pointer[-1]; + uint16_t counter = read_u16(&this_instr[1].cache); + (void)counter; + #if ENABLE_SPECIALIZATION_FT + if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { + next_instr = this_instr; + _PyFrame_SetStackPointer(frame, stack_pointer); + _Py_Specialize_GetIter(iter, next_instr); + stack_pointer = _PyFrame_GetStackPointer(frame); + DISPATCH_SAME_OPARG(); + } + OPCODE_DEFERRED_INC(GET_ITER); + ADVANCE_ADAPTIVE_COUNTER(this_instr[1].counter); + #endif /* ENABLE_SPECIALIZATION_FT */ } - else { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); - stack_pointer = _PyFrame_GetStackPointer(frame); - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); + // _GET_ITER + { + iterable = iter; + #ifdef Py_STATS _PyFrame_SetStackPointer(frame, stack_pointer); - PyStackRef_CLOSE(iterable); + _Py_GatherStats_GetIter(iterable); stack_pointer = _PyFrame_GetStackPointer(frame); - if (iter_o == NULL) { - JUMP_TO_LABEL(error); + #endif + + PyTypeObject *tp = PyStackRef_TYPE(iterable); + if (tp == &PyTuple_Type || tp == &PyList_Type) { + iter = iterable; + index_or_null = PyStackRef_TagInt(0); + } + else { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iterable); + if (tp == &PyRange_Type && _PyRange_IsSimpleCompact(iter_o)) { + _PyFrame_SetStackPointer(frame, stack_pointer); + Py_ssize_t start = _PyRange_GetStartIfCompact(iter_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + Py_ssize_t stop = _PyRange_GetStopIfCompact(iter_o); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); + iter = PyStackRef_TagInt(stop); + index_or_null = PyStackRef_TagInt(start); + } + else { + _PyFrame_SetStackPointer(frame, stack_pointer); + iter_o = PyObject_GetIter(iter_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iterable); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (iter_o == NULL) { + JUMP_TO_LABEL(error); + } + iter = PyStackRef_FromPyObjectSteal(iter_o); + index_or_null = PyStackRef_NULL; + } + stack_pointer += 1; } - iter = PyStackRef_FromPyObjectSteal(iter_o); - index_or_null = PyStackRef_NULL; - stack_pointer += 1; } stack_pointer[-1] = iter; stack_pointer[0] = index_or_null; @@ -6210,6 +6228,106 @@ DISPATCH(); } + TARGET(GET_ITER_LIST_OR_TUPLE) { + #if Py_TAIL_CALL_INTERP + int opcode = GET_ITER_LIST_OR_TUPLE; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_LIST_OR_TUPLE); + static_assert(1 == 1, "incorrect cache size"); + _PyStackRef iter; + _PyStackRef index0; + /* Skip 1 cache entry */ + iter = stack_pointer[-1]; + PyTypeObject *tp = PyStackRef_TYPE(iter); + if (tp != &PyList_Type) { + if (tp != &PyTuple_Type) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + } + index0 = PyStackRef_TagInt(0); + stack_pointer[0] = index0; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + DISPATCH(); + } + + TARGET(GET_ITER_RANGE) { + #if Py_TAIL_CALL_INTERP + int opcode = GET_ITER_RANGE; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_RANGE); + static_assert(1 == 1, "incorrect cache size"); + _PyStackRef iter; + _PyStackRef stop; + _PyStackRef index; + /* Skip 1 cache entry */ + iter = stack_pointer[-1]; + PyTypeObject *tp = PyStackRef_TYPE(iter); + if (tp != &PyRange_Type) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + if (!_PyRange_IsSimpleCompact(iter_o)) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + index = PyStackRef_TagInt(_PyRange_GetStartIfCompact(iter_o)); + stack_pointer = _PyFrame_GetStackPointer(frame); + stop = PyStackRef_TagInt(_PyRange_GetStopIfCompact(iter_o)); + stack_pointer[-1] = stop; + stack_pointer[0] = index; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(iter); + stack_pointer = _PyFrame_GetStackPointer(frame); + DISPATCH(); + } + + TARGET(GET_ITER_SELF) { + #if Py_TAIL_CALL_INTERP + int opcode = GET_ITER_SELF; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(GET_ITER_SELF); + static_assert(1 == 1, "incorrect cache size"); + _PyStackRef iter; + _PyStackRef null; + /* Skip 1 cache entry */ + iter = stack_pointer[-1]; + PyTypeObject *tp = PyStackRef_TYPE(iter); + if (tp->tp_iter != PyObject_SelfIter) { + UPDATE_MISS_STATS(GET_ITER); + assert(_PyOpcode_Deopt[opcode] == (GET_ITER)); + JUMP_TO_PREDICTED(GET_ITER); + } + null = PyStackRef_NULL; + stack_pointer[0] = null; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + DISPATCH(); + } + TARGET(GET_LEN) { #if Py_TAIL_CALL_INTERP int opcode = GET_LEN; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 1d6dcddab4b12d..338afdf4532a4c 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -175,6 +175,9 @@ static void *opcode_targets[256] = { &&TARGET_FOR_ITER_LIST, &&TARGET_FOR_ITER_RANGE, &&TARGET_FOR_ITER_TUPLE, + &&TARGET_GET_ITER_LIST_OR_TUPLE, + &&TARGET_GET_ITER_RANGE, + &&TARGET_GET_ITER_SELF, &&TARGET_JUMP_BACKWARD_JIT, &&TARGET_JUMP_BACKWARD_NO_JIT, &&TARGET_LOAD_ATTR_CLASS, @@ -231,9 +234,6 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_POP_ITER, &&TARGET_INSTRUMENTED_END_SEND, @@ -359,6 +359,9 @@ Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_AITER(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_ANEXT(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_AWAITABLE(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_ITER(TAIL_CALL_PARAMS); +Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_ITER_LIST_OR_TUPLE(TAIL_CALL_PARAMS); +Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_ITER_RANGE(TAIL_CALL_PARAMS); +Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_ITER_SELF(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_LEN(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_GET_YIELD_FROM_ITER(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_IMPORT_FROM(TAIL_CALL_PARAMS); @@ -596,6 +599,9 @@ static py_tail_call_funcptr INSTRUCTION_TABLE[256] = { [GET_ANEXT] = _TAIL_CALL_GET_ANEXT, [GET_AWAITABLE] = _TAIL_CALL_GET_AWAITABLE, [GET_ITER] = _TAIL_CALL_GET_ITER, + [GET_ITER_LIST_OR_TUPLE] = _TAIL_CALL_GET_ITER_LIST_OR_TUPLE, + [GET_ITER_RANGE] = _TAIL_CALL_GET_ITER_RANGE, + [GET_ITER_SELF] = _TAIL_CALL_GET_ITER_SELF, [GET_LEN] = _TAIL_CALL_GET_LEN, [GET_YIELD_FROM_ITER] = _TAIL_CALL_GET_YIELD_FROM_ITER, [IMPORT_FROM] = _TAIL_CALL_IMPORT_FROM, @@ -736,9 +742,6 @@ static py_tail_call_funcptr INSTRUCTION_TABLE[256] = { [125] = _TAIL_CALL_UNKNOWN_OPCODE, [126] = _TAIL_CALL_UNKNOWN_OPCODE, [127] = _TAIL_CALL_UNKNOWN_OPCODE, - [210] = _TAIL_CALL_UNKNOWN_OPCODE, - [211] = _TAIL_CALL_UNKNOWN_OPCODE, - [212] = _TAIL_CALL_UNKNOWN_OPCODE, [213] = _TAIL_CALL_UNKNOWN_OPCODE, [214] = _TAIL_CALL_UNKNOWN_OPCODE, [215] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 4780e492f61d74..0d068849009ab7 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1599,6 +1599,36 @@ break; } + case _GET_ITER_SELF: { + JitOptSymbol *null; + null = sym_new_null(ctx); + stack_pointer[0] = null; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + + case _GET_ITER_LIST_OR_TUPLE: { + JitOptSymbol *index0; + index0 = sym_new_not_null(ctx); + stack_pointer[0] = index0; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + + case _GET_ITER_RANGE: { + JitOptSymbol *stop; + JitOptSymbol *index; + stop = sym_new_not_null(ctx); + index = sym_new_not_null(ctx); + stack_pointer[-1] = stop; + stack_pointer[0] = index; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + case _GET_YIELD_FROM_ITER: { JitOptSymbol *iter; iter = sym_new_not_null(ctx); diff --git a/Python/specialize.c b/Python/specialize.c index 92f79d39d55208..310e0f894f74cd 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -17,6 +17,7 @@ #include "pycore_uop_ids.h" // MAX_UOP_ID #include "pycore_opcode_utils.h" // RESUME_AT_FUNC_START #include "pycore_pylifecycle.h" // _PyOS_URandomNonblock() +#include "pycore_range.h" // _PyRange_IsSimpleCompact() #include "pycore_runtime.h" // _Py_ID() #include "pycore_unicodeobject.h" // _PyUnicodeASCIIIter_Type @@ -2908,11 +2909,11 @@ _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT { assert(ENABLE_SPECIALIZATION_FT); assert(_PyOpcode_Caches[FOR_ITER] == INLINE_CACHE_ENTRIES_FOR_ITER); - PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); - PyTypeObject *tp = Py_TYPE(iter_o); + PyTypeObject *tp = PyStackRef_TYPE(iter); if (PyStackRef_IsNull(null_or_index)) { #ifdef Py_GIL_DISABLED + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); // Only specialize for uniquely referenced iterators, so that we know // they're only referenced by this one thread. This is more limiting // than we need (even `it = iter(mylist); for item in it:` won't get @@ -2922,11 +2923,7 @@ _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT goto failure; } #endif - if (tp == &PyRangeIter_Type) { - specialize(instr, FOR_ITER_RANGE); - return; - } - else if (tp == &PyGen_Type && oparg <= SHRT_MAX) { + if (tp == &PyGen_Type && oparg <= SHRT_MAX) { // Generators are very much not thread-safe, so don't worry about // the specialization not being thread-safe. assert(instr[oparg + INLINE_CACHE_ENTRIES_FOR_ITER + 1].op.code == END_FOR || @@ -2941,8 +2938,13 @@ _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT } } else { + if (tp == &PyLong_Type) { + specialize(instr, FOR_ITER_RANGE); + return; + } if (tp == &PyList_Type) { #ifdef Py_GIL_DISABLED + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); // Only specialize for lists owned by this thread or shared if (!_Py_IsOwnedByCurrentThread(iter_o) && !_PyObject_GC_IS_SHARED(iter_o)) { goto failure; @@ -2958,7 +2960,7 @@ _Py_Specialize_ForIter(_PyStackRef iter, _PyStackRef null_or_index, _Py_CODEUNIT } failure: SPECIALIZATION_FAIL(FOR_ITER, - _PySpecialization_ClassifyIterator(iter_o)); + _PySpecialization_ClassifyIterator(PyStackRef_AsPyObjectBorrow(iter))); unspecialize(instr); } @@ -3174,6 +3176,31 @@ _Py_GatherStats_GetIter(_PyStackRef iterable) #endif +Py_NO_INLINE void +_Py_Specialize_GetIter(_PyStackRef iterable, _Py_CODEUNIT *instr) +{ + PyTypeObject *tp = PyStackRef_TYPE(iterable); + if (tp->tp_iter == PyObject_SelfIter) { + specialize(instr, GET_ITER_SELF); + return; + } + if (tp == &PyList_Type || tp == &PyTuple_Type) { + specialize(instr, GET_ITER_LIST_OR_TUPLE); + return; + } + if (tp == &PyRange_Type) { + if (_PyRange_IsSimpleCompact(PyStackRef_AsPyObjectBorrow(iterable))) { + specialize(instr, GET_ITER_RANGE); + return; + } + } +#ifdef Py_STATS + _Py_GatherStats_GetIter(iterable); +#endif + unspecialize(instr); + return; +} + /* Code init cleanup. * CALL_ALLOC_AND_ENTER_INIT will set up * the frame to execute the EXIT_INIT_CHECK diff --git a/Python/stackrefs.c b/Python/stackrefs.c index ecc0012ef17b39..be517778c67f93 100644 --- a/Python/stackrefs.c +++ b/Python/stackrefs.c @@ -206,6 +206,14 @@ _PyStackRef PyStackRef_TagInt(intptr_t i) return (_PyStackRef){ .index = (i << 1) + 1 }; } +bool +PyStackRef_TaggedIntLessThan(_PyStackRef a, _PyStackRef b) +{ + assert(PyStackRef_IsTaggedInt(a)); + assert(PyStackRef_IsTaggedInt(b)); + return ((intptr_t)a.index) < ((intptr_t)b.index); +} + intptr_t PyStackRef_UntagInt(_PyStackRef i) { diff --git a/Tools/cases_generator/analyzer.py b/Tools/cases_generator/analyzer.py index 1447f365336d82..7e0b8d891e7d6b 100644 --- a/Tools/cases_generator/analyzer.py +++ b/Tools/cases_generator/analyzer.py @@ -683,6 +683,11 @@ def has_error_without_pop(op: parser.CodeDef) -> bool: "PyStackRef_IsNullOrInt", "PyStackRef_IsError", "PyStackRef_IsValid", + "_PyRange_IsSimpleCompact", + "_PyRange_GetStopIfCompact", + "PyStackRef_BoxInt", + "PyStackRef_TYPE", + "PyStackRef_TaggedIntLessThan", )