diff --git a/Include/cpython/object.h b/Include/cpython/object.h index 973d358ed8e4ec..19e77dc8eec28a 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -239,6 +239,9 @@ struct _typeobject { * Otherwise, limited to MAX_VERSIONS_PER_CLASS (defined elsewhere). */ uint16_t tp_versions_used; + /* Returns the object at the index given, or NULL if out-of-bounds + * Never raises an exception. */ + iterindexfunc tp_iterindex; }; #define _Py_ATTR_CACHE_UNUSED (30000) // (see tp_versions_used) 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..eef3fa0c273384 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. Add FOR_ITER_INDEX) 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..b9d4537cbe7761 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -208,6 +208,8 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 2; case FOR_ITER_GEN: return 2; + case FOR_ITER_INDEX: + return 2; case FOR_ITER_LIST: return 2; case FOR_ITER_RANGE: @@ -222,6 +224,12 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 1; case GET_ITER: return 1; + case GET_ITER_INDEX: + return 1; + case GET_ITER_RANGE: + return 1; + case GET_ITER_SELF: + return 1; case GET_LEN: return 1; case GET_YIELD_FROM_ITER: @@ -691,6 +699,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 3; case FOR_ITER_GEN: return 2; + case FOR_ITER_INDEX: + return 3; case FOR_ITER_LIST: return 3; case FOR_ITER_RANGE: @@ -705,6 +715,12 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 1; case GET_ITER: return 2; + case GET_ITER_INDEX: + return 2; + case GET_ITER_RANGE: + return 2; + case GET_ITER_SELF: + return 2; case GET_LEN: return 2; case GET_YIELD_FROM_ITER: @@ -1155,13 +1171,17 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [FORMAT_WITH_SPEC] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [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_INDEX] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_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_INDEX] = { 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 }, @@ -1396,6 +1416,7 @@ _PyOpcode_macro_expansion[256] = { [FORMAT_WITH_SPEC] = { .nuops = 1, .uops = { { _FORMAT_WITH_SPEC, OPARG_SIMPLE, 0 } } }, [FOR_ITER] = { .nuops = 1, .uops = { { _FOR_ITER, OPARG_REPLACED, 0 } } }, [FOR_ITER_GEN] = { .nuops = 3, .uops = { { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _FOR_ITER_GEN_FRAME, OPARG_SIMPLE, 1 }, { _PUSH_FRAME, OPARG_SIMPLE, 1 } } }, + [FOR_ITER_INDEX] = { .nuops = 2, .uops = { { _ITER_CHECK_INDEX, OPARG_SIMPLE, 1 }, { _FOR_ITER_INDEX, OPARG_REPLACED, 1 } } }, [FOR_ITER_LIST] = { .nuops = 3, .uops = { { _ITER_CHECK_LIST, OPARG_SIMPLE, 1 }, { _ITER_JUMP_LIST, OPARG_REPLACED, 1 }, { _ITER_NEXT_LIST, OPARG_REPLACED, 1 } } }, [FOR_ITER_RANGE] = { .nuops = 3, .uops = { { _ITER_CHECK_RANGE, OPARG_SIMPLE, 1 }, { _ITER_JUMP_RANGE, OPARG_REPLACED, 1 }, { _ITER_NEXT_RANGE, OPARG_SIMPLE, 1 } } }, [FOR_ITER_TUPLE] = { .nuops = 3, .uops = { { _ITER_CHECK_TUPLE, OPARG_SIMPLE, 1 }, { _ITER_JUMP_TUPLE, OPARG_REPLACED, 1 }, { _ITER_NEXT_TUPLE, OPARG_SIMPLE, 1 } } }, @@ -1403,6 +1424,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_INDEX] = { .nuops = 1, .uops = { { _GET_ITER_INDEX, 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 } } }, @@ -1593,6 +1617,7 @@ const char *_PyOpcode_OpName[267] = { [FORMAT_WITH_SPEC] = "FORMAT_WITH_SPEC", [FOR_ITER] = "FOR_ITER", [FOR_ITER_GEN] = "FOR_ITER_GEN", + [FOR_ITER_INDEX] = "FOR_ITER_INDEX", [FOR_ITER_LIST] = "FOR_ITER_LIST", [FOR_ITER_RANGE] = "FOR_ITER_RANGE", [FOR_ITER_TUPLE] = "FOR_ITER_TUPLE", @@ -1600,6 +1625,9 @@ const char *_PyOpcode_OpName[267] = { [GET_ANEXT] = "GET_ANEXT", [GET_AWAITABLE] = "GET_AWAITABLE", [GET_ITER] = "GET_ITER", + [GET_ITER_INDEX] = "GET_ITER_INDEX", + [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 +1792,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,10 +1810,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, [216] = 216, @@ -1890,6 +1915,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [FORMAT_WITH_SPEC] = FORMAT_WITH_SPEC, [FOR_ITER] = FOR_ITER, [FOR_ITER_GEN] = FOR_ITER, + [FOR_ITER_INDEX] = FOR_ITER, [FOR_ITER_LIST] = FOR_ITER, [FOR_ITER_RANGE] = FOR_ITER, [FOR_ITER_TUPLE] = FOR_ITER, @@ -1897,6 +1923,9 @@ const uint8_t _PyOpcode_Deopt[256] = { [GET_ANEXT] = GET_ANEXT, [GET_AWAITABLE] = GET_AWAITABLE, [GET_ITER] = GET_ITER, + [GET_ITER_INDEX] = 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,10 +2071,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: \ case 216: \ 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 10e7199269eb40..83920f68f14480 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) { @@ -329,10 +337,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 @@ -849,6 +865,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..c4a09ca925381c 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -112,61 +112,65 @@ extern "C" { #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC #define _FOR_ITER 373 #define _FOR_ITER_GEN_FRAME 374 -#define _FOR_ITER_TIER_TWO 375 +#define _FOR_ITER_INDEX 375 +#define _FOR_ITER_INDEX_TIER_TWO 376 +#define _FOR_ITER_TIER_TWO 377 #define _GET_AITER GET_AITER #define _GET_ANEXT GET_ANEXT #define _GET_AWAITABLE GET_AWAITABLE -#define _GET_ITER GET_ITER +#define _GET_ITER 378 +#define _GET_ITER_INDEX GET_ITER_INDEX +#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 379 +#define _GUARD_CALLABLE_ISINSTANCE 380 +#define _GUARD_CALLABLE_LEN 381 +#define _GUARD_CALLABLE_LIST_APPEND 382 +#define _GUARD_CALLABLE_STR_1 383 +#define _GUARD_CALLABLE_TUPLE_1 384 +#define _GUARD_CALLABLE_TYPE_1 385 +#define _GUARD_DORV_NO_DICT 386 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 387 +#define _GUARD_GLOBALS_VERSION 388 +#define _GUARD_IS_FALSE_POP 389 +#define _GUARD_IS_NONE_POP 390 +#define _GUARD_IS_NOT_NONE_POP 391 +#define _GUARD_IS_TRUE_POP 392 +#define _GUARD_KEYS_VERSION 393 +#define _GUARD_NOS_DICT 394 +#define _GUARD_NOS_FLOAT 395 +#define _GUARD_NOS_INT 396 +#define _GUARD_NOS_LIST 397 +#define _GUARD_NOS_NOT_NULL 398 +#define _GUARD_NOS_NULL 399 +#define _GUARD_NOS_TUPLE 400 +#define _GUARD_NOS_UNICODE 401 +#define _GUARD_NOT_EXHAUSTED_LIST 402 +#define _GUARD_NOT_EXHAUSTED_RANGE 403 +#define _GUARD_NOT_EXHAUSTED_TUPLE 404 +#define _GUARD_THIRD_NULL 405 +#define _GUARD_TOS_ANY_SET 406 +#define _GUARD_TOS_DICT 407 +#define _GUARD_TOS_FLOAT 408 +#define _GUARD_TOS_INT 409 +#define _GUARD_TOS_LIST 410 +#define _GUARD_TOS_SLICE 411 +#define _GUARD_TOS_TUPLE 412 +#define _GUARD_TOS_UNICODE 413 +#define _GUARD_TYPE_VERSION 414 +#define _GUARD_TYPE_VERSION_AND_LOCK 415 #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 _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 416 +#define _INIT_CALL_PY_EXACT_ARGS 417 +#define _INIT_CALL_PY_EXACT_ARGS_0 418 +#define _INIT_CALL_PY_EXACT_ARGS_1 419 +#define _INIT_CALL_PY_EXACT_ARGS_2 420 +#define _INIT_CALL_PY_EXACT_ARGS_3 421 +#define _INIT_CALL_PY_EXACT_ARGS_4 422 +#define _INSERT_NULL 423 #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD #define _INSTRUMENTED_LINE INSTRUMENTED_LINE @@ -175,171 +179,173 @@ 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 424 #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_INDEX 425 +#define _ITER_CHECK_LIST 426 +#define _ITER_CHECK_RANGE 427 +#define _ITER_CHECK_TUPLE 428 +#define _ITER_JUMP_LIST 429 +#define _ITER_JUMP_RANGE 430 +#define _ITER_JUMP_TUPLE 431 +#define _ITER_NEXT_LIST 432 +#define _ITER_NEXT_LIST_TIER_TWO 433 +#define _ITER_NEXT_RANGE 434 +#define _ITER_NEXT_TUPLE 435 +#define _JUMP_TO_TOP 436 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 433 -#define _LOAD_ATTR_CLASS 434 +#define _LOAD_ATTR 437 +#define _LOAD_ATTR_CLASS 438 #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 439 +#define _LOAD_ATTR_METHOD_LAZY_DICT 440 +#define _LOAD_ATTR_METHOD_NO_DICT 441 +#define _LOAD_ATTR_METHOD_WITH_VALUES 442 +#define _LOAD_ATTR_MODULE 443 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 444 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 445 +#define _LOAD_ATTR_PROPERTY_FRAME 446 +#define _LOAD_ATTR_SLOT 447 +#define _LOAD_ATTR_WITH_HINT 448 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 445 +#define _LOAD_BYTECODE 449 #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 450 +#define _LOAD_CONST_INLINE_BORROW 451 +#define _LOAD_CONST_UNDER_INLINE 452 +#define _LOAD_CONST_UNDER_INLINE_BORROW 453 #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 454 +#define _LOAD_FAST_0 455 +#define _LOAD_FAST_1 456 +#define _LOAD_FAST_2 457 +#define _LOAD_FAST_3 458 +#define _LOAD_FAST_4 459 +#define _LOAD_FAST_5 460 +#define _LOAD_FAST_6 461 +#define _LOAD_FAST_7 462 #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 463 +#define _LOAD_FAST_BORROW_0 464 +#define _LOAD_FAST_BORROW_1 465 +#define _LOAD_FAST_BORROW_2 466 +#define _LOAD_FAST_BORROW_3 467 +#define _LOAD_FAST_BORROW_4 468 +#define _LOAD_FAST_BORROW_5 469 +#define _LOAD_FAST_BORROW_6 470 +#define _LOAD_FAST_BORROW_7 471 #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 472 +#define _LOAD_GLOBAL_BUILTINS 473 +#define _LOAD_GLOBAL_MODULE 474 #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 475 +#define _LOAD_SMALL_INT_0 476 +#define _LOAD_SMALL_INT_1 477 +#define _LOAD_SMALL_INT_2 478 +#define _LOAD_SMALL_INT_3 479 +#define _LOAD_SPECIAL 480 #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 481 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 478 +#define _MAKE_WARM 482 #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 483 +#define _MAYBE_EXPAND_METHOD_KW 484 +#define _MONITOR_CALL 485 +#define _MONITOR_CALL_KW 486 +#define _MONITOR_FOR_ITER 487 +#define _MONITOR_JUMP_BACKWARD 488 +#define _MONITOR_RESUME 489 #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 490 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW 491 +#define _POP_CALL_ONE 492 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW 493 +#define _POP_CALL_TWO 494 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW 495 #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 496 +#define _POP_JUMP_IF_TRUE 497 #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 498 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 499 +#define _POP_TWO 500 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 501 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 497 +#define _PUSH_FRAME 502 #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 503 +#define _PY_FRAME_GENERAL 504 +#define _PY_FRAME_KW 505 +#define _QUICKEN_RESUME 506 +#define _REPLACE_WITH_TRUE 507 #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 508 +#define _SEND 509 +#define _SEND_GEN_FRAME 510 #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 511 +#define _STORE_ATTR 512 +#define _STORE_ATTR_INSTANCE_VALUE 513 +#define _STORE_ATTR_SLOT 514 +#define _STORE_ATTR_WITH_HINT 515 #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 516 +#define _STORE_FAST_0 517 +#define _STORE_FAST_1 518 +#define _STORE_FAST_2 519 +#define _STORE_FAST_3 520 +#define _STORE_FAST_4 521 +#define _STORE_FAST_5 522 +#define _STORE_FAST_6 523 +#define _STORE_FAST_7 524 #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 525 +#define _STORE_SUBSCR 526 +#define _STORE_SUBSCR_DICT 527 +#define _STORE_SUBSCR_LIST_INT 528 #define _SWAP SWAP -#define _TIER2_RESUME_CHECK 524 -#define _TO_BOOL 525 +#define _TIER2_RESUME_CHECK 529 +#define _TO_BOOL 530 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 526 +#define _TO_BOOL_LIST 531 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 527 +#define _TO_BOOL_STR 532 #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 533 +#define _UNPACK_SEQUENCE_LIST 534 +#define _UNPACK_SEQUENCE_TUPLE 535 +#define _UNPACK_SEQUENCE_TWO_TUPLE 536 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 531 +#define MAX_UOP_ID 536 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index b08909e72c4f43..7871d3291ce6e8 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -202,7 +202,12 @@ 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_INDEX] = 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, + [_ITER_CHECK_INDEX] = HAS_DEOPT_FLAG, + [_FOR_ITER_INDEX_TIER_TWO] = HAS_EXIT_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, [_GUARD_NOT_EXHAUSTED_LIST] = HAS_EXIT_FLAG, @@ -212,7 +217,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, @@ -430,11 +435,15 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { [_FORMAT_SIMPLE] = "_FORMAT_SIMPLE", [_FORMAT_WITH_SPEC] = "_FORMAT_WITH_SPEC", [_FOR_ITER_GEN_FRAME] = "_FOR_ITER_GEN_FRAME", + [_FOR_ITER_INDEX_TIER_TWO] = "_FOR_ITER_INDEX_TIER_TWO", [_FOR_ITER_TIER_TWO] = "_FOR_ITER_TIER_TWO", [_GET_AITER] = "_GET_AITER", [_GET_ANEXT] = "_GET_ANEXT", [_GET_AWAITABLE] = "_GET_AWAITABLE", [_GET_ITER] = "_GET_ITER", + [_GET_ITER_INDEX] = "_GET_ITER_INDEX", + [_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", @@ -486,6 +495,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = { [_INSERT_NULL] = "_INSERT_NULL", [_IS_NONE] = "_IS_NONE", [_IS_OP] = "_IS_OP", + [_ITER_CHECK_INDEX] = "_ITER_CHECK_INDEX", [_ITER_CHECK_LIST] = "_ITER_CHECK_LIST", [_ITER_CHECK_RANGE] = "_ITER_CHECK_RANGE", [_ITER_CHECK_TUPLE] = "_ITER_CHECK_TUPLE", @@ -1004,8 +1014,18 @@ int _PyUop_num_popped(int opcode, int oparg) return 0; case _GET_ITER: return 1; + case _GET_ITER_SELF: + return 0; + case _GET_ITER_INDEX: + return 0; + case _GET_ITER_RANGE: + return 1; case _GET_YIELD_FROM_ITER: return 1; + case _ITER_CHECK_INDEX: + return 0; + case _FOR_ITER_INDEX_TIER_TWO: + return 0; case _FOR_ITER_TIER_TWO: return 0; case _ITER_CHECK_LIST: diff --git a/Include/object.h b/Include/object.h index c75e9db0cbd935..846f761cd5effd 100644 --- a/Include/object.h +++ b/Include/object.h @@ -367,6 +367,7 @@ typedef Py_hash_t (*hashfunc)(PyObject *); typedef PyObject *(*richcmpfunc) (PyObject *, PyObject *, int); typedef PyObject *(*getiterfunc) (PyObject *); typedef PyObject *(*iternextfunc) (PyObject *); +typedef PyObject *(*iterindexfunc) (PyObject *, Py_ssize_t); typedef PyObject *(*descrgetfunc) (PyObject *, PyObject *, PyObject *); typedef int (*descrsetfunc) (PyObject *, PyObject *, PyObject *); typedef int (*initproc)(PyObject *, PyObject *, PyObject *); diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index 1d5c74adefcd35..1818c3c4e8900e 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -175,60 +175,64 @@ extern "C" { #define CONTAINS_OP_DICT 169 #define CONTAINS_OP_SET 170 #define FOR_ITER_GEN 171 -#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 FOR_ITER_INDEX 172 +#define FOR_ITER_LIST 173 +#define FOR_ITER_RANGE 174 +#define FOR_ITER_TUPLE 175 +#define GET_ITER_INDEX 176 +#define GET_ITER_RANGE 177 +#define GET_ITER_SELF 178 +#define JUMP_BACKWARD_JIT 179 +#define JUMP_BACKWARD_NO_JIT 180 +#define LOAD_ATTR_CLASS 181 +#define LOAD_ATTR_CLASS_WITH_METACLASS_CHECK 182 +#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 183 +#define LOAD_ATTR_INSTANCE_VALUE 184 +#define LOAD_ATTR_METHOD_LAZY_DICT 185 +#define LOAD_ATTR_METHOD_NO_DICT 186 +#define LOAD_ATTR_METHOD_WITH_VALUES 187 +#define LOAD_ATTR_MODULE 188 +#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 189 +#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 190 +#define LOAD_ATTR_PROPERTY 191 +#define LOAD_ATTR_SLOT 192 +#define LOAD_ATTR_WITH_HINT 193 +#define LOAD_GLOBAL_BUILTIN 194 +#define LOAD_GLOBAL_MODULE 195 +#define LOAD_SUPER_ATTR_ATTR 196 +#define LOAD_SUPER_ATTR_METHOD 197 +#define RESUME_CHECK 198 +#define SEND_GEN 199 +#define STORE_ATTR_INSTANCE_VALUE 200 +#define STORE_ATTR_SLOT 201 +#define STORE_ATTR_WITH_HINT 202 +#define STORE_SUBSCR_DICT 203 +#define STORE_SUBSCR_LIST_INT 204 +#define TO_BOOL_ALWAYS_TRUE 205 +#define TO_BOOL_BOOL 206 +#define TO_BOOL_INT 207 +#define TO_BOOL_LIST 208 +#define TO_BOOL_NONE 209 +#define TO_BOOL_STR 210 +#define UNPACK_SEQUENCE_LIST 211 +#define UNPACK_SEQUENCE_TUPLE 212 +#define UNPACK_SEQUENCE_TWO_TUPLE 213 #define INSTRUMENTED_END_FOR 234 #define INSTRUMENTED_POP_ITER 235 #define INSTRUMENTED_END_SEND 236 -#define INSTRUMENTED_FOR_ITER 237 -#define INSTRUMENTED_INSTRUCTION 238 -#define INSTRUMENTED_JUMP_FORWARD 239 -#define INSTRUMENTED_NOT_TAKEN 240 -#define INSTRUMENTED_POP_JUMP_IF_TRUE 241 -#define INSTRUMENTED_POP_JUMP_IF_FALSE 242 -#define INSTRUMENTED_POP_JUMP_IF_NONE 243 -#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 244 -#define INSTRUMENTED_RESUME 245 -#define INSTRUMENTED_RETURN_VALUE 246 -#define INSTRUMENTED_YIELD_VALUE 247 -#define INSTRUMENTED_END_ASYNC_FOR 248 -#define INSTRUMENTED_LOAD_SUPER_ATTR 249 +#define INSTRUMENTED_INSTRUCTION 237 +#define INSTRUMENTED_JUMP_FORWARD 238 +#define INSTRUMENTED_NOT_TAKEN 239 +#define INSTRUMENTED_POP_JUMP_IF_TRUE 240 +#define INSTRUMENTED_POP_JUMP_IF_FALSE 241 +#define INSTRUMENTED_POP_JUMP_IF_NONE 242 +#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 243 +#define INSTRUMENTED_RESUME 244 +#define INSTRUMENTED_RETURN_VALUE 245 +#define INSTRUMENTED_YIELD_VALUE 246 +#define INSTRUMENTED_END_ASYNC_FOR 247 +#define INSTRUMENTED_LOAD_SUPER_ATTR 248 +#define INSTRUMENTED_FOR_ITER 249 #define INSTRUMENTED_CALL 250 #define INSTRUMENTED_CALL_KW 251 #define INSTRUMENTED_CALL_FUNCTION_EX 252 diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index f168d169a32948..67e8156c11155d 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -84,11 +84,17 @@ "JUMP_BACKWARD_NO_JIT", "JUMP_BACKWARD_JIT", ], + "GET_ITER": [ + "GET_ITER_INDEX", + "GET_ITER_SELF", + "GET_ITER_RANGE", + ], "FOR_ITER": [ "FOR_ITER_LIST", "FOR_ITER_TUPLE", "FOR_ITER_RANGE", "FOR_ITER_GEN", + "FOR_ITER_INDEX", ], "CALL": [ "CALL_BOUND_METHOD_EXACT_ARGS", @@ -164,44 +170,48 @@ 'CONTAINS_OP_DICT': 169, 'CONTAINS_OP_SET': 170, 'FOR_ITER_GEN': 171, - '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, + 'FOR_ITER_INDEX': 172, + 'FOR_ITER_LIST': 173, + 'FOR_ITER_RANGE': 174, + 'FOR_ITER_TUPLE': 175, + 'GET_ITER_INDEX': 176, + 'GET_ITER_RANGE': 177, + 'GET_ITER_SELF': 178, + 'JUMP_BACKWARD_JIT': 179, + 'JUMP_BACKWARD_NO_JIT': 180, + 'LOAD_ATTR_CLASS': 181, + 'LOAD_ATTR_CLASS_WITH_METACLASS_CHECK': 182, + 'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 183, + 'LOAD_ATTR_INSTANCE_VALUE': 184, + 'LOAD_ATTR_METHOD_LAZY_DICT': 185, + 'LOAD_ATTR_METHOD_NO_DICT': 186, + 'LOAD_ATTR_METHOD_WITH_VALUES': 187, + 'LOAD_ATTR_MODULE': 188, + 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 189, + 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 190, + 'LOAD_ATTR_PROPERTY': 191, + 'LOAD_ATTR_SLOT': 192, + 'LOAD_ATTR_WITH_HINT': 193, + 'LOAD_GLOBAL_BUILTIN': 194, + 'LOAD_GLOBAL_MODULE': 195, + 'LOAD_SUPER_ATTR_ATTR': 196, + 'LOAD_SUPER_ATTR_METHOD': 197, + 'RESUME_CHECK': 198, + 'SEND_GEN': 199, + 'STORE_ATTR_INSTANCE_VALUE': 200, + 'STORE_ATTR_SLOT': 201, + 'STORE_ATTR_WITH_HINT': 202, + 'STORE_SUBSCR_DICT': 203, + 'STORE_SUBSCR_LIST_INT': 204, + 'TO_BOOL_ALWAYS_TRUE': 205, + 'TO_BOOL_BOOL': 206, + 'TO_BOOL_INT': 207, + 'TO_BOOL_LIST': 208, + 'TO_BOOL_NONE': 209, + 'TO_BOOL_STR': 210, + 'UNPACK_SEQUENCE_LIST': 211, + 'UNPACK_SEQUENCE_TUPLE': 212, + 'UNPACK_SEQUENCE_TWO_TUPLE': 213, } opmap = { @@ -331,19 +341,19 @@ 'INSTRUMENTED_END_FOR': 234, 'INSTRUMENTED_POP_ITER': 235, 'INSTRUMENTED_END_SEND': 236, - 'INSTRUMENTED_FOR_ITER': 237, - 'INSTRUMENTED_INSTRUCTION': 238, - 'INSTRUMENTED_JUMP_FORWARD': 239, - 'INSTRUMENTED_NOT_TAKEN': 240, - 'INSTRUMENTED_POP_JUMP_IF_TRUE': 241, - 'INSTRUMENTED_POP_JUMP_IF_FALSE': 242, - 'INSTRUMENTED_POP_JUMP_IF_NONE': 243, - 'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 244, - 'INSTRUMENTED_RESUME': 245, - 'INSTRUMENTED_RETURN_VALUE': 246, - 'INSTRUMENTED_YIELD_VALUE': 247, - 'INSTRUMENTED_END_ASYNC_FOR': 248, - 'INSTRUMENTED_LOAD_SUPER_ATTR': 249, + 'INSTRUMENTED_INSTRUCTION': 237, + 'INSTRUMENTED_JUMP_FORWARD': 238, + 'INSTRUMENTED_NOT_TAKEN': 239, + 'INSTRUMENTED_POP_JUMP_IF_TRUE': 240, + 'INSTRUMENTED_POP_JUMP_IF_FALSE': 241, + 'INSTRUMENTED_POP_JUMP_IF_NONE': 242, + 'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 243, + 'INSTRUMENTED_RESUME': 244, + 'INSTRUMENTED_RETURN_VALUE': 245, + 'INSTRUMENTED_YIELD_VALUE': 246, + 'INSTRUMENTED_END_ASYNC_FOR': 247, + 'INSTRUMENTED_LOAD_SUPER_ATTR': 248, + 'INSTRUMENTED_FOR_ITER': 249, 'INSTRUMENTED_CALL': 250, 'INSTRUMENTED_CALL_KW': 251, 'INSTRUMENTED_CALL_FUNCTION_EX': 252, 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..a5c37490f7adb4 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_INDEX 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..58d97147f8e772 100644 --- a/Lib/test/test_opcache.py +++ b/Lib/test/test_opcache.py @@ -1832,23 +1832,113 @@ 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_INDEX") + 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_INDEX") + self.assert_no_opcode(for_iter_tuple, "GET_ITER") + + s = "hello" + def for_iter_str(): + n = 0 + while n < _testinternalcapi.SPECIALIZATION_THRESHOLD: + n += 1 + for c in s: + self.assertIn(c, s) + + for_iter_str() + self.assert_specialized(for_iter_str, "GET_ITER_INDEX") + self.assert_no_opcode(for_iter_str, "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/Lib/test/test_sys.py b/Lib/test/test_sys.py index 39e62027f03e5a..e116e0c5ce042e 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1764,7 +1764,7 @@ def delx(self): del self.__x check((1,2,3), vsize('') + self.P + 3*self.P) # type # static type: PyTypeObject - fmt = 'P2nPI13Pl4Pn9Pn12PIPc' + fmt = 'P2nPI13Pl4Pn9Pn12PIPcsP' s = vsize(fmt) check(int, s) typeid = 'n' if support.Py_GIL_DISABLED else '' 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/bytearrayobject.c b/Objects/bytearrayobject.c index b5d5ca9178ebdb..1b176a73052498 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -2795,6 +2795,27 @@ Construct a mutable bytearray object from:\n\ static PyObject *bytearray_iter(PyObject *seq); + +static PyObject * +bytearray_iterindex(PyObject *self, Py_ssize_t index) +{ + + assert(PyByteArray_Check(self)); + int val; + Py_BEGIN_CRITICAL_SECTION(self); + if (index < 0 || index >= Py_SIZE(self)) { + val = -1; + } + else { + val = (unsigned char)PyByteArray_AS_STRING(self)[index]; + } + Py_END_CRITICAL_SECTION(); + if (val < 0) { + return NULL; + } + return _PyLong_FromUnsignedChar((unsigned char)val); +} + PyTypeObject PyByteArray_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "bytearray", @@ -2837,6 +2858,7 @@ PyTypeObject PyByteArray_Type = { PyType_GenericNew, /* tp_new */ PyObject_Free, /* tp_free */ .tp_version_tag = _Py_TYPE_VERSION_BYTEARRAY, + .tp_iterindex = bytearray_iterindex, }; /*********************** Bytearray Iterator ****************************/ diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index 87ea1162e03513..bacaea31647ef2 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -3091,6 +3091,17 @@ Construct an immutable array of bytes from:\n\ static PyObject *bytes_iter(PyObject *seq); +static PyObject * +bytes_iterindex(PyObject *self, Py_ssize_t index) +{ + assert(PyBytes_Check(self)); + + if (index < 0 || index >= PyBytes_GET_SIZE(self)) { + return NULL; + } + return _PyLong_FromUnsignedChar((unsigned char)((PyBytesObject*)self)->ob_sval[index]); +} + PyTypeObject PyBytes_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "bytes", @@ -3134,6 +3145,7 @@ PyTypeObject PyBytes_Type = { bytes_new, /* tp_new */ PyObject_Free, /* tp_free */ .tp_version_tag = _Py_TYPE_VERSION_BYTES, + .tp_iterindex = bytes_iterindex, }; void diff --git a/Objects/listobject.c b/Objects/listobject.c index c5895645a2dd12..d29d23f4460598 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -3863,6 +3863,14 @@ list_ass_subscript(PyObject *self, PyObject *item, PyObject *value) return res; } + +static PyObject * +list_iterindex(PyObject *self, Py_ssize_t index) +{ + return list_get_item_ref((PyListObject *)self, index); + +} + static PyMappingMethods list_as_mapping = { list_length, list_subscript, @@ -3913,6 +3921,7 @@ PyTypeObject PyList_Type = { PyObject_GC_Del, /* tp_free */ .tp_vectorcall = list_vectorcall, .tp_version_tag = _Py_TYPE_VERSION_LIST, + .tp_iterindex = list_iterindex, }; /*********************** List 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/Objects/tupleobject.c b/Objects/tupleobject.c index 9b31758485ca5e..59e921e63b0ee4 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -833,6 +833,16 @@ tuple_subscript(PyObject *op, PyObject* item) } } +static PyObject * +tuple_iterindex(PyObject *self, Py_ssize_t index) +{ + if (index < 0 || index >= PyTuple_GET_SIZE(self)) { + return NULL; + } + PyObject *item = PyTuple_GET_ITEM(self, index); + return Py_NewRef(item); +} + /*[clinic input] tuple.__getnewargs__ [clinic start generated code]*/ @@ -904,6 +914,7 @@ PyTypeObject PyTuple_Type = { PyObject_GC_Del, /* tp_free */ .tp_vectorcall = tuple_vectorcall, .tp_version_tag = _Py_TYPE_VERSION_TUPLE, + .tp_iterindex = tuple_iterindex, }; /* The following function breaks the notion that tuples are immutable: diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 5c2308a012142a..3f66699b7caf43 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -15735,6 +15735,18 @@ errors defaults to 'strict'."); static PyObject *unicode_iter(PyObject *seq); +static PyObject * +unicode_iterindex(PyObject *self, Py_ssize_t index) +{ + if (index < 0 || index >= PyUnicode_GET_LENGTH(self)) { + return NULL; + } + int kind = PyUnicode_KIND(self); + const void *data = PyUnicode_DATA(self); + Py_UCS4 chr = PyUnicode_READ(kind, data, index); + return unicode_char(chr); +} + PyTypeObject PyUnicode_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "str", /* tp_name */ @@ -15779,6 +15791,7 @@ PyTypeObject PyUnicode_Type = { unicode_new, /* tp_new */ PyObject_Free, /* tp_free */ .tp_vectorcall = unicode_vectorcall, + .tp_iterindex = unicode_iterindex, }; /* Initialize the Unicode implementation */ 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 032e76f72af42c..0d056bdacb38b0 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3051,26 +3051,79 @@ 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_INDEX, + 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 /* before: [obj]; after [getiter(obj)] */ PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { + if (tp->tp_iterindex != NULL) { iter = iterable; DEAD(iterable); 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_INDEX, (unused/1, iter -- iter, index0)) { + PyTypeObject *tp = PyStackRef_TYPE(iter); + DEOPT_IF(tp->tp_iterindex == NULL); + 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); @@ -3113,13 +3166,14 @@ dummy_func( FOR_ITER_TUPLE, FOR_ITER_RANGE, FOR_ITER_GEN, + FOR_ITER_INDEX, }; - specializing op(_SPECIALIZE_FOR_ITER, (counter/1, iter, null_or_index -- iter, null_or_index)) { + specializing op(_SPECIALIZE_FOR_ITER, (counter/1, iter, maybe_index -- iter, maybe_index)) { #if ENABLE_SPECIALIZATION_FT if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; - _Py_Specialize_ForIter(iter, null_or_index, next_instr, oparg); + _Py_Specialize_ForIter(iter, maybe_index, next_instr, oparg); DISPATCH_SAME_OPARG(); } OPCODE_DEFERRED_INC(FOR_ITER); @@ -3127,8 +3181,8 @@ dummy_func( #endif /* ENABLE_SPECIALIZATION_FT */ } - replaced op(_FOR_ITER, (iter, null_or_index -- iter, null_or_index, next)) { - _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index); + replaced op(_FOR_ITER, (iter, null_or_index[1] -- iter, null_or_index[1], next)) { + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, null_or_index); if (!PyStackRef_IsValid(item)) { if (PyStackRef_IsError(item)) { ERROR_NO_POP(); @@ -3140,8 +3194,42 @@ dummy_func( next = item; } - op(_FOR_ITER_TIER_TWO, (iter, null_or_index -- iter, null_or_index, next)) { - _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index); + op(_ITER_CHECK_INDEX, (iter, null_or_index -- iter, null_or_index)) { + DEOPT_IF(PyStackRef_IsNull(null_or_index)); + DEOPT_IF(PyStackRef_IsTaggedInt(iter)); + } + + replaced op(_FOR_ITER_INDEX, (iter, null_or_index -- iter, null_or_index, next)) { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + assert(Py_TYPE(iter_o)->tp_iterindex != NULL); + PyObject *item = Py_TYPE(iter_o)->tp_iterindex(iter_o, PyStackRef_UntagInt(null_or_index)); + if (item == NULL) { + assert(!_PyErr_Occurred(tstate)); + // Jump forward by oparg and skip the following END_FOR + JUMPBY(oparg + 1); + DISPATCH(); + } + next = PyStackRef_FromPyObjectSteal(item); + } + + op(_FOR_ITER_INDEX_TIER_TWO, (iter, null_or_index -- iter, null_or_index, next)) { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + assert(Py_TYPE(iter_o)->tp_iterindex != NULL); + PyObject *item = Py_TYPE(iter_o)->tp_iterindex(iter_o, PyStackRef_UntagInt(null_or_index)); + if (item == NULL) { + /* The translator sets the deopt target just past the matching END_FOR */ + EXIT_IF(true); + } + next = PyStackRef_FromPyObjectSteal(item); + } + + macro(FOR_ITER_INDEX) = + unused/1 + + _ITER_CHECK_INDEX + + _FOR_ITER_INDEX; + + op(_FOR_ITER_TIER_TWO, (iter, null_or_index[1] -- iter, null_or_index[1], next)) { + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, null_or_index); if (!PyStackRef_IsValid(item)) { if (PyStackRef_IsError(item)) { ERROR_NO_POP(); @@ -3153,29 +3241,19 @@ dummy_func( next = item; } - macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER; - - inst(INSTRUMENTED_FOR_ITER, (unused/1, iter, null_or_index -- iter, null_or_index, next)) { - _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index); - if (!PyStackRef_IsValid(item)) { - if (PyStackRef_IsError(item)) { - ERROR_NO_POP(); - } - // Jump forward by oparg and skip the following END_FOR - JUMPBY(oparg + 1); - DISPATCH(); - } - next = item; + op(_MONITOR_FOR_ITER, ( -- )) { INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT); } + macro(INSTRUMENTED_FOR_ITER) = unused/1 + _FOR_ITER + _MONITOR_FOR_ITER; + 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 } @@ -3257,18 +3335,15 @@ 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)); } replaced op(_ITER_JUMP_TUPLE, (iter, null_or_index -- iter, null_or_index)) { - PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter); - (void)tuple_o; - assert(Py_TYPE(tuple_o) == &PyTuple_Type); + assert(PyStackRef_TYPE(iter) == &PyTuple_Type); STAT_INC(FOR_ITER, hit); + PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter); if ((size_t)PyStackRef_UntagInt(null_or_index) >= (size_t)PyTuple_GET_SIZE(tuple_o)) { - null_or_index = PyStackRef_TagInt(-1); /* Jump forward oparg, then skip following END_FOR instruction */ JUMPBY(oparg + 1); DISPATCH(); @@ -3298,21 +3373,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(); @@ -3321,24 +3386,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) = @@ -3348,8 +3404,8 @@ dummy_func( _ITER_NEXT_RANGE; op(_FOR_ITER_GEN_FRAME, (iter, null -- iter, null, gen_frame)) { + 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..a8153bebde6f8e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3440,47 +3440,62 @@ _PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *na } static _PyStackRef -foriter_next(PyObject *seq, _PyStackRef index) -{ - assert(PyStackRef_IsTaggedInt(index)); - assert(PyTuple_CheckExact(seq) || PyList_CheckExact(seq)); - intptr_t i = PyStackRef_UntagInt(index); - if (PyTuple_CheckExact(seq)) { - size_t size = PyTuple_GET_SIZE(seq); - if ((size_t)i >= size) { - return PyStackRef_NULL; - } - return PyStackRef_FromPyObjectNew(PyTuple_GET_ITEM(seq, i)); - } - PyObject *item = _PyList_GetItemRef((PyListObject *)seq, i); - if (item == NULL) { - return PyStackRef_NULL; - } - return PyStackRef_FromPyObjectSteal(item); +not_iterator(PyObject *obj) +{ + PyErr_Format(PyExc_TypeError, + "'%.200s' object is not an async iterator", + Py_TYPE(obj)->tp_name); + return PyStackRef_ERROR; } -_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); - } - PyObject *next_o = (*Py_TYPE(iter_o)->tp_iternext)(iter_o); - if (next_o == NULL) { - if (_PyErr_Occurred(tstate)) { - if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { - _PyEval_MonitorRaise(tstate, frame, frame->instr_ptr); - _PyErr_Clear(tstate); + if (PyStackRef_IsNull(index)) { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + iternextfunc func = Py_TYPE(iter_o)->tp_iternext; + if (func == NULL) { + return not_iterator(iter_o); + } + PyObject *next_o = func(iter_o); + if (next_o == NULL) { + if (_PyErr_Occurred(tstate)) { + if (_PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) { + _PyEval_MonitorRaise(tstate, frame, frame->instr_ptr); + _PyErr_Clear(tstate); + } + else { + return PyStackRef_ERROR; + } } - else { - return PyStackRef_ERROR; + return PyStackRef_NULL; + } + return PyStackRef_FromPyObjectSteal(next_o); + } + else { + assert(PyStackRef_IsTaggedInt(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); + assert(Py_TYPE(iter_o)->tp_iterindex != NULL); + PyObject *item = Py_TYPE(iter_o)->tp_iterindex(iter_o, PyStackRef_UntagInt(index)); + *index_ptr = PyStackRef_IncrementTaggedIntNoOverflow(index); + if (item == NULL) { + assert(!_PyErr_Occurred(tstate)); + return PyStackRef_NULL; } + return PyStackRef_FromPyObjectSteal(item); } - return PyStackRef_NULL; } - return PyStackRef_FromPyObjectSteal(next_o); } /* Check if a 'cls' provides the given special method. */ diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 4f772f916d1152..4d7778da6ed301 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4198,24 +4198,40 @@ #endif PyTypeObject *tp = PyStackRef_TYPE(iterable); - if (tp == &PyTuple_Type || tp == &PyList_Type) { + if (tp->tp_iterindex != NULL) { iter = iterable; 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; @@ -4225,6 +4241,67 @@ 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_INDEX: { + _PyStackRef iter; + _PyStackRef index0; + iter = stack_pointer[-1]; + PyTypeObject *tp = PyStackRef_TYPE(iter); + if (tp->tp_iterindex == NULL) { + 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; @@ -4265,14 +4342,56 @@ /* _FOR_ITER is not a viable micro-op for tier 2 because it is replaced */ - case _FOR_ITER_TIER_TWO: { + case _ITER_CHECK_INDEX: { + _PyStackRef null_or_index; + _PyStackRef iter; + null_or_index = stack_pointer[-1]; + iter = stack_pointer[-2]; + if (PyStackRef_IsNull(null_or_index)) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + if (PyStackRef_IsTaggedInt(iter)) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + break; + } + + /* _FOR_ITER_INDEX is not a viable micro-op for tier 2 because it is replaced */ + + case _FOR_ITER_INDEX_TIER_TWO: { _PyStackRef null_or_index; _PyStackRef iter; _PyStackRef next; null_or_index = stack_pointer[-1]; iter = stack_pointer[-2]; + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + assert(Py_TYPE(iter_o)->tp_iterindex != NULL); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *item = Py_TYPE(iter_o)->tp_iterindex(iter_o, PyStackRef_UntagInt(null_or_index)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (item == NULL) { + if (true) { + UOP_STAT_INC(uopcode, miss); + JUMP_TO_JUMP_TARGET(); + } + } + next = PyStackRef_FromPyObjectSteal(item); + stack_pointer[0] = next; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + + case _FOR_ITER_TIER_TWO: { + _PyStackRef *null_or_index; + _PyStackRef iter; + _PyStackRef next; + null_or_index = &stack_pointer[-1]; + iter = stack_pointer[-2]; _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index); + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, null_or_index); stack_pointer = _PyFrame_GetStackPointer(frame); if (!PyStackRef_IsValid(item)) { if (PyStackRef_IsError(item)) { @@ -4284,27 +4403,26 @@ } } next = item; - stack_pointer[-1] = null_or_index; stack_pointer[0] = next; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); break; } - /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 because it is instrumented */ + /* _MONITOR_FOR_ITER is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ case _ITER_CHECK_LIST: { _PyStackRef null_or_index; _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(); @@ -4369,8 +4487,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(); } @@ -4416,28 +4533,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(); } @@ -4445,23 +4555,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()); @@ -4473,11 +4575,11 @@ _PyStackRef 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 5ac519bb1b6093..de0b7a0337eb7d 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -5734,11 +5734,12 @@ _Py_CODEUNIT* const this_instr = next_instr - 2; (void)this_instr; _PyStackRef iter; - _PyStackRef null_or_index; + _PyStackRef maybe_index; + _PyStackRef *null_or_index; _PyStackRef next; // _SPECIALIZE_FOR_ITER { - null_or_index = stack_pointer[-1]; + maybe_index = stack_pointer[-1]; iter = stack_pointer[-2]; uint16_t counter = read_u16(&this_instr[1].cache); (void)counter; @@ -5746,7 +5747,7 @@ if (ADAPTIVE_COUNTER_TRIGGERS(counter)) { next_instr = this_instr; _PyFrame_SetStackPointer(frame, stack_pointer); - _Py_Specialize_ForIter(iter, null_or_index, next_instr, oparg); + _Py_Specialize_ForIter(iter, maybe_index, next_instr, oparg); stack_pointer = _PyFrame_GetStackPointer(frame); DISPATCH_SAME_OPARG(); } @@ -5756,20 +5757,20 @@ } // _FOR_ITER { + null_or_index = &stack_pointer[-1]; + iter = stack_pointer[-2]; _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index); + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, null_or_index); stack_pointer = _PyFrame_GetStackPointer(frame); if (!PyStackRef_IsValid(item)) { if (PyStackRef_IsError(item)) { JUMP_TO_LABEL(error); } JUMPBY(oparg + 1); - stack_pointer[-1] = null_or_index; DISPATCH(); } next = item; } - stack_pointer[-1] = null_or_index; stack_pointer[0] = next; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); @@ -5802,12 +5803,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); @@ -5847,6 +5848,56 @@ DISPATCH(); } + TARGET(FOR_ITER_INDEX) { + #if Py_TAIL_CALL_INTERP + int opcode = FOR_ITER_INDEX; + (void)(opcode); + #endif + _Py_CODEUNIT* const this_instr = next_instr; + (void)this_instr; + frame->instr_ptr = next_instr; + next_instr += 2; + INSTRUCTION_STATS(FOR_ITER_INDEX); + 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_INDEX + { + null_or_index = stack_pointer[-1]; + iter = stack_pointer[-2]; + if (PyStackRef_IsNull(null_or_index)) { + UPDATE_MISS_STATS(FOR_ITER); + assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); + JUMP_TO_PREDICTED(FOR_ITER); + } + if (PyStackRef_IsTaggedInt(iter)) { + UPDATE_MISS_STATS(FOR_ITER); + assert(_PyOpcode_Deopt[opcode] == (FOR_ITER)); + JUMP_TO_PREDICTED(FOR_ITER); + } + } + // _FOR_ITER_INDEX + { + PyObject *iter_o = PyStackRef_AsPyObjectBorrow(iter); + assert(Py_TYPE(iter_o)->tp_iterindex != NULL); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *item = Py_TYPE(iter_o)->tp_iterindex(iter_o, PyStackRef_UntagInt(null_or_index)); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (item == NULL) { + assert(!_PyErr_Occurred(tstate)); + JUMPBY(oparg + 1); + DISPATCH(); + } + next = PyStackRef_FromPyObjectSteal(item); + } + stack_pointer[0] = next; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + DISPATCH(); + } + TARGET(FOR_ITER_LIST) { #if Py_TAIL_CALL_INTERP int opcode = FOR_ITER_LIST; @@ -5866,14 +5917,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)); @@ -5943,55 +5994,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()); @@ -6017,8 +6048,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); @@ -6027,14 +6057,11 @@ } // _ITER_JUMP_TUPLE { - PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter); - (void)tuple_o; - assert(Py_TYPE(tuple_o) == &PyTuple_Type); + assert(PyStackRef_TYPE(iter) == &PyTuple_Type); STAT_INC(FOR_ITER, hit); + PyObject *tuple_o = PyStackRef_AsPyObjectBorrow(iter); if ((size_t)PyStackRef_UntagInt(null_or_index) >= (size_t)PyTuple_GET_SIZE(tuple_o)) { - null_or_index = PyStackRef_TagInt(-1); JUMPBY(oparg + 1); - stack_pointer[-1] = null_or_index; DISPATCH(); } } @@ -6174,38 +6201,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->tp_iterindex != NULL) { + 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; @@ -6214,6 +6280,104 @@ DISPATCH(); } + TARGET(GET_ITER_INDEX) { + #if Py_TAIL_CALL_INTERP + int opcode = GET_ITER_INDEX; + (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_INDEX); + 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->tp_iterindex == NULL) { + 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; @@ -7035,25 +7199,29 @@ next_instr += 2; INSTRUCTION_STATS(INSTRUMENTED_FOR_ITER); _PyStackRef iter; - _PyStackRef null_or_index; + _PyStackRef *null_or_index; _PyStackRef next; /* Skip 1 cache entry */ - null_or_index = stack_pointer[-1]; - iter = stack_pointer[-2]; - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, &null_or_index); - stack_pointer = _PyFrame_GetStackPointer(frame); - if (!PyStackRef_IsValid(item)) { - if (PyStackRef_IsError(item)) { - JUMP_TO_LABEL(error); + // _FOR_ITER + { + null_or_index = &stack_pointer[-1]; + iter = stack_pointer[-2]; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyStackRef item = _PyForIter_VirtualIteratorNext(tstate, frame, iter, null_or_index); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (!PyStackRef_IsValid(item)) { + if (PyStackRef_IsError(item)) { + JUMP_TO_LABEL(error); + } + JUMPBY(oparg + 1); + DISPATCH(); } - JUMPBY(oparg + 1); - stack_pointer[-1] = null_or_index; - DISPATCH(); + next = item; + } + // _MONITOR_FOR_ITER + { + INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT); } - next = item; - INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT); - stack_pointer[-1] = null_or_index; stack_pointer[0] = next; stack_pointer += 1; assert(WITHIN_STACK_BOUNDS()); diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 1d6dcddab4b12d..fe47ee5af00993 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -172,9 +172,13 @@ static void *opcode_targets[256] = { &&TARGET_CONTAINS_OP_DICT, &&TARGET_CONTAINS_OP_SET, &&TARGET_FOR_ITER_GEN, + &&TARGET_FOR_ITER_INDEX, &&TARGET_FOR_ITER_LIST, &&TARGET_FOR_ITER_RANGE, &&TARGET_FOR_ITER_TUPLE, + &&TARGET_GET_ITER_INDEX, + &&TARGET_GET_ITER_RANGE, + &&TARGET_GET_ITER_SELF, &&TARGET_JUMP_BACKWARD_JIT, &&TARGET_JUMP_BACKWARD_NO_JIT, &&TARGET_LOAD_ATTR_CLASS, @@ -230,14 +234,9 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_POP_ITER, &&TARGET_INSTRUMENTED_END_SEND, - &&TARGET_INSTRUMENTED_FOR_ITER, &&TARGET_INSTRUMENTED_INSTRUCTION, &&TARGET_INSTRUMENTED_JUMP_FORWARD, &&TARGET_INSTRUMENTED_NOT_TAKEN, @@ -250,6 +249,7 @@ static void *opcode_targets[256] = { &&TARGET_INSTRUMENTED_YIELD_VALUE, &&TARGET_INSTRUMENTED_END_ASYNC_FOR, &&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR, + &&TARGET_INSTRUMENTED_FOR_ITER, &&TARGET_INSTRUMENTED_CALL, &&TARGET_INSTRUMENTED_CALL_KW, &&TARGET_INSTRUMENTED_CALL_FUNCTION_EX, @@ -352,6 +352,7 @@ Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FORMAT_SIMPLE(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FORMAT_WITH_SPEC(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER_GEN(TAIL_CALL_PARAMS); +Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER_INDEX(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER_LIST(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER_RANGE(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_FOR_ITER_TUPLE(TAIL_CALL_PARAMS); @@ -359,6 +360,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_INDEX(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); @@ -589,6 +593,7 @@ static py_tail_call_funcptr INSTRUCTION_TABLE[256] = { [FORMAT_WITH_SPEC] = _TAIL_CALL_FORMAT_WITH_SPEC, [FOR_ITER] = _TAIL_CALL_FOR_ITER, [FOR_ITER_GEN] = _TAIL_CALL_FOR_ITER_GEN, + [FOR_ITER_INDEX] = _TAIL_CALL_FOR_ITER_INDEX, [FOR_ITER_LIST] = _TAIL_CALL_FOR_ITER_LIST, [FOR_ITER_RANGE] = _TAIL_CALL_FOR_ITER_RANGE, [FOR_ITER_TUPLE] = _TAIL_CALL_FOR_ITER_TUPLE, @@ -596,6 +601,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_INDEX] = _TAIL_CALL_GET_ITER_INDEX, + [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,10 +744,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, [216] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Python/optimizer.c b/Python/optimizer.c index dde3dd8ebe745a..134c2d946fd1af 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -431,6 +431,7 @@ _PyUOp_Replacements[MAX_UOP_ID + 1] = { [_ITER_JUMP_LIST] = _GUARD_NOT_EXHAUSTED_LIST, [_ITER_JUMP_TUPLE] = _GUARD_NOT_EXHAUSTED_TUPLE, [_FOR_ITER] = _FOR_ITER_TIER_TWO, + [_FOR_ITER_INDEX] = _FOR_ITER_INDEX_TIER_TWO, [_ITER_NEXT_LIST] = _ITER_NEXT_LIST_TIER_TWO, }; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index adab110c5ced66..19befddddb742c 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_INDEX: { + 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); @@ -1608,6 +1638,21 @@ /* _FOR_ITER is not a viable micro-op for tier 2 */ + case _ITER_CHECK_INDEX: { + break; + } + + /* _FOR_ITER_INDEX is not a viable micro-op for tier 2 */ + + case _FOR_ITER_INDEX_TIER_TWO: { + JitOptSymbol *next; + next = sym_new_not_null(ctx); + stack_pointer[0] = next; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + case _FOR_ITER_TIER_TWO: { JitOptSymbol *next; next = sym_new_not_null(ctx); @@ -1617,7 +1662,7 @@ break; } - /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 */ + /* _MONITOR_FOR_ITER is not a viable micro-op for tier 2 */ case _ITER_CHECK_LIST: { break; diff --git a/Python/specialize.c b/Python/specialize.c index 92f79d39d55208..40924823724f3b 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_iterindex != NULL) { + specialize(instr, GET_ITER_INDEX); + return; + } + if (tp->tp_iter == PyObject_SelfIter) { + specialize(instr, GET_ITER_SELF); + 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 fca9b29f9ebc2e..93ff312ce3aa22 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_IsValid", "PyStackRef_Wrap", "PyStackRef_Unwrap", + "_PyRange_IsSimpleCompact", + "_PyRange_GetStopIfCompact", + "PyStackRef_BoxInt", + "PyStackRef_TYPE", + "PyStackRef_TaggedIntLessThan", )