From d2f1d917e8b3d2dd8f35495c7632a32688883332 Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Thu, 19 Dec 2024 16:59:51 +0000 Subject: [PATCH] GH-122548: Implement branch taken and not taken events for sys.monitoring (GH-122564) --- Doc/c-api/monitoring.rst | 12 +- Doc/library/sys.monitoring.rst | 29 +- Doc/whatsnew/3.13.rst | 2 +- Doc/whatsnew/3.14.rst | 14 + Include/cpython/code.h | 6 +- Include/cpython/monitoring.h | 43 +- Include/internal/pycore_code.h | 2 + Include/internal/pycore_magic_number.h | 3 +- Include/internal/pycore_opcode_metadata.h | 25 +- Include/internal/pycore_opcode_utils.h | 6 + Include/internal/pycore_uop_ids.h | 1 + Include/opcode_ids.h | 198 ++++----- Lib/_opcode_metadata.py | 198 ++++----- Lib/test/test_compiler_codegen.py | 2 + Lib/test/test_dis.py | 391 +++++++++--------- Lib/test/test_monitoring.py | 67 ++- ...-12-13-14-21-04.gh-issue-122548.hq3Vud.rst | 4 + Modules/_testcapi/monitoring.c | 25 +- Objects/codeobject.c | 7 + Programs/test_frozenmain.h | 66 +-- Python/bytecodes.c | 60 ++- Python/codegen.c | 9 +- Python/executor_cases.c.h | 2 + Python/flowgraph.c | 6 + Python/generated_cases.c.h | 74 ++-- Python/instrumentation.c | 321 +++++++++++--- Python/opcode_targets.h | 4 +- Python/optimizer_cases.c.h | 2 + Tools/c-analyzer/cpython/globals-to-fix.tsv | 2 + 29 files changed, 998 insertions(+), 583 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-12-13-14-21-04.gh-issue-122548.hq3Vud.rst diff --git a/Doc/c-api/monitoring.rst b/Doc/c-api/monitoring.rst index 51d866cfd47469..bda6cd271197d0 100644 --- a/Doc/c-api/monitoring.rst +++ b/Doc/c-api/monitoring.rst @@ -75,9 +75,14 @@ See :mod:`sys.monitoring` for descriptions of the events. Fire a ``JUMP`` event. -.. c:function:: int PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) +.. c:function:: int PyMonitoring_FireBranchLeftEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) - Fire a ``BRANCH`` event. + Fire a ``BRANCH_LEFT`` event. + + +.. c:function:: int PyMonitoring_FireBranchRightEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) + + Fire a ``BRANCH_RIGHT`` event. .. c:function:: int PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval) @@ -168,7 +173,8 @@ would typically correspond to a python function. ================================================== ===================================== Macro Event ================================================== ===================================== - .. c:macro:: PY_MONITORING_EVENT_BRANCH :monitoring-event:`BRANCH` + .. c:macro:: PY_MONITORING_EVENT_BRANCH_LEFT :monitoring-event:`BRANCH_LEFT` + .. c:macro:: PY_MONITORING_EVENT_BRANCH_RIGHT :monitoring-event:`BRANCH_RIGHT` .. c:macro:: PY_MONITORING_EVENT_CALL :monitoring-event:`CALL` .. c:macro:: PY_MONITORING_EVENT_C_RAISE :monitoring-event:`C_RAISE` .. c:macro:: PY_MONITORING_EVENT_C_RETURN :monitoring-event:`C_RETURN` diff --git a/Doc/library/sys.monitoring.rst b/Doc/library/sys.monitoring.rst index f7140af2494898..cfdcdf2e2df476 100644 --- a/Doc/library/sys.monitoring.rst +++ b/Doc/library/sys.monitoring.rst @@ -79,9 +79,17 @@ Events The following events are supported: -.. monitoring-event:: BRANCH +.. monitoring-event:: BRANCH_LEFT - A conditional branch is taken (or not). + A conditional branch goes left. + + It is up to the tool to determine how to present "left" and "right" branches. + There is no guarantee which branch is "left" and which is "right", except + that it will be consistent for the duration of the program. + +.. monitoring-event:: BRANCH_RIGHT + + A conditional branch goes right. .. monitoring-event:: CALL @@ -180,9 +188,20 @@ The local events are: * :monitoring-event:`LINE` * :monitoring-event:`INSTRUCTION` * :monitoring-event:`JUMP` -* :monitoring-event:`BRANCH` +* :monitoring-event:`BRANCH_LEFT` +* :monitoring-event:`BRANCH_RIGHT` * :monitoring-event:`STOP_ITERATION` +Deprecated event +'''''''''''''''' + +* ``BRANCH`` + +The ``BRANCH`` event is deprecated in 3.14. +Using :monitoring-event:`BRANCH_LEFT` and :monitoring-event:`BRANCH_RIGHT` +events will give much better performance as they can be disabled +independently. + Ancillary events '''''''''''''''' @@ -357,13 +376,11 @@ Different events will provide the callback function with different arguments, as func(code: CodeType, line_number: int) -> DISABLE | Any -* :monitoring-event:`BRANCH` and :monitoring-event:`JUMP`:: +* :monitoring-event:`BRANCH_LEFT`, :monitoring-event:`BRANCH_RIGHT` and :monitoring-event:`JUMP`:: func(code: CodeType, instruction_offset: int, destination_offset: int) -> DISABLE | Any Note that the *destination_offset* is where the code will next execute. - For an untaken branch this will be the offset of the instruction following - the branch. * :monitoring-event:`INSTRUCTION`:: diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 9f6d98b9950d19..45cc1b5bad9b18 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1971,7 +1971,7 @@ New Features * :c:func:`PyMonitoring_FireCallEvent` * :c:func:`PyMonitoring_FireLineEvent` * :c:func:`PyMonitoring_FireJumpEvent` - * :c:func:`PyMonitoring_FireBranchEvent` + * ``PyMonitoring_FireBranchEvent`` * :c:func:`PyMonitoring_FireCReturnEvent` * :c:func:`PyMonitoring_FirePyThrowEvent` * :c:func:`PyMonitoring_FireRaiseEvent` diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 2e43dce5e061b4..97a37a82f76b9b 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -603,6 +603,11 @@ sys which only exists in specialized builds of Python, may now return objects from other interpreters than the one it's called in. +sys.monitoring +-------------- + +Two new events are added: :monitoring-event:`BRANCH_LEFT` and +:monitoring-event:`BRANCH_RIGHT`. The ``BRANCH`` event is deprecated. tkinter ------- @@ -1144,6 +1149,11 @@ New features a :exc:`UnicodeError` object. (Contributed by Bénédikt Tran in :gh:`127691`.) +* Add :c:func:`PyMonitoring_FireBranchLeftEvent` and + :c:func:`PyMonitoring_FireBranchRightEvent` for generating + :monitoring-event:`BRANCH_LEFT` and :monitoring-event:`BRANCH_RIGHT` + events, respectively. + Porting to Python 3.14 ---------------------- @@ -1177,6 +1187,10 @@ Deprecated .. include:: ../deprecations/c-api-pending-removal-in-future.rst +* The ``PyMonitoring_FireBranchEvent`` function is deprecated and should + be replaced with calls to :c:func:`PyMonitoring_FireBranchLeftEvent` + and :c:func:`PyMonitoring_FireBranchRightEvent`. + Removed ------- diff --git a/Include/cpython/code.h b/Include/cpython/code.h index 3899d4269233a1..c3c0165d556ead 100644 --- a/Include/cpython/code.h +++ b/Include/cpython/code.h @@ -11,11 +11,11 @@ extern "C" { /* Total tool ids available */ #define _PY_MONITORING_TOOL_IDS 8 /* Count of all local monitoring events */ -#define _PY_MONITORING_LOCAL_EVENTS 10 +#define _PY_MONITORING_LOCAL_EVENTS 11 /* Count of all "real" monitoring events (not derived from other events) */ -#define _PY_MONITORING_UNGROUPED_EVENTS 15 +#define _PY_MONITORING_UNGROUPED_EVENTS 16 /* Count of all monitoring events */ -#define _PY_MONITORING_EVENTS 17 +#define _PY_MONITORING_EVENTS 19 /* Tables of which tools are active for each monitored event. */ typedef struct _Py_LocalMonitors { diff --git a/Include/cpython/monitoring.h b/Include/cpython/monitoring.h index 797ba51246b1c6..ce92942404c9f7 100644 --- a/Include/cpython/monitoring.h +++ b/Include/cpython/monitoring.h @@ -13,25 +13,27 @@ #define PY_MONITORING_EVENT_LINE 5 #define PY_MONITORING_EVENT_INSTRUCTION 6 #define PY_MONITORING_EVENT_JUMP 7 -#define PY_MONITORING_EVENT_BRANCH 8 -#define PY_MONITORING_EVENT_STOP_ITERATION 9 +#define PY_MONITORING_EVENT_BRANCH_LEFT 8 +#define PY_MONITORING_EVENT_BRANCH_RIGHT 9 +#define PY_MONITORING_EVENT_STOP_ITERATION 10 #define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) \ ((ev) < _PY_MONITORING_LOCAL_EVENTS) /* Other events, mainly exceptions */ -#define PY_MONITORING_EVENT_RAISE 10 -#define PY_MONITORING_EVENT_EXCEPTION_HANDLED 11 -#define PY_MONITORING_EVENT_PY_UNWIND 12 -#define PY_MONITORING_EVENT_PY_THROW 13 -#define PY_MONITORING_EVENT_RERAISE 14 +#define PY_MONITORING_EVENT_RAISE 11 +#define PY_MONITORING_EVENT_EXCEPTION_HANDLED 12 +#define PY_MONITORING_EVENT_PY_UNWIND 13 +#define PY_MONITORING_EVENT_PY_THROW 14 +#define PY_MONITORING_EVENT_RERAISE 15 /* Ancillary events */ -#define PY_MONITORING_EVENT_C_RETURN 15 -#define PY_MONITORING_EVENT_C_RAISE 16 +#define PY_MONITORING_EVENT_C_RETURN 16 +#define PY_MONITORING_EVENT_C_RAISE 17 +#define PY_MONITORING_EVENT_BRANCH 18 typedef struct _PyMonitoringState { @@ -74,10 +76,18 @@ PyAPI_FUNC(int) _PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset); -PyAPI_FUNC(int) +Py_DEPRECATED(3.14) PyAPI_FUNC(int) _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset); +PyAPI_FUNC(int) +_PyMonitoring_FireBranchRightEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, + PyObject *target_offset); + +PyAPI_FUNC(int) +_PyMonitoring_FireBranchLeftEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, + PyObject *target_offset); + PyAPI_FUNC(int) _PyMonitoring_FireCReturnEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *retval); @@ -174,12 +184,21 @@ PyMonitoring_FireJumpEvent(PyMonitoringState *state, PyObject *codelike, int32_t } static inline int -PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, +PyMonitoring_FireBranchRightEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, + PyObject *target_offset) +{ + _PYMONITORING_IF_ACTIVE( + state, + _PyMonitoring_FireBranchRightEvent(state, codelike, offset, target_offset)); +} + +static inline int +PyMonitoring_FireBranchLeftEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, PyObject *target_offset) { _PYMONITORING_IF_ACTIVE( state, - _PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset)); + _PyMonitoring_FireBranchLeftEvent(state, codelike, offset, target_offset)); } static inline int diff --git a/Include/internal/pycore_code.h b/Include/internal/pycore_code.h index d607a54aa4a2f5..d97fe81a2fc54a 100644 --- a/Include/internal/pycore_code.h +++ b/Include/internal/pycore_code.h @@ -603,6 +603,8 @@ extern _Py_CODEUNIT _Py_GetBaseCodeUnit(PyCodeObject *code, int offset); extern int _PyInstruction_GetLength(PyCodeObject *code, int offset); +extern PyObject *_PyInstrumentation_BranchesIterator(PyCodeObject *code); + struct _PyCode8 _PyCode_DEF(8); PyAPI_DATA(const struct _PyCode8) _Py_InitCleanup; diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index 14e29576875c6e..079a9befcd4c5e 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -262,6 +262,7 @@ Known values: Python 3.14a1 3607 (Add pseudo instructions JUMP_IF_TRUE/FALSE) Python 3.14a1 3608 (Add support for slices) Python 3.14a2 3609 (Add LOAD_SMALL_INT and LOAD_CONST_IMMORTAL instructions, remove RETURN_CONST) + Python 3.14a3 3610 (Add NOT_TAKEN instruction) Python 3.15 will start with 3650 @@ -274,7 +275,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3609 +#define PYC_MAGIC_NUMBER 3611 /* 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 d2ae8928a8fe8f..e09fff062b5202 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -243,6 +243,8 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 0; case INSTRUMENTED_LOAD_SUPER_ATTR: return 0; + case INSTRUMENTED_NOT_TAKEN: + return 0; case INSTRUMENTED_POP_JUMP_IF_FALSE: return 0; case INSTRUMENTED_POP_JUMP_IF_NONE: @@ -367,6 +369,8 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 1; case NOP: return 0; + case NOT_TAKEN: + return 0; case POP_BLOCK: return 0; case POP_EXCEPT: @@ -702,6 +706,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 0; case INSTRUMENTED_LOAD_SUPER_ATTR: return 0; + case INSTRUMENTED_NOT_TAKEN: + return 0; case INSTRUMENTED_POP_JUMP_IF_FALSE: return 0; case INSTRUMENTED_POP_JUMP_IF_NONE: @@ -826,6 +832,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 2; case NOP: return 0; + case NOT_TAKEN: + return 0; case POP_BLOCK: return 0; case POP_EXCEPT: @@ -1387,6 +1395,10 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) { *effect = 0; return 0; } + case INSTRUMENTED_NOT_TAKEN: { + *effect = 0; + return 0; + } case INSTRUMENTED_POP_JUMP_IF_FALSE: { *effect = 0; return 0; @@ -1635,6 +1647,10 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) { *effect = 0; return 0; } + case NOT_TAKEN: { + *effect = 0; + return 0; + } case POP_BLOCK: { *effect = 0; return 0; @@ -2043,6 +2059,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [INSTRUMENTED_LINE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, [INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IXC, 0 }, + [INSTRUMENTED_NOT_TAKEN] = { true, INSTR_FMT_IX, 0 }, [INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, [INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, @@ -2100,6 +2117,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = { [MATCH_MAPPING] = { true, INSTR_FMT_IX, 0 }, [MATCH_SEQUENCE] = { true, INSTR_FMT_IX, 0 }, [NOP] = { true, INSTR_FMT_IX, HAS_PURE_FLAG }, + [NOT_TAKEN] = { true, INSTR_FMT_IX, HAS_PURE_FLAG }, [POP_EXCEPT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, [POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, [POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG }, @@ -2304,6 +2322,7 @@ _PyOpcode_macro_expansion[256] = { [MATCH_MAPPING] = { .nuops = 1, .uops = { { _MATCH_MAPPING, 0, 0 } } }, [MATCH_SEQUENCE] = { .nuops = 1, .uops = { { _MATCH_SEQUENCE, 0, 0 } } }, [NOP] = { .nuops = 1, .uops = { { _NOP, 0, 0 } } }, + [NOT_TAKEN] = { .nuops = 1, .uops = { { _NOP, 0, 0 } } }, [POP_EXCEPT] = { .nuops = 1, .uops = { { _POP_EXCEPT, 0, 0 } } }, [POP_JUMP_IF_FALSE] = { .nuops = 1, .uops = { { _POP_JUMP_IF_FALSE, 9, 1 } } }, [POP_JUMP_IF_NONE] = { .nuops = 2, .uops = { { _IS_NONE, 0, 0 }, { _POP_JUMP_IF_TRUE, 9, 1 } } }, @@ -2462,6 +2481,7 @@ const char *_PyOpcode_OpName[266] = { [INSTRUMENTED_JUMP_FORWARD] = "INSTRUMENTED_JUMP_FORWARD", [INSTRUMENTED_LINE] = "INSTRUMENTED_LINE", [INSTRUMENTED_LOAD_SUPER_ATTR] = "INSTRUMENTED_LOAD_SUPER_ATTR", + [INSTRUMENTED_NOT_TAKEN] = "INSTRUMENTED_NOT_TAKEN", [INSTRUMENTED_POP_JUMP_IF_FALSE] = "INSTRUMENTED_POP_JUMP_IF_FALSE", [INSTRUMENTED_POP_JUMP_IF_NONE] = "INSTRUMENTED_POP_JUMP_IF_NONE", [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = "INSTRUMENTED_POP_JUMP_IF_NOT_NONE", @@ -2524,6 +2544,7 @@ const char *_PyOpcode_OpName[266] = { [MATCH_MAPPING] = "MATCH_MAPPING", [MATCH_SEQUENCE] = "MATCH_SEQUENCE", [NOP] = "NOP", + [NOT_TAKEN] = "NOT_TAKEN", [POP_BLOCK] = "POP_BLOCK", [POP_EXCEPT] = "POP_EXCEPT", [POP_JUMP_IF_FALSE] = "POP_JUMP_IF_FALSE", @@ -2718,6 +2739,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [INSTRUMENTED_JUMP_FORWARD] = INSTRUMENTED_JUMP_FORWARD, [INSTRUMENTED_LINE] = INSTRUMENTED_LINE, [INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR, + [INSTRUMENTED_NOT_TAKEN] = INSTRUMENTED_NOT_TAKEN, [INSTRUMENTED_POP_JUMP_IF_FALSE] = INSTRUMENTED_POP_JUMP_IF_FALSE, [INSTRUMENTED_POP_JUMP_IF_NONE] = INSTRUMENTED_POP_JUMP_IF_NONE, [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = INSTRUMENTED_POP_JUMP_IF_NOT_NONE, @@ -2775,6 +2797,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [MATCH_MAPPING] = MATCH_MAPPING, [MATCH_SEQUENCE] = MATCH_SEQUENCE, [NOP] = NOP, + [NOT_TAKEN] = NOT_TAKEN, [POP_EXCEPT] = POP_EXCEPT, [POP_JUMP_IF_FALSE] = POP_JUMP_IF_FALSE, [POP_JUMP_IF_NONE] = POP_JUMP_IF_NONE, @@ -2833,7 +2856,6 @@ const uint8_t _PyOpcode_Deopt[256] = { #endif // NEED_OPCODE_METADATA #define EXTRA_CASES \ - case 116: \ case 117: \ case 118: \ case 119: \ @@ -2874,7 +2896,6 @@ const uint8_t _PyOpcode_Deopt[256] = { case 233: \ case 234: \ case 235: \ - case 236: \ ; struct pseudo_targets { uint8_t as_sequence; diff --git a/Include/internal/pycore_opcode_utils.h b/Include/internal/pycore_opcode_utils.h index c6ce7e65a65d4b..0872231d1f2d11 100644 --- a/Include/internal/pycore_opcode_utils.h +++ b/Include/internal/pycore_opcode_utils.h @@ -45,6 +45,12 @@ extern "C" { (opcode) == JUMP_BACKWARD || \ (opcode) == JUMP_BACKWARD_NO_INTERRUPT) +#define IS_CONDITIONAL_JUMP_OPCODE(opcode) \ + ((opcode) == POP_JUMP_IF_FALSE || \ + (opcode) == POP_JUMP_IF_TRUE || \ + (opcode) == POP_JUMP_IF_NONE || \ + (opcode) == POP_JUMP_IF_NOT_NONE) + #define IS_SCOPE_EXIT_OPCODE(opcode) \ ((opcode) == RETURN_VALUE || \ (opcode) == RAISE_VARARGS || \ diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 45563585dd5681..5fc57e48f500d0 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -155,6 +155,7 @@ extern "C" { #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD #define _INSTRUMENTED_LINE INSTRUMENTED_LINE #define _INSTRUMENTED_LOAD_SUPER_ATTR INSTRUMENTED_LOAD_SUPER_ATTR +#define _INSTRUMENTED_NOT_TAKEN INSTRUMENTED_NOT_TAKEN #define _INSTRUMENTED_POP_JUMP_IF_FALSE INSTRUMENTED_POP_JUMP_IF_FALSE #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index ce3d23eaa6d56d..3cd189b93dd9d6 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -38,94 +38,95 @@ extern "C" { #define MATCH_MAPPING 25 #define MATCH_SEQUENCE 26 #define NOP 27 -#define POP_EXCEPT 28 -#define POP_TOP 29 -#define PUSH_EXC_INFO 30 -#define PUSH_NULL 31 -#define RETURN_GENERATOR 32 -#define RETURN_VALUE 33 -#define SETUP_ANNOTATIONS 34 -#define STORE_SLICE 35 -#define STORE_SUBSCR 36 -#define TO_BOOL 37 -#define UNARY_INVERT 38 -#define UNARY_NEGATIVE 39 -#define UNARY_NOT 40 -#define WITH_EXCEPT_START 41 -#define BINARY_OP 42 -#define BUILD_LIST 43 -#define BUILD_MAP 44 -#define BUILD_SET 45 -#define BUILD_SLICE 46 -#define BUILD_STRING 47 -#define BUILD_TUPLE 48 -#define CALL 49 -#define CALL_FUNCTION_EX 50 -#define CALL_INTRINSIC_1 51 -#define CALL_INTRINSIC_2 52 -#define CALL_KW 53 -#define COMPARE_OP 54 -#define CONTAINS_OP 55 -#define CONVERT_VALUE 56 -#define COPY 57 -#define COPY_FREE_VARS 58 -#define DELETE_ATTR 59 -#define DELETE_DEREF 60 -#define DELETE_FAST 61 -#define DELETE_GLOBAL 62 -#define DELETE_NAME 63 -#define DICT_MERGE 64 -#define DICT_UPDATE 65 -#define EXTENDED_ARG 66 -#define FOR_ITER 67 -#define GET_AWAITABLE 68 -#define IMPORT_FROM 69 -#define IMPORT_NAME 70 -#define IS_OP 71 -#define JUMP_BACKWARD 72 -#define JUMP_BACKWARD_NO_INTERRUPT 73 -#define JUMP_FORWARD 74 -#define LIST_APPEND 75 -#define LIST_EXTEND 76 -#define LOAD_ATTR 77 -#define LOAD_COMMON_CONSTANT 78 -#define LOAD_CONST 79 -#define LOAD_DEREF 80 -#define LOAD_FAST 81 -#define LOAD_FAST_AND_CLEAR 82 -#define LOAD_FAST_CHECK 83 -#define LOAD_FAST_LOAD_FAST 84 -#define LOAD_FROM_DICT_OR_DEREF 85 -#define LOAD_FROM_DICT_OR_GLOBALS 86 -#define LOAD_GLOBAL 87 -#define LOAD_NAME 88 -#define LOAD_SMALL_INT 89 -#define LOAD_SPECIAL 90 -#define LOAD_SUPER_ATTR 91 -#define MAKE_CELL 92 -#define MAP_ADD 93 -#define MATCH_CLASS 94 -#define POP_JUMP_IF_FALSE 95 -#define POP_JUMP_IF_NONE 96 -#define POP_JUMP_IF_NOT_NONE 97 -#define POP_JUMP_IF_TRUE 98 -#define RAISE_VARARGS 99 -#define RERAISE 100 -#define SEND 101 -#define SET_ADD 102 -#define SET_FUNCTION_ATTRIBUTE 103 -#define SET_UPDATE 104 -#define STORE_ATTR 105 -#define STORE_DEREF 106 -#define STORE_FAST 107 -#define STORE_FAST_LOAD_FAST 108 -#define STORE_FAST_STORE_FAST 109 -#define STORE_GLOBAL 110 -#define STORE_NAME 111 -#define SWAP 112 -#define UNPACK_EX 113 -#define UNPACK_SEQUENCE 114 -#define YIELD_VALUE 115 +#define NOT_TAKEN 28 +#define POP_EXCEPT 29 +#define POP_TOP 30 +#define PUSH_EXC_INFO 31 +#define PUSH_NULL 32 +#define RETURN_GENERATOR 33 +#define RETURN_VALUE 34 +#define SETUP_ANNOTATIONS 35 +#define STORE_SLICE 36 +#define STORE_SUBSCR 37 +#define TO_BOOL 38 +#define UNARY_INVERT 39 +#define UNARY_NEGATIVE 40 +#define UNARY_NOT 41 +#define WITH_EXCEPT_START 42 +#define BINARY_OP 43 +#define BUILD_LIST 44 +#define BUILD_MAP 45 +#define BUILD_SET 46 +#define BUILD_SLICE 47 +#define BUILD_STRING 48 +#define BUILD_TUPLE 49 +#define CALL 50 +#define CALL_FUNCTION_EX 51 +#define CALL_INTRINSIC_1 52 +#define CALL_INTRINSIC_2 53 +#define CALL_KW 54 +#define COMPARE_OP 55 +#define CONTAINS_OP 56 +#define CONVERT_VALUE 57 +#define COPY 58 +#define COPY_FREE_VARS 59 +#define DELETE_ATTR 60 +#define DELETE_DEREF 61 +#define DELETE_FAST 62 +#define DELETE_GLOBAL 63 +#define DELETE_NAME 64 +#define DICT_MERGE 65 +#define DICT_UPDATE 66 +#define EXTENDED_ARG 67 +#define FOR_ITER 68 +#define GET_AWAITABLE 69 +#define IMPORT_FROM 70 +#define IMPORT_NAME 71 +#define IS_OP 72 +#define JUMP_BACKWARD 73 +#define JUMP_BACKWARD_NO_INTERRUPT 74 +#define JUMP_FORWARD 75 +#define LIST_APPEND 76 +#define LIST_EXTEND 77 +#define LOAD_ATTR 78 +#define LOAD_COMMON_CONSTANT 79 +#define LOAD_CONST 80 +#define LOAD_DEREF 81 +#define LOAD_FAST 82 +#define LOAD_FAST_AND_CLEAR 83 +#define LOAD_FAST_CHECK 84 +#define LOAD_FAST_LOAD_FAST 85 +#define LOAD_FROM_DICT_OR_DEREF 86 +#define LOAD_FROM_DICT_OR_GLOBALS 87 +#define LOAD_GLOBAL 88 +#define LOAD_NAME 89 +#define LOAD_SMALL_INT 90 +#define LOAD_SPECIAL 91 +#define LOAD_SUPER_ATTR 92 +#define MAKE_CELL 93 +#define MAP_ADD 94 +#define MATCH_CLASS 95 +#define POP_JUMP_IF_FALSE 96 +#define POP_JUMP_IF_NONE 97 +#define POP_JUMP_IF_NOT_NONE 98 +#define POP_JUMP_IF_TRUE 99 +#define RAISE_VARARGS 100 +#define RERAISE 101 +#define SEND 102 +#define SET_ADD 103 +#define SET_FUNCTION_ATTRIBUTE 104 +#define SET_UPDATE 105 +#define STORE_ATTR 106 +#define STORE_DEREF 107 +#define STORE_FAST 108 +#define STORE_FAST_LOAD_FAST 109 +#define STORE_FAST_STORE_FAST 110 +#define STORE_GLOBAL 111 +#define STORE_NAME 112 +#define SWAP 113 +#define UNPACK_EX 114 +#define UNPACK_SEQUENCE 115 +#define YIELD_VALUE 116 #define RESUME 149 #define BINARY_OP_ADD_FLOAT 150 #define BINARY_OP_ADD_INT 151 @@ -205,14 +206,15 @@ extern "C" { #define UNPACK_SEQUENCE_LIST 225 #define UNPACK_SEQUENCE_TUPLE 226 #define UNPACK_SEQUENCE_TWO_TUPLE 227 -#define INSTRUMENTED_END_FOR 237 -#define INSTRUMENTED_END_SEND 238 -#define INSTRUMENTED_LOAD_SUPER_ATTR 239 -#define INSTRUMENTED_FOR_ITER 240 -#define INSTRUMENTED_CALL_KW 241 -#define INSTRUMENTED_CALL_FUNCTION_EX 242 -#define INSTRUMENTED_INSTRUCTION 243 -#define INSTRUMENTED_JUMP_FORWARD 244 +#define INSTRUMENTED_END_FOR 236 +#define INSTRUMENTED_END_SEND 237 +#define INSTRUMENTED_LOAD_SUPER_ATTR 238 +#define INSTRUMENTED_FOR_ITER 239 +#define INSTRUMENTED_CALL_KW 240 +#define INSTRUMENTED_CALL_FUNCTION_EX 241 +#define INSTRUMENTED_INSTRUCTION 242 +#define INSTRUMENTED_JUMP_FORWARD 243 +#define INSTRUMENTED_NOT_TAKEN 244 #define INSTRUMENTED_POP_JUMP_IF_TRUE 245 #define INSTRUMENTED_POP_JUMP_IF_FALSE 246 #define INSTRUMENTED_POP_JUMP_IF_NONE 247 @@ -235,9 +237,9 @@ extern "C" { #define SETUP_WITH 264 #define STORE_FAST_MAYBE_NULL 265 -#define HAVE_ARGUMENT 41 +#define HAVE_ARGUMENT 42 #define MIN_SPECIALIZED_OPCODE 150 -#define MIN_INSTRUMENTED_OPCODE 237 +#define MIN_INSTRUMENTED_OPCODE 236 #ifdef __cplusplus } diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index cda3c340c322f3..dada2cb5fa033f 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -231,102 +231,104 @@ 'MATCH_MAPPING': 25, 'MATCH_SEQUENCE': 26, 'NOP': 27, - 'POP_EXCEPT': 28, - 'POP_TOP': 29, - 'PUSH_EXC_INFO': 30, - 'PUSH_NULL': 31, - 'RETURN_GENERATOR': 32, - 'RETURN_VALUE': 33, - 'SETUP_ANNOTATIONS': 34, - 'STORE_SLICE': 35, - 'STORE_SUBSCR': 36, - 'TO_BOOL': 37, - 'UNARY_INVERT': 38, - 'UNARY_NEGATIVE': 39, - 'UNARY_NOT': 40, - 'WITH_EXCEPT_START': 41, - 'BINARY_OP': 42, - 'BUILD_LIST': 43, - 'BUILD_MAP': 44, - 'BUILD_SET': 45, - 'BUILD_SLICE': 46, - 'BUILD_STRING': 47, - 'BUILD_TUPLE': 48, - 'CALL': 49, - 'CALL_FUNCTION_EX': 50, - 'CALL_INTRINSIC_1': 51, - 'CALL_INTRINSIC_2': 52, - 'CALL_KW': 53, - 'COMPARE_OP': 54, - 'CONTAINS_OP': 55, - 'CONVERT_VALUE': 56, - 'COPY': 57, - 'COPY_FREE_VARS': 58, - 'DELETE_ATTR': 59, - 'DELETE_DEREF': 60, - 'DELETE_FAST': 61, - 'DELETE_GLOBAL': 62, - 'DELETE_NAME': 63, - 'DICT_MERGE': 64, - 'DICT_UPDATE': 65, - 'EXTENDED_ARG': 66, - 'FOR_ITER': 67, - 'GET_AWAITABLE': 68, - 'IMPORT_FROM': 69, - 'IMPORT_NAME': 70, - 'IS_OP': 71, - 'JUMP_BACKWARD': 72, - 'JUMP_BACKWARD_NO_INTERRUPT': 73, - 'JUMP_FORWARD': 74, - 'LIST_APPEND': 75, - 'LIST_EXTEND': 76, - 'LOAD_ATTR': 77, - 'LOAD_COMMON_CONSTANT': 78, - 'LOAD_CONST': 79, - 'LOAD_DEREF': 80, - 'LOAD_FAST': 81, - 'LOAD_FAST_AND_CLEAR': 82, - 'LOAD_FAST_CHECK': 83, - 'LOAD_FAST_LOAD_FAST': 84, - 'LOAD_FROM_DICT_OR_DEREF': 85, - 'LOAD_FROM_DICT_OR_GLOBALS': 86, - 'LOAD_GLOBAL': 87, - 'LOAD_NAME': 88, - 'LOAD_SMALL_INT': 89, - 'LOAD_SPECIAL': 90, - 'LOAD_SUPER_ATTR': 91, - 'MAKE_CELL': 92, - 'MAP_ADD': 93, - 'MATCH_CLASS': 94, - 'POP_JUMP_IF_FALSE': 95, - 'POP_JUMP_IF_NONE': 96, - 'POP_JUMP_IF_NOT_NONE': 97, - 'POP_JUMP_IF_TRUE': 98, - 'RAISE_VARARGS': 99, - 'RERAISE': 100, - 'SEND': 101, - 'SET_ADD': 102, - 'SET_FUNCTION_ATTRIBUTE': 103, - 'SET_UPDATE': 104, - 'STORE_ATTR': 105, - 'STORE_DEREF': 106, - 'STORE_FAST': 107, - 'STORE_FAST_LOAD_FAST': 108, - 'STORE_FAST_STORE_FAST': 109, - 'STORE_GLOBAL': 110, - 'STORE_NAME': 111, - 'SWAP': 112, - 'UNPACK_EX': 113, - 'UNPACK_SEQUENCE': 114, - 'YIELD_VALUE': 115, - 'INSTRUMENTED_END_FOR': 237, - 'INSTRUMENTED_END_SEND': 238, - 'INSTRUMENTED_LOAD_SUPER_ATTR': 239, - 'INSTRUMENTED_FOR_ITER': 240, - 'INSTRUMENTED_CALL_KW': 241, - 'INSTRUMENTED_CALL_FUNCTION_EX': 242, - 'INSTRUMENTED_INSTRUCTION': 243, - 'INSTRUMENTED_JUMP_FORWARD': 244, + 'NOT_TAKEN': 28, + 'POP_EXCEPT': 29, + 'POP_TOP': 30, + 'PUSH_EXC_INFO': 31, + 'PUSH_NULL': 32, + 'RETURN_GENERATOR': 33, + 'RETURN_VALUE': 34, + 'SETUP_ANNOTATIONS': 35, + 'STORE_SLICE': 36, + 'STORE_SUBSCR': 37, + 'TO_BOOL': 38, + 'UNARY_INVERT': 39, + 'UNARY_NEGATIVE': 40, + 'UNARY_NOT': 41, + 'WITH_EXCEPT_START': 42, + 'BINARY_OP': 43, + 'BUILD_LIST': 44, + 'BUILD_MAP': 45, + 'BUILD_SET': 46, + 'BUILD_SLICE': 47, + 'BUILD_STRING': 48, + 'BUILD_TUPLE': 49, + 'CALL': 50, + 'CALL_FUNCTION_EX': 51, + 'CALL_INTRINSIC_1': 52, + 'CALL_INTRINSIC_2': 53, + 'CALL_KW': 54, + 'COMPARE_OP': 55, + 'CONTAINS_OP': 56, + 'CONVERT_VALUE': 57, + 'COPY': 58, + 'COPY_FREE_VARS': 59, + 'DELETE_ATTR': 60, + 'DELETE_DEREF': 61, + 'DELETE_FAST': 62, + 'DELETE_GLOBAL': 63, + 'DELETE_NAME': 64, + 'DICT_MERGE': 65, + 'DICT_UPDATE': 66, + 'EXTENDED_ARG': 67, + 'FOR_ITER': 68, + 'GET_AWAITABLE': 69, + 'IMPORT_FROM': 70, + 'IMPORT_NAME': 71, + 'IS_OP': 72, + 'JUMP_BACKWARD': 73, + 'JUMP_BACKWARD_NO_INTERRUPT': 74, + 'JUMP_FORWARD': 75, + 'LIST_APPEND': 76, + 'LIST_EXTEND': 77, + 'LOAD_ATTR': 78, + 'LOAD_COMMON_CONSTANT': 79, + 'LOAD_CONST': 80, + 'LOAD_DEREF': 81, + 'LOAD_FAST': 82, + 'LOAD_FAST_AND_CLEAR': 83, + 'LOAD_FAST_CHECK': 84, + 'LOAD_FAST_LOAD_FAST': 85, + 'LOAD_FROM_DICT_OR_DEREF': 86, + 'LOAD_FROM_DICT_OR_GLOBALS': 87, + 'LOAD_GLOBAL': 88, + 'LOAD_NAME': 89, + 'LOAD_SMALL_INT': 90, + 'LOAD_SPECIAL': 91, + 'LOAD_SUPER_ATTR': 92, + 'MAKE_CELL': 93, + 'MAP_ADD': 94, + 'MATCH_CLASS': 95, + 'POP_JUMP_IF_FALSE': 96, + 'POP_JUMP_IF_NONE': 97, + 'POP_JUMP_IF_NOT_NONE': 98, + 'POP_JUMP_IF_TRUE': 99, + 'RAISE_VARARGS': 100, + 'RERAISE': 101, + 'SEND': 102, + 'SET_ADD': 103, + 'SET_FUNCTION_ATTRIBUTE': 104, + 'SET_UPDATE': 105, + 'STORE_ATTR': 106, + 'STORE_DEREF': 107, + 'STORE_FAST': 108, + 'STORE_FAST_LOAD_FAST': 109, + 'STORE_FAST_STORE_FAST': 110, + 'STORE_GLOBAL': 111, + 'STORE_NAME': 112, + 'SWAP': 113, + 'UNPACK_EX': 114, + 'UNPACK_SEQUENCE': 115, + 'YIELD_VALUE': 116, + 'INSTRUMENTED_END_FOR': 236, + 'INSTRUMENTED_END_SEND': 237, + 'INSTRUMENTED_LOAD_SUPER_ATTR': 238, + 'INSTRUMENTED_FOR_ITER': 239, + 'INSTRUMENTED_CALL_KW': 240, + 'INSTRUMENTED_CALL_FUNCTION_EX': 241, + 'INSTRUMENTED_INSTRUCTION': 242, + 'INSTRUMENTED_JUMP_FORWARD': 243, + 'INSTRUMENTED_NOT_TAKEN': 244, 'INSTRUMENTED_POP_JUMP_IF_TRUE': 245, 'INSTRUMENTED_POP_JUMP_IF_FALSE': 246, 'INSTRUMENTED_POP_JUMP_IF_NONE': 247, @@ -348,5 +350,5 @@ 'STORE_FAST_MAYBE_NULL': 265, } -HAVE_ARGUMENT = 41 -MIN_INSTRUMENTED_OPCODE = 237 +HAVE_ARGUMENT = 42 +MIN_INSTRUMENTED_OPCODE = 236 diff --git a/Lib/test/test_compiler_codegen.py b/Lib/test/test_compiler_codegen.py index 2dd7cf65ee3c2a..f8c4fc14c91ebe 100644 --- a/Lib/test/test_compiler_codegen.py +++ b/Lib/test/test_compiler_codegen.py @@ -29,6 +29,7 @@ def test_if_expression(self): ('LOAD_CONST', 0, 1), ('TO_BOOL', 0, 1), ('POP_JUMP_IF_FALSE', false_lbl := self.Label(), 1), + ('NOT_TAKEN', None, 1), ('LOAD_SMALL_INT', 42, 1), ('JUMP_NO_INTERRUPT', exit_lbl := self.Label()), false_lbl, @@ -49,6 +50,7 @@ def test_for_loop(self): ('GET_ITER', None, 1), loop_lbl := self.Label(), ('FOR_ITER', exit_lbl := self.Label(), 1), + ('NOT_TAKEN', None, 1), ('NOP', None, 1, 1), ('STORE_NAME', 1, 1), ('LOAD_NAME', 2, 2), diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index c719f571152d61..955a3e4cb9e4f7 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -175,10 +175,11 @@ def bug708901(): %3d CALL 2 GET_ITER - L1: FOR_ITER 3 (to L2) + L1: FOR_ITER 4 (to L2) + NOT_TAKEN STORE_FAST 0 (res) -%3d JUMP_BACKWARD 5 (to L1) +%3d JUMP_BACKWARD 6 (to L1) %3d L2: END_FOR POP_TOP @@ -200,7 +201,8 @@ def bug1333982(x=[]): dis_bug1333982 = """\ %3d RESUME 0 -%3d LOAD_COMMON_CONSTANT 0 (AssertionError) +%3d NOT_TAKEN + LOAD_COMMON_CONSTANT 0 (AssertionError) LOAD_CONST 0 ( at 0x..., file "%s", line %d>) MAKE_FUNCTION LOAD_FAST 0 (x) @@ -432,7 +434,7 @@ def foo(a: int, b: str) -> str: 1 LOAD_SMALL_INT 0 STORE_NAME 0 (x) - 2 L1: NOP + 2 L1: NOT_TAKEN 3 LOAD_NAME 0 (x) LOAD_SMALL_INT 1 @@ -458,7 +460,8 @@ def foo(a: int, b: str) -> str: %4d LOAD_GLOBAL 0 (Exception) CHECK_EXC_MATCH - POP_JUMP_IF_FALSE 23 (to L7) + POP_JUMP_IF_FALSE 24 (to L7) + NOT_TAKEN STORE_FAST 0 (e) %4d L4: LOAD_FAST 0 (e) @@ -555,7 +558,8 @@ def _with(c): %4d L3: PUSH_EXC_INFO WITH_EXCEPT_START TO_BOOL - POP_JUMP_IF_TRUE 1 (to L4) + POP_JUMP_IF_TRUE 2 (to L4) + NOT_TAKEN RERAISE 2 L4: POP_TOP L5: POP_EXCEPT @@ -645,7 +649,8 @@ async def _asyncwith(c): L20: CLEANUP_THROW L21: END_SEND TO_BOOL - POP_JUMP_IF_TRUE 1 (to L22) + POP_JUMP_IF_TRUE 2 (to L22) + NOT_TAKEN RERAISE 2 L22: POP_TOP L23: POP_EXCEPT @@ -839,7 +844,8 @@ def foo(x): L1: RESUME 0 LOAD_FAST 0 (.0) GET_ITER - L2: FOR_ITER 10 (to L3) + L2: FOR_ITER 11 (to L3) + NOT_TAKEN STORE_FAST 1 (z) LOAD_DEREF 2 (x) LOAD_FAST 1 (z) @@ -847,7 +853,7 @@ def foo(x): YIELD_VALUE 0 RESUME 5 POP_TOP - JUMP_BACKWARD 12 (to L2) + JUMP_BACKWARD 13 (to L2) L3: END_FOR POP_TOP LOAD_CONST 0 (None) @@ -893,14 +899,15 @@ def loop_test(): LOAD_SMALL_INT 3 BINARY_OP 5 (*) GET_ITER - L1: FOR_ITER_LIST 14 (to L2) + L1: FOR_ITER_LIST 15 (to L2) + NOT_TAKEN STORE_FAST 0 (i) %3d LOAD_GLOBAL_MODULE 1 (load_test + NULL) LOAD_FAST 0 (i) CALL_PY_GENERAL 1 POP_TOP - JUMP_BACKWARD 16 (to L1) + JUMP_BACKWARD 17 (to L1) %3d L2: END_FOR POP_TOP @@ -1699,204 +1706,214 @@ def _prepare_test_cases(): Instruction = dis.Instruction expected_opinfo_outer = [ - Instruction(opname='MAKE_CELL', opcode=92, arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='MAKE_CELL', opcode=92, arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='MAKE_CELL', opcode=93, arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='MAKE_CELL', opcode=93, arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=True, line_number=1, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval=(3, 4), argrepr='(3, 4)', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='a', argrepr='a', offset=8, start_offset=8, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=1, argval='b', argrepr='b', offset=10, start_offset=10, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), - Instruction(opname='BUILD_TUPLE', opcode=48, arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval=code_object_f, argrepr=repr(code_object_f), offset=14, start_offset=14, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=3, argval=(3, 4), argrepr='(3, 4)', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=0, argval='a', argrepr='a', offset=8, start_offset=8, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=1, argval='b', argrepr='b', offset=10, start_offset=10, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), + Instruction(opname='BUILD_TUPLE', opcode=49, arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=0, argval=code_object_f, argrepr=repr(code_object_f), offset=14, start_offset=14, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), Instruction(opname='MAKE_FUNCTION', opcode=23, arg=None, argval=None, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), - Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), - Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), - Instruction(opname='STORE_FAST', opcode=107, arg=2, argval='f', argrepr='f', offset=22, start_offset=22, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=1, argval='print', argrepr='print + NULL', offset=24, start_offset=24, starts_line=True, line_number=7, label=None, positions=None, 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')]), - Instruction(opname='LOAD_DEREF', opcode=80, arg=0, argval='a', argrepr='a', offset=34, start_offset=34, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_DEREF', opcode=80, arg=1, argval='b', argrepr='b', offset=36, start_offset=36, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=1, argval='', argrepr="''", offset=38, start_offset=38, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=1, argval=1, argrepr='', offset=40, start_offset=40, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), - Instruction(opname='BUILD_LIST', opcode=43, arg=0, argval=0, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), - Instruction(opname='BUILD_MAP', opcode=44, arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=2, argval='Hello world!', argrepr="'Hello world!'", offset=46, start_offset=46, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=7, argval=7, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=2, argval='f', argrepr='f', offset=58, start_offset=58, starts_line=True, line_number=8, label=None, positions=None, cache_info=None), - Instruction(opname='RETURN_VALUE', opcode=33, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=8, label=None, positions=None, cache_info=None), + Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=104, arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), + Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=104, arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), + Instruction(opname='STORE_FAST', opcode=108, arg=2, argval='f', argrepr='f', offset=22, start_offset=22, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=1, argval='print', argrepr='print + NULL', offset=24, start_offset=24, starts_line=True, line_number=7, label=None, positions=None, 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')]), + Instruction(opname='LOAD_DEREF', opcode=81, arg=0, argval='a', argrepr='a', offset=34, start_offset=34, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_DEREF', opcode=81, arg=1, argval='b', argrepr='b', offset=36, start_offset=36, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=1, argval='', argrepr="''", offset=38, start_offset=38, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_SMALL_INT', opcode=90, arg=1, argval=1, argrepr='', offset=40, start_offset=40, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), + Instruction(opname='BUILD_LIST', opcode=44, arg=0, argval=0, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), + Instruction(opname='BUILD_MAP', opcode=45, arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=2, argval='Hello world!', argrepr="'Hello world!'", offset=46, start_offset=46, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=7, argval=7, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=2, argval='f', argrepr='f', offset=58, start_offset=58, starts_line=True, line_number=8, label=None, positions=None, cache_info=None), + Instruction(opname='RETURN_VALUE', opcode=34, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=8, label=None, positions=None, cache_info=None), ] expected_opinfo_f = [ - Instruction(opname='COPY_FREE_VARS', opcode=58, arg=2, argval=2, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='MAKE_CELL', opcode=92, arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='MAKE_CELL', opcode=92, arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='COPY_FREE_VARS', opcode=59, arg=2, argval=2, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='MAKE_CELL', opcode=93, arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='MAKE_CELL', opcode=93, arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=1, argval=(5, 6), argrepr='(5, 6)', offset=8, start_offset=8, starts_line=True, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=3, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=4, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='c', argrepr='c', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=1, argval='d', argrepr='d', offset=16, start_offset=16, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='BUILD_TUPLE', opcode=48, arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, start_offset=20, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=1, argval=(5, 6), argrepr='(5, 6)', offset=8, start_offset=8, starts_line=True, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=3, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=4, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=0, argval='c', argrepr='c', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=1, argval='d', argrepr='d', offset=16, start_offset=16, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='BUILD_TUPLE', opcode=49, arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=0, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, start_offset=20, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='MAKE_FUNCTION', opcode=23, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='STORE_FAST', opcode=107, arg=2, argval='inner', argrepr='inner', offset=28, start_offset=28, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=1, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=5, label=None, positions=None, 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')]), - Instruction(opname='LOAD_DEREF', opcode=80, arg=3, argval='a', argrepr='a', offset=40, start_offset=40, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_DEREF', opcode=80, arg=4, argval='b', argrepr='b', offset=42, start_offset=42, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_DEREF', opcode=80, arg=0, argval='c', argrepr='c', offset=44, start_offset=44, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_DEREF', opcode=80, arg=1, argval='d', argrepr='d', offset=46, start_offset=46, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=4, argval=4, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=2, argval='inner', argrepr='inner', offset=58, start_offset=58, starts_line=True, line_number=6, label=None, positions=None, cache_info=None), - Instruction(opname='RETURN_VALUE', opcode=33, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=6, label=None, positions=None, cache_info=None), + Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=104, arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=104, arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='STORE_FAST', opcode=108, arg=2, argval='inner', argrepr='inner', offset=28, start_offset=28, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=1, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=5, label=None, positions=None, 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')]), + Instruction(opname='LOAD_DEREF', opcode=81, arg=3, argval='a', argrepr='a', offset=40, start_offset=40, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_DEREF', opcode=81, arg=4, argval='b', argrepr='b', offset=42, start_offset=42, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_DEREF', opcode=81, arg=0, argval='c', argrepr='c', offset=44, start_offset=44, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_DEREF', opcode=81, arg=1, argval='d', argrepr='d', offset=46, start_offset=46, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=4, argval=4, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=2, argval='inner', argrepr='inner', offset=58, start_offset=58, starts_line=True, line_number=6, label=None, positions=None, cache_info=None), + Instruction(opname='RETURN_VALUE', opcode=34, arg=None, argval=None, argrepr='', offset=60, start_offset=60, starts_line=False, line_number=6, label=None, positions=None, cache_info=None), ] expected_opinfo_inner = [ - Instruction(opname='COPY_FREE_VARS', opcode=58, arg=4, argval=4, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='COPY_FREE_VARS', opcode=59, arg=4, argval=4, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=2, start_offset=2, starts_line=True, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=1, argval='print', argrepr='print + NULL', offset=4, start_offset=4, starts_line=True, line_number=4, label=None, positions=None, 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')]), - Instruction(opname='LOAD_DEREF', opcode=80, arg=2, argval='a', argrepr='a', offset=14, start_offset=14, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_DEREF', opcode=80, arg=3, argval='b', argrepr='b', offset=16, start_offset=16, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_DEREF', opcode=80, arg=4, argval='c', argrepr='c', offset=18, start_offset=18, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_DEREF', opcode=80, arg=5, argval='d', argrepr='d', offset=20, start_offset=20, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST_LOAD_FAST', opcode=84, arg=1, argval=('e', 'f'), argrepr='e, f', offset=22, start_offset=22, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=6, argval=6, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=32, start_offset=32, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval=None, argrepr='None', offset=34, start_offset=34, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), - Instruction(opname='RETURN_VALUE', opcode=33, arg=None, argval=None, argrepr='', offset=36, start_offset=36, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=1, argval='print', argrepr='print + NULL', offset=4, start_offset=4, starts_line=True, line_number=4, label=None, positions=None, 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')]), + Instruction(opname='LOAD_DEREF', opcode=81, arg=2, argval='a', argrepr='a', offset=14, start_offset=14, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_DEREF', opcode=81, arg=3, argval='b', argrepr='b', offset=16, start_offset=16, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_DEREF', opcode=81, arg=4, argval='c', argrepr='c', offset=18, start_offset=18, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_DEREF', opcode=81, arg=5, argval='d', argrepr='d', offset=20, start_offset=20, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST_LOAD_FAST', opcode=85, arg=1, argval=('e', 'f'), argrepr='e, f', offset=22, start_offset=22, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=6, argval=6, argrepr='', offset=24, start_offset=24, starts_line=False, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=32, start_offset=32, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=0, argval=None, argrepr='None', offset=34, start_offset=34, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), + Instruction(opname='RETURN_VALUE', opcode=34, arg=None, argval=None, argrepr='', offset=36, start_offset=36, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), ] expected_opinfo_jumpy = [ Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=1, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=1, argval='range', argrepr='range + NULL', offset=2, start_offset=2, starts_line=True, line_number=3, label=None, positions=None, 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')]), - Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=10, argval=10, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=1, argval='range', argrepr='range + NULL', offset=2, start_offset=2, starts_line=True, line_number=3, label=None, positions=None, 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')]), + Instruction(opname='LOAD_SMALL_INT', opcode=90, arg=10, argval=10, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=1, argval=1, argrepr='', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), Instruction(opname='GET_ITER', opcode=16, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='FOR_ITER', opcode=67, arg=30, argval=88, argrepr='to L4', offset=24, start_offset=24, starts_line=False, line_number=3, label=1, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='STORE_FAST', opcode=107, arg=0, argval='i', argrepr='i', offset=28, start_offset=28, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=30, start_offset=30, starts_line=True, line_number=4, label=None, positions=None, 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')]), - Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='i', argrepr='i', offset=40, start_offset=40, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=50, start_offset=50, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='i', argrepr='i', offset=52, start_offset=52, starts_line=True, line_number=5, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=4, argval=4, argrepr='', offset=54, start_offset=54, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), - Instruction(opname='COMPARE_OP', opcode=54, arg=18, argval='<', argrepr='bool(<)', offset=56, start_offset=56, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=95, arg=2, argval=68, argrepr='to L2', offset=60, start_offset=60, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='JUMP_BACKWARD', opcode=72, arg=22, argval=24, argrepr='to L1', offset=64, start_offset=64, starts_line=True, line_number=6, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='i', argrepr='i', offset=68, start_offset=68, starts_line=True, line_number=7, label=2, positions=None, cache_info=None), - Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=6, argval=6, argrepr='', offset=70, start_offset=70, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), - Instruction(opname='COMPARE_OP', opcode=54, arg=148, argval='>', argrepr='bool(>)', offset=72, start_offset=72, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=98, arg=2, argval=84, argrepr='to L3', offset=76, start_offset=76, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='JUMP_BACKWARD', opcode=72, arg=30, argval=24, argrepr='to L1', offset=80, start_offset=80, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=84, start_offset=84, starts_line=True, line_number=8, label=3, positions=None, cache_info=None), - Instruction(opname='JUMP_FORWARD', opcode=74, arg=13, argval=114, argrepr='to L5', offset=86, start_offset=86, starts_line=False, line_number=8, label=None, positions=None, cache_info=None), - Instruction(opname='END_FOR', opcode=9, arg=None, argval=None, argrepr='', offset=88, start_offset=88, starts_line=True, line_number=3, label=4, positions=None, cache_info=None), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=92, start_offset=92, starts_line=True, line_number=10, label=None, positions=None, 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')]), - Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=102, start_offset=102, starts_line=False, line_number=10, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=104, start_offset=104, starts_line=False, line_number=10, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=112, start_offset=112, starts_line=False, line_number=10, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST_CHECK', opcode=83, arg=0, argval='i', argrepr='i', offset=114, start_offset=114, starts_line=True, line_number=11, label=5, positions=None, cache_info=None), - Instruction(opname='TO_BOOL', opcode=37, arg=None, argval=None, argrepr='', offset=116, start_offset=116, starts_line=False, line_number=11, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=95, arg=33, argval=194, argrepr='to L8', offset=124, start_offset=124, starts_line=False, line_number=11, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=128, start_offset=128, starts_line=True, line_number=12, label=None, positions=None, 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')]), - Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='i', argrepr='i', offset=138, start_offset=138, starts_line=False, line_number=12, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=140, start_offset=140, starts_line=False, line_number=12, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=148, start_offset=148, starts_line=False, line_number=12, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='i', argrepr='i', offset=150, start_offset=150, starts_line=True, line_number=13, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=1, argval=1, argrepr='', offset=152, start_offset=152, starts_line=False, line_number=13, label=None, positions=None, cache_info=None), - Instruction(opname='BINARY_OP', opcode=42, arg=23, argval=23, argrepr='-=', offset=154, start_offset=154, starts_line=False, line_number=13, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='STORE_FAST', opcode=107, arg=0, argval='i', argrepr='i', offset=158, start_offset=158, starts_line=False, line_number=13, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='i', argrepr='i', offset=160, start_offset=160, starts_line=True, line_number=14, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=6, argval=6, argrepr='', offset=162, start_offset=162, starts_line=False, line_number=14, label=None, positions=None, cache_info=None), - Instruction(opname='COMPARE_OP', opcode=54, arg=148, argval='>', argrepr='bool(>)', offset=164, start_offset=164, starts_line=False, line_number=14, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=95, arg=2, argval=176, argrepr='to L6', offset=168, start_offset=168, starts_line=False, line_number=14, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='JUMP_BACKWARD', opcode=72, arg=31, argval=114, argrepr='to L5', offset=172, start_offset=172, starts_line=True, line_number=15, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='i', argrepr='i', offset=176, start_offset=176, starts_line=True, line_number=16, label=6, positions=None, cache_info=None), - Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=4, argval=4, argrepr='', offset=178, start_offset=178, starts_line=False, line_number=16, label=None, positions=None, cache_info=None), - Instruction(opname='COMPARE_OP', opcode=54, arg=18, argval='<', argrepr='bool(<)', offset=180, start_offset=180, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=98, arg=2, argval=192, argrepr='to L7', offset=184, start_offset=184, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='JUMP_BACKWARD', opcode=72, arg=39, argval=114, argrepr='to L5', offset=188, start_offset=188, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='JUMP_FORWARD', opcode=74, arg=11, argval=216, argrepr='to L9', offset=192, start_offset=192, starts_line=True, line_number=17, label=7, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=194, start_offset=194, starts_line=True, line_number=19, label=8, positions=None, 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')]), - Instruction(opname='LOAD_CONST', opcode=79, arg=1, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=204, start_offset=204, starts_line=False, line_number=19, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=206, start_offset=206, starts_line=False, line_number=19, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=214, start_offset=214, starts_line=False, line_number=19, label=None, positions=None, cache_info=None), - Instruction(opname='NOP', opcode=27, arg=None, argval=None, argrepr='', offset=216, start_offset=216, starts_line=True, line_number=20, label=9, positions=None, cache_info=None), - Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=1, argval=1, argrepr='', offset=218, start_offset=218, starts_line=True, line_number=21, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=0, argval=0, argrepr='', offset=220, start_offset=220, starts_line=False, line_number=21, label=None, positions=None, cache_info=None), - Instruction(opname='BINARY_OP', opcode=42, arg=11, argval=11, argrepr='/', offset=222, start_offset=222, starts_line=False, line_number=21, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=226, start_offset=226, starts_line=False, line_number=21, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='i', argrepr='i', offset=228, start_offset=228, starts_line=True, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='COPY', opcode=57, arg=1, argval=1, argrepr='', offset=230, start_offset=230, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_SPECIAL', opcode=90, arg=1, argval=1, argrepr='__exit__', offset=232, start_offset=232, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='SWAP', opcode=112, arg=2, argval=2, argrepr='', offset=234, start_offset=234, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='SWAP', opcode=112, arg=3, argval=3, argrepr='', offset=236, start_offset=236, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_SPECIAL', opcode=90, arg=0, argval=0, argrepr='__enter__', offset=238, start_offset=238, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=0, argval=0, argrepr='', offset=240, start_offset=240, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='STORE_FAST', opcode=107, arg=1, argval='dodgy', argrepr='dodgy', offset=248, start_offset=248, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=250, start_offset=250, starts_line=True, line_number=26, label=None, positions=None, 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')]), - Instruction(opname='LOAD_CONST', opcode=79, arg=2, argval='Never reach this', argrepr="'Never reach this'", offset=260, start_offset=260, starts_line=False, line_number=26, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=270, start_offset=270, starts_line=False, line_number=26, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval=None, argrepr='None', offset=272, start_offset=272, starts_line=True, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval=None, argrepr='None', offset=274, start_offset=274, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval=None, argrepr='None', offset=276, start_offset=276, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=3, argval=3, argrepr='', offset=278, start_offset=278, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=286, start_offset=286, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=288, start_offset=288, starts_line=True, line_number=28, label=10, positions=None, 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')]), - Instruction(opname='LOAD_CONST', opcode=79, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=298, start_offset=298, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=300, start_offset=300, starts_line=False, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=308, start_offset=308, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval=None, argrepr='None', offset=310, start_offset=310, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), - Instruction(opname='RETURN_VALUE', opcode=33, arg=None, argval=None, argrepr='', offset=312, start_offset=312, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), - Instruction(opname='PUSH_EXC_INFO', opcode=30, arg=None, argval=None, argrepr='', offset=314, start_offset=314, starts_line=True, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='WITH_EXCEPT_START', opcode=41, arg=None, argval=None, argrepr='', offset=316, start_offset=316, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='TO_BOOL', opcode=37, arg=None, argval=None, argrepr='', offset=318, start_offset=318, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=98, arg=1, argval=332, argrepr='to L11', offset=326, start_offset=326, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='RERAISE', opcode=100, arg=2, argval=2, argrepr='', offset=330, start_offset=330, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=332, start_offset=332, starts_line=False, line_number=25, label=11, positions=None, cache_info=None), - Instruction(opname='POP_EXCEPT', opcode=28, arg=None, argval=None, argrepr='', offset=334, start_offset=334, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=336, start_offset=336, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=338, start_offset=338, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=340, start_offset=340, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=73, arg=28, argval=288, argrepr='to L10', offset=342, start_offset=342, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), - Instruction(opname='COPY', opcode=57, arg=3, argval=3, argrepr='', offset=344, start_offset=344, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='POP_EXCEPT', opcode=28, arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='RERAISE', opcode=100, arg=1, argval=1, argrepr='', offset=348, start_offset=348, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='PUSH_EXC_INFO', opcode=30, arg=None, argval=None, argrepr='', offset=350, start_offset=350, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=352, start_offset=352, starts_line=True, line_number=22, label=None, positions=None, 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')]), - Instruction(opname='CHECK_EXC_MATCH', opcode=5, arg=None, argval=None, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=22, label=None, positions=None, cache_info=None), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=95, arg=14, argval=396, argrepr='to L12', offset=364, start_offset=364, starts_line=False, line_number=22, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=22, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=370, start_offset=370, starts_line=True, line_number=23, label=None, positions=None, 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')]), - Instruction(opname='LOAD_CONST', opcode=79, arg=4, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=380, start_offset=380, starts_line=False, line_number=23, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=382, start_offset=382, starts_line=False, line_number=23, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=390, start_offset=390, starts_line=False, line_number=23, label=None, positions=None, cache_info=None), - Instruction(opname='POP_EXCEPT', opcode=28, arg=None, argval=None, argrepr='', offset=392, start_offset=392, starts_line=False, line_number=23, label=None, positions=None, cache_info=None), - Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=73, arg=54, argval=288, argrepr='to L10', offset=394, start_offset=394, starts_line=False, line_number=23, label=None, positions=None, cache_info=None), - Instruction(opname='RERAISE', opcode=100, arg=0, argval=0, argrepr='', offset=396, start_offset=396, starts_line=True, line_number=22, label=12, positions=None, cache_info=None), - Instruction(opname='COPY', opcode=57, arg=3, argval=3, argrepr='', offset=398, start_offset=398, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='POP_EXCEPT', opcode=28, arg=None, argval=None, argrepr='', offset=400, start_offset=400, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='RERAISE', opcode=100, arg=1, argval=1, argrepr='', offset=402, start_offset=402, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='PUSH_EXC_INFO', opcode=30, arg=None, argval=None, argrepr='', offset=404, start_offset=404, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=406, start_offset=406, starts_line=True, line_number=28, label=None, positions=None, 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')]), - Instruction(opname='LOAD_CONST', opcode=79, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=416, start_offset=416, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), - Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=418, start_offset=418, starts_line=False, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), - Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=426, start_offset=426, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), - Instruction(opname='RERAISE', opcode=100, arg=0, argval=0, argrepr='', offset=428, start_offset=428, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), - Instruction(opname='COPY', opcode=57, arg=3, argval=3, argrepr='', offset=430, start_offset=430, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='POP_EXCEPT', opcode=28, arg=None, argval=None, argrepr='', offset=432, start_offset=432, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), - Instruction(opname='RERAISE', opcode=100, arg=1, argval=1, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='FOR_ITER', opcode=68, arg=34, argval=96, argrepr='to L4', offset=24, start_offset=24, starts_line=False, line_number=3, label=1, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=28, start_offset=28, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='STORE_FAST', opcode=108, arg=0, argval='i', argrepr='i', offset=30, start_offset=30, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=3, argval='print', argrepr='print + NULL', offset=32, start_offset=32, starts_line=True, line_number=4, label=None, positions=None, 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')]), + Instruction(opname='LOAD_FAST', opcode=82, arg=0, argval='i', argrepr='i', offset=42, start_offset=42, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=1, argval=1, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=4, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=52, start_offset=52, starts_line=False, line_number=4, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=0, argval='i', argrepr='i', offset=54, start_offset=54, starts_line=True, line_number=5, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_SMALL_INT', opcode=90, arg=4, argval=4, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), + Instruction(opname='COMPARE_OP', opcode=55, arg=18, argval='<', argrepr='bool(<)', offset=58, start_offset=58, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=96, arg=3, argval=72, argrepr='to L2', offset=62, start_offset=62, starts_line=False, line_number=5, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=66, start_offset=66, starts_line=False, line_number=5, label=None, positions=None, cache_info=None), + Instruction(opname='JUMP_BACKWARD', opcode=73, arg=24, argval=24, argrepr='to L1', offset=68, start_offset=68, starts_line=True, line_number=6, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='LOAD_FAST', opcode=82, arg=0, argval='i', argrepr='i', offset=72, start_offset=72, starts_line=True, line_number=7, label=2, positions=None, cache_info=None), + Instruction(opname='LOAD_SMALL_INT', opcode=90, arg=6, argval=6, argrepr='', offset=74, start_offset=74, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), + Instruction(opname='COMPARE_OP', opcode=55, arg=148, argval='>', argrepr='bool(>)', offset=76, start_offset=76, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=99, arg=3, argval=90, argrepr='to L3', offset=80, start_offset=80, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=84, start_offset=84, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), + Instruction(opname='JUMP_BACKWARD', opcode=73, arg=33, argval=24, argrepr='to L1', offset=86, start_offset=86, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='NOP', opcode=27, arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=True, line_number=None, label=3, positions=None, cache_info=None), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=92, start_offset=92, starts_line=True, line_number=8, label=None, positions=None, cache_info=None), + Instruction(opname='JUMP_FORWARD', opcode=75, arg=13, argval=122, argrepr='to L5', offset=94, start_offset=94, starts_line=False, line_number=8, label=None, positions=None, cache_info=None), + Instruction(opname='END_FOR', opcode=9, arg=None, argval=None, argrepr='', offset=96, start_offset=96, starts_line=True, line_number=3, label=4, positions=None, cache_info=None), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=98, start_offset=98, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=3, argval='print', argrepr='print + NULL', offset=100, start_offset=100, starts_line=True, line_number=10, label=None, positions=None, 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')]), + Instruction(opname='LOAD_CONST', opcode=80, arg=0, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=110, start_offset=110, starts_line=False, line_number=10, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=1, argval=1, argrepr='', offset=112, start_offset=112, starts_line=False, line_number=10, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=120, start_offset=120, starts_line=False, line_number=10, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST_CHECK', opcode=84, arg=0, argval='i', argrepr='i', offset=122, start_offset=122, starts_line=True, line_number=11, label=5, positions=None, cache_info=None), + Instruction(opname='TO_BOOL', opcode=38, arg=None, argval=None, argrepr='', offset=124, start_offset=124, starts_line=False, line_number=11, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=96, arg=37, argval=210, argrepr='to L8', offset=132, start_offset=132, starts_line=False, line_number=11, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=136, start_offset=136, starts_line=False, line_number=11, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=3, argval='print', argrepr='print + NULL', offset=138, start_offset=138, starts_line=True, line_number=12, label=None, positions=None, 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')]), + Instruction(opname='LOAD_FAST', opcode=82, arg=0, argval='i', argrepr='i', offset=148, start_offset=148, starts_line=False, line_number=12, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=1, argval=1, argrepr='', offset=150, start_offset=150, starts_line=False, line_number=12, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=158, start_offset=158, starts_line=False, line_number=12, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=0, argval='i', argrepr='i', offset=160, start_offset=160, starts_line=True, line_number=13, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_SMALL_INT', opcode=90, arg=1, argval=1, argrepr='', offset=162, start_offset=162, starts_line=False, line_number=13, label=None, positions=None, cache_info=None), + Instruction(opname='BINARY_OP', opcode=43, arg=23, argval=23, argrepr='-=', offset=164, start_offset=164, starts_line=False, line_number=13, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='STORE_FAST', opcode=108, arg=0, argval='i', argrepr='i', offset=168, start_offset=168, starts_line=False, line_number=13, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=0, argval='i', argrepr='i', offset=170, start_offset=170, starts_line=True, line_number=14, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_SMALL_INT', opcode=90, arg=6, argval=6, argrepr='', offset=172, start_offset=172, starts_line=False, line_number=14, label=None, positions=None, cache_info=None), + Instruction(opname='COMPARE_OP', opcode=55, arg=148, argval='>', argrepr='bool(>)', offset=174, start_offset=174, starts_line=False, line_number=14, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=96, arg=3, argval=188, argrepr='to L6', offset=178, start_offset=178, starts_line=False, line_number=14, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=182, start_offset=182, starts_line=False, line_number=14, label=None, positions=None, cache_info=None), + Instruction(opname='JUMP_BACKWARD', opcode=73, arg=33, argval=122, argrepr='to L5', offset=184, start_offset=184, starts_line=True, line_number=15, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='LOAD_FAST', opcode=82, arg=0, argval='i', argrepr='i', offset=188, start_offset=188, starts_line=True, line_number=16, label=6, positions=None, cache_info=None), + Instruction(opname='LOAD_SMALL_INT', opcode=90, arg=4, argval=4, argrepr='', offset=190, start_offset=190, starts_line=False, line_number=16, label=None, positions=None, cache_info=None), + Instruction(opname='COMPARE_OP', opcode=55, arg=18, argval='<', argrepr='bool(<)', offset=192, start_offset=192, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=99, arg=3, argval=206, argrepr='to L7', offset=196, start_offset=196, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=200, start_offset=200, starts_line=False, line_number=16, label=None, positions=None, cache_info=None), + Instruction(opname='JUMP_BACKWARD', opcode=73, arg=42, argval=122, argrepr='to L5', offset=202, start_offset=202, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='NOP', opcode=27, arg=None, argval=None, argrepr='', offset=206, start_offset=206, starts_line=True, line_number=None, label=7, positions=None, cache_info=None), + Instruction(opname='JUMP_FORWARD', opcode=75, arg=11, argval=232, argrepr='to L9', offset=208, start_offset=208, starts_line=True, line_number=17, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=3, argval='print', argrepr='print + NULL', offset=210, start_offset=210, starts_line=True, line_number=19, label=8, positions=None, 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')]), + Instruction(opname='LOAD_CONST', opcode=80, arg=1, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=220, start_offset=220, starts_line=False, line_number=19, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=1, argval=1, argrepr='', offset=222, start_offset=222, starts_line=False, line_number=19, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=230, start_offset=230, starts_line=False, line_number=19, label=None, positions=None, cache_info=None), + Instruction(opname='NOP', opcode=27, arg=None, argval=None, argrepr='', offset=232, start_offset=232, starts_line=True, line_number=20, label=9, positions=None, cache_info=None), + Instruction(opname='LOAD_SMALL_INT', opcode=90, arg=1, argval=1, argrepr='', offset=234, start_offset=234, starts_line=True, line_number=21, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_SMALL_INT', opcode=90, arg=0, argval=0, argrepr='', offset=236, start_offset=236, starts_line=False, line_number=21, label=None, positions=None, cache_info=None), + Instruction(opname='BINARY_OP', opcode=43, arg=11, argval=11, argrepr='/', offset=238, start_offset=238, starts_line=False, line_number=21, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=242, start_offset=242, starts_line=False, line_number=21, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_FAST', opcode=82, arg=0, argval='i', argrepr='i', offset=244, start_offset=244, starts_line=True, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='COPY', opcode=58, arg=1, argval=1, argrepr='', offset=246, start_offset=246, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_SPECIAL', opcode=91, arg=1, argval=1, argrepr='__exit__', offset=248, start_offset=248, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='SWAP', opcode=113, arg=2, argval=2, argrepr='', offset=250, start_offset=250, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='SWAP', opcode=113, arg=3, argval=3, argrepr='', offset=252, start_offset=252, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_SPECIAL', opcode=91, arg=0, argval=0, argrepr='__enter__', offset=254, start_offset=254, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=0, argval=0, argrepr='', offset=256, start_offset=256, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='STORE_FAST', opcode=108, arg=1, argval='dodgy', argrepr='dodgy', offset=264, start_offset=264, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=3, argval='print', argrepr='print + NULL', offset=266, start_offset=266, starts_line=True, line_number=26, label=None, positions=None, 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')]), + Instruction(opname='LOAD_CONST', opcode=80, arg=2, argval='Never reach this', argrepr="'Never reach this'", offset=276, start_offset=276, starts_line=False, line_number=26, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=1, argval=1, argrepr='', offset=278, start_offset=278, starts_line=False, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=286, start_offset=286, starts_line=False, line_number=26, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=3, argval=None, argrepr='None', offset=288, start_offset=288, starts_line=True, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=3, argval=None, argrepr='None', offset=290, start_offset=290, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=3, argval=None, argrepr='None', offset=292, start_offset=292, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=3, argval=3, argrepr='', offset=294, start_offset=294, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=302, start_offset=302, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=3, argval='print', argrepr='print + NULL', offset=304, start_offset=304, starts_line=True, line_number=28, label=10, positions=None, 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')]), + Instruction(opname='LOAD_CONST', opcode=80, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=314, start_offset=314, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=1, argval=1, argrepr='', offset=316, start_offset=316, starts_line=False, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=324, start_offset=324, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=3, argval=None, argrepr='None', offset=326, start_offset=326, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), + Instruction(opname='RETURN_VALUE', opcode=34, arg=None, argval=None, argrepr='', offset=328, start_offset=328, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), + Instruction(opname='PUSH_EXC_INFO', opcode=31, arg=None, argval=None, argrepr='', offset=330, start_offset=330, starts_line=True, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='WITH_EXCEPT_START', opcode=42, arg=None, argval=None, argrepr='', offset=332, start_offset=332, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='TO_BOOL', opcode=38, arg=None, argval=None, argrepr='', offset=334, start_offset=334, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=99, arg=2, argval=350, argrepr='to L11', offset=342, start_offset=342, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=346, start_offset=346, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='RERAISE', opcode=101, arg=2, argval=2, argrepr='', offset=348, start_offset=348, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=350, start_offset=350, starts_line=False, line_number=25, label=11, positions=None, cache_info=None), + Instruction(opname='POP_EXCEPT', opcode=29, arg=None, argval=None, argrepr='', offset=352, start_offset=352, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=354, start_offset=354, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=356, start_offset=356, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=358, start_offset=358, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=74, arg=29, argval=304, argrepr='to L10', offset=360, start_offset=360, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), + Instruction(opname='COPY', opcode=58, arg=3, argval=3, argrepr='', offset=362, start_offset=362, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='POP_EXCEPT', opcode=29, arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='RERAISE', opcode=101, arg=1, argval=1, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='PUSH_EXC_INFO', opcode=31, arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=370, start_offset=370, starts_line=True, line_number=22, label=None, positions=None, 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')]), + Instruction(opname='CHECK_EXC_MATCH', opcode=5, arg=None, argval=None, argrepr='', offset=380, start_offset=380, starts_line=False, line_number=22, label=None, positions=None, cache_info=None), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=96, arg=15, argval=416, argrepr='to L12', offset=382, start_offset=382, starts_line=False, line_number=22, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), + Instruction(opname='NOT_TAKEN', opcode=28, arg=None, argval=None, argrepr='', offset=386, start_offset=386, starts_line=False, line_number=22, label=None, positions=None, cache_info=None), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=388, start_offset=388, starts_line=False, line_number=22, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=3, argval='print', argrepr='print + NULL', offset=390, start_offset=390, starts_line=True, line_number=23, label=None, positions=None, 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')]), + Instruction(opname='LOAD_CONST', opcode=80, arg=4, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=400, start_offset=400, starts_line=False, line_number=23, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=1, argval=1, argrepr='', offset=402, start_offset=402, starts_line=False, line_number=23, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=410, start_offset=410, starts_line=False, line_number=23, label=None, positions=None, cache_info=None), + Instruction(opname='POP_EXCEPT', opcode=29, arg=None, argval=None, argrepr='', offset=412, start_offset=412, starts_line=False, line_number=23, label=None, positions=None, cache_info=None), + Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=74, arg=56, argval=304, argrepr='to L10', offset=414, start_offset=414, starts_line=False, line_number=23, label=None, positions=None, cache_info=None), + Instruction(opname='RERAISE', opcode=101, arg=0, argval=0, argrepr='', offset=416, start_offset=416, starts_line=True, line_number=22, label=12, positions=None, cache_info=None), + Instruction(opname='COPY', opcode=58, arg=3, argval=3, argrepr='', offset=418, start_offset=418, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='POP_EXCEPT', opcode=29, arg=None, argval=None, argrepr='', offset=420, start_offset=420, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='RERAISE', opcode=101, arg=1, argval=1, argrepr='', offset=422, start_offset=422, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='PUSH_EXC_INFO', opcode=31, arg=None, argval=None, argrepr='', offset=424, start_offset=424, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='LOAD_GLOBAL', opcode=88, arg=3, argval='print', argrepr='print + NULL', offset=426, start_offset=426, starts_line=True, line_number=28, label=None, positions=None, 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')]), + Instruction(opname='LOAD_CONST', opcode=80, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=436, start_offset=436, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), + Instruction(opname='CALL', opcode=50, arg=1, argval=1, argrepr='', offset=438, start_offset=438, starts_line=False, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), + Instruction(opname='POP_TOP', opcode=30, arg=None, argval=None, argrepr='', offset=446, start_offset=446, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), + Instruction(opname='RERAISE', opcode=101, arg=0, argval=0, argrepr='', offset=448, start_offset=448, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), + Instruction(opname='COPY', opcode=58, arg=3, argval=3, argrepr='', offset=450, start_offset=450, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='POP_EXCEPT', opcode=29, arg=None, argval=None, argrepr='', offset=452, start_offset=452, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), + Instruction(opname='RERAISE', opcode=101, arg=1, argval=1, argrepr='', offset=454, start_offset=454, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), ] # One last piece of inspect fodder to check the default line number handling def simple(): pass expected_opinfo_simple = [ Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=0, start_offset=0, starts_line=True, line_number=simple.__code__.co_firstlineno, label=None, positions=None), - Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval=None, argrepr='None', offset=2, start_offset=2, starts_line=False, line_number=simple.__code__.co_firstlineno, label=None), - Instruction(opname='RETURN_VALUE', opcode=33, arg=None, argval=None, argrepr='', offset=4, start_offset=4, starts_line=False, line_number=simple.__code__.co_firstlineno, label=None), + Instruction(opname='LOAD_CONST', opcode=80, arg=0, argval=None, argrepr='None', offset=2, start_offset=2, starts_line=False, line_number=simple.__code__.co_firstlineno, label=None), + Instruction(opname='RETURN_VALUE', opcode=34, arg=None, argval=None, argrepr='', offset=4, start_offset=4, starts_line=False, line_number=simple.__code__.co_firstlineno, label=None), ] diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 5a4bcebedf19de..087ac8d456b843 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1491,7 +1491,15 @@ class BranchRecorder(JumpRecorder): event_type = E.BRANCH name = "branch" +class BranchRightRecorder(JumpRecorder): + event_type = E.BRANCH_RIGHT + name = "branch right" + +class BranchLeftRecorder(JumpRecorder): + + event_type = E.BRANCH_LEFT + name = "branch left" class JumpOffsetRecorder: @@ -1504,16 +1512,23 @@ def __init__(self, events, offsets=False): def __call__(self, code, from_, to): self.events.append((self.name, code.co_name, from_, to)) -class BranchOffsetRecorder(JumpOffsetRecorder): +class BranchLeftOffsetRecorder(JumpOffsetRecorder): - event_type = E.BRANCH - name = "branch" + event_type = E.BRANCH_LEFT + name = "branch left" + +class BranchRightOffsetRecorder(JumpOffsetRecorder): + + event_type = E.BRANCH_RIGHT + name = "branch right" JUMP_AND_BRANCH_RECORDERS = JumpRecorder, BranchRecorder JUMP_BRANCH_AND_LINE_RECORDERS = JumpRecorder, BranchRecorder, LineRecorder FLOW_AND_LINE_RECORDERS = JumpRecorder, BranchRecorder, LineRecorder, ExceptionRecorder, ReturnRecorder -BRANCH_OFFSET_RECORDERS = BranchOffsetRecorder, + +BRANCHES_RECORDERS = BranchLeftRecorder, BranchRightRecorder +BRANCH_OFFSET_RECORDERS = BranchLeftOffsetRecorder, BranchRightOffsetRecorder class TestBranchAndJumpEvents(CheckEvents): maxDiff = None @@ -1529,6 +1544,11 @@ def func(): x = 6 7 + def whilefunc(n=0): + while n < 3: + n += 1 # line 2 + 3 + self.check_events(func, recorders = JUMP_AND_BRANCH_RECORDERS, expected = [ ('branch', 'func', 2, 2), ('branch', 'func', 3, 6), @@ -1558,6 +1578,26 @@ def func(): ('line', 'func', 7), ('line', 'get_events', 11)]) + self.check_events(func, recorders = BRANCHES_RECORDERS, expected = [ + ('branch left', 'func', 2, 2), + ('branch right', 'func', 3, 6), + ('branch left', 'func', 2, 2), + ('branch left', 'func', 3, 4), + ('branch right', 'func', 2, 7)]) + + self.check_events(whilefunc, recorders = BRANCHES_RECORDERS, expected = [ + ('branch left', 'whilefunc', 1, 2), + ('branch left', 'whilefunc', 1, 2), + ('branch left', 'whilefunc', 1, 2), + ('branch right', 'whilefunc', 1, 3)]) + + self.check_events(func, recorders = BRANCH_OFFSET_RECORDERS, expected = [ + ('branch left', 'func', 28, 34), + ('branch right', 'func', 46, 60), + ('branch left', 'func', 28, 34), + ('branch left', 'func', 46, 52), + ('branch right', 'func', 28, 72)]) + def test_except_star(self): class Foo: @@ -1583,8 +1623,8 @@ def func(): ('branch', 'func', 4, 4), ('line', 'func', 5), ('line', 'meth', 1), - ('jump', 'func', 5, '[offset=118]'), - ('branch', 'func', '[offset=122]', '[offset=126]'), + ('jump', 'func', 5, '[offset=120]'), + ('branch', 'func', '[offset=124]', '[offset=130]'), ('line', 'get_events', 11)]) self.check_events(func, recorders = FLOW_AND_LINE_RECORDERS, expected = [ @@ -1598,8 +1638,8 @@ def func(): ('line', 'func', 5), ('line', 'meth', 1), ('return', 'meth', None), - ('jump', 'func', 5, '[offset=118]'), - ('branch', 'func', '[offset=122]', '[offset=126]'), + ('jump', 'func', 5, '[offset=120]'), + ('branch', 'func', '[offset=124]', '[offset=130]'), ('return', 'func', None), ('line', 'get_events', 11)]) @@ -1611,8 +1651,8 @@ def foo(n=0): n += 1 return None - in_loop = ('branch', 'foo', 10, 14) - exit_loop = ('branch', 'foo', 10, 30) + in_loop = ('branch left', 'foo', 10, 16) + exit_loop = ('branch right', 'foo', 10, 32) self.check_events(foo, recorders = BRANCH_OFFSET_RECORDERS, expected = [ in_loop, in_loop, @@ -1852,6 +1892,10 @@ def test_local(self): code = f1.__code__ sys.monitoring.set_local_events(TEST_TOOL, code, E.PY_START) self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL, code), E.PY_START) + sys.monitoring.set_local_events(TEST_TOOL, code, 0) + sys.monitoring.set_local_events(TEST_TOOL, code, E.BRANCH) + self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL, code), E.BRANCH_LEFT | E.BRANCH_RIGHT) + sys.monitoring.set_local_events(TEST_TOOL, code, 0) sys.monitoring.set_local_events(TEST_TOOL2, code, E.PY_START) self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL2, code), E.PY_START) sys.monitoring.set_local_events(TEST_TOOL, code, 0) @@ -2053,7 +2097,8 @@ def setUp(self): ( 1, E.PY_RETURN, capi.fire_event_py_return, 20), ( 2, E.CALL, capi.fire_event_call, callable, 40), ( 1, E.JUMP, capi.fire_event_jump, 60), - ( 1, E.BRANCH, capi.fire_event_branch, 70), + ( 1, E.BRANCH_RIGHT, capi.fire_event_branch_right, 70), + ( 1, E.BRANCH_LEFT, capi.fire_event_branch_left, 80), ( 1, E.PY_THROW, capi.fire_event_py_throw, ValueError(1)), ( 1, E.RAISE, capi.fire_event_raise, ValueError(2)), ( 1, E.EXCEPTION_HANDLED, capi.fire_event_exception_handled, ValueError(5)), diff --git a/Misc/NEWS.d/next/Library/2024-12-13-14-21-04.gh-issue-122548.hq3Vud.rst b/Misc/NEWS.d/next/Library/2024-12-13-14-21-04.gh-issue-122548.hq3Vud.rst new file mode 100644 index 00000000000000..6cd13572ff1893 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-12-13-14-21-04.gh-issue-122548.hq3Vud.rst @@ -0,0 +1,4 @@ +Adds two new local events to sys.monitoring, ``BRANCH_LEFT`` and +``BRANCH_RIGHT``. This allows the two arms of the branch to be disabled +independently, which should hugely improve performance of branch-level +coverage tools. The old branch event, ``BRANCH`` is now deprecated. diff --git a/Modules/_testcapi/monitoring.c b/Modules/_testcapi/monitoring.c index 6fd4a405688f48..e475e3b5937199 100644 --- a/Modules/_testcapi/monitoring.c +++ b/Modules/_testcapi/monitoring.c @@ -286,7 +286,7 @@ fire_event_jump(PyObject *self, PyObject *args) } static PyObject * -fire_event_branch(PyObject *self, PyObject *args) +fire_event_branch_right(PyObject *self, PyObject *args) { PyObject *codelike; int offset; @@ -299,7 +299,25 @@ fire_event_branch(PyObject *self, PyObject *args) if (state == NULL) { return NULL; } - int res = PyMonitoring_FireBranchEvent(state, codelike, offset, target_offset); + int res = PyMonitoring_FireBranchRightEvent(state, codelike, offset, target_offset); + RETURN_INT(teardown_fire(res, state, exception)); +} + +static PyObject * +fire_event_branch_left(PyObject *self, PyObject *args) +{ + PyObject *codelike; + int offset; + PyObject *target_offset; + if (!PyArg_ParseTuple(args, "OiO", &codelike, &offset, &target_offset)) { + return NULL; + } + PyObject *exception = NULL; + PyMonitoringState *state = setup_fire(codelike, offset, exception); + if (state == NULL) { + return NULL; + } + int res = PyMonitoring_FireBranchLeftEvent(state, codelike, offset, target_offset); RETURN_INT(teardown_fire(res, state, exception)); } @@ -478,7 +496,8 @@ static PyMethodDef TestMethods[] = { {"fire_event_call", fire_event_call, METH_VARARGS}, {"fire_event_line", fire_event_line, METH_VARARGS}, {"fire_event_jump", fire_event_jump, METH_VARARGS}, - {"fire_event_branch", fire_event_branch, METH_VARARGS}, + {"fire_event_branch_left", fire_event_branch_left, METH_VARARGS}, + {"fire_event_branch_right", fire_event_branch_right, METH_VARARGS}, {"fire_event_py_throw", fire_event_py_throw, METH_VARARGS}, {"fire_event_raise", fire_event_raise, METH_VARARGS}, {"fire_event_c_raise", fire_event_c_raise, METH_VARARGS}, diff --git a/Objects/codeobject.c b/Objects/codeobject.c index eb8de136ee6432..ae232cae86799b 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -2197,6 +2197,12 @@ code_linesiterator(PyObject *self, PyObject *Py_UNUSED(args)) return (PyObject *)new_linesiterator(code); } +static PyObject * +code_branchesiterator(PyCodeObject *code, PyObject *Py_UNUSED(args)) +{ + return _PyInstrumentation_BranchesIterator(code); +} + /*[clinic input] @text_signature "($self, /, **changes)" code.replace @@ -2337,6 +2343,7 @@ code__varname_from_oparg_impl(PyCodeObject *self, int oparg) static struct PyMethodDef code_methods[] = { {"__sizeof__", code_sizeof, METH_NOARGS}, {"co_lines", code_linesiterator, METH_NOARGS}, + {"co_branches", (PyCFunction)code_branchesiterator, METH_NOARGS}, {"co_positions", code_positionsiterator, METH_NOARGS}, CODE_REPLACE_METHODDEF CODE__VARNAME_FROM_OPARG_METHODDEF diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index 99b0fa48e01c8b..a0007830e8cbc0 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,37 +1,37 @@ // 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,168,0,0,0,149,0,89,0,79,0, - 70,0,111,0,89,0,79,0,70,1,111,1,88,2,31,0, - 79,1,49,1,0,0,0,0,0,0,29,0,88,2,31,0, - 79,2,88,0,77,6,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,49,2,0,0,0,0,0,0, - 29,0,88,1,77,8,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,31,0,49,0,0,0,0,0, - 0,0,79,3,2,0,0,0,111,5,79,4,16,0,67,20, - 0,0,111,6,88,2,31,0,79,5,88,6,12,0,79,6, - 88,5,88,6,2,0,0,0,12,0,47,4,49,1,0,0, - 0,0,0,0,29,0,72,22,0,0,9,0,29,0,79,0, - 33,0,41,7,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,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,122,7,99,111,110, - 102,105,103,32,122,2,58,32,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,2,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,17,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,209,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,153,59,152,45,208,10,40,214, - 4,41,243,15,6,12,2,114,15,0,0,0, + 0,0,0,0,0,243,170,0,0,0,149,0,90,0,80,0, + 71,0,112,0,90,0,80,0,71,1,112,1,89,2,32,0, + 80,1,50,1,0,0,0,0,0,0,30,0,89,2,32,0, + 80,2,89,0,78,6,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,50,2,0,0,0,0,0,0, + 30,0,89,1,78,8,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,32,0,50,0,0,0,0,0, + 0,0,80,3,2,0,0,0,112,5,80,4,16,0,68,21, + 0,0,28,0,112,6,89,2,32,0,80,5,89,6,12,0, + 80,6,89,5,89,6,2,0,0,0,12,0,48,4,50,1, + 0,0,0,0,0,0,30,0,73,23,0,0,9,0,30,0, + 80,0,34,0,41,7,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,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,122,7,99, + 111,110,102,105,103,32,122,2,58,32,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,2, + 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,17,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,209,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,153,59,152,45,208,10, + 40,214,4,41,243,15,6,12,2,114,15,0,0,0, }; diff --git a/Python/bytecodes.c b/Python/bytecodes.c index b67264f0440869..cf089c368b651c 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -148,6 +148,8 @@ dummy_func( RESUME_CHECK, }; + macro(NOT_TAKEN) = NOP; + op(_CHECK_PERIODIC, (--)) { _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY(); QSBR_QUIESCENT_STATE(tstate); @@ -2723,7 +2725,7 @@ dummy_func( int flag = PyStackRef_IsFalse(cond); DEAD(cond); RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - JUMPBY(oparg * flag); + JUMPBY(flag ? oparg : next_instr->op.code == NOT_TAKEN); } replaced op(_POP_JUMP_IF_TRUE, (cond -- )) { @@ -2731,7 +2733,7 @@ dummy_func( int flag = PyStackRef_IsTrue(cond); DEAD(cond); RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - JUMPBY(oparg * flag); + JUMPBY(flag ? oparg : next_instr->op.code == NOT_TAKEN); } op(_IS_NONE, (value -- b)) { @@ -2923,13 +2925,11 @@ dummy_func( macro(FOR_ITER) = _SPECIALIZE_FOR_ITER + _FOR_ITER; inst(INSTRUMENTED_FOR_ITER, (unused/1 -- )) { - _Py_CODEUNIT *target; _PyStackRef iter_stackref = TOP(); PyObject *iter = PyStackRef_AsPyObjectBorrow(iter_stackref); PyObject *next = (*Py_TYPE(iter)->tp_iternext)(iter); if (next != NULL) { PUSH(PyStackRef_FromPyObjectSteal(next)); - target = next_instr; } else { if (_PyErr_Occurred(tstate)) { @@ -2946,9 +2946,9 @@ dummy_func( STACK_SHRINK(1); PyStackRef_CLOSE(iter_stackref); /* Skip END_FOR and POP_TOP */ - target = next_instr + oparg + 2; + _Py_CODEUNIT *target = next_instr + oparg + 2; + INSTRUMENTED_JUMP(this_instr, target, PY_MONITORING_EVENT_BRANCH_RIGHT); } - INSTRUMENTED_JUMP(this_instr, target, PY_MONITORING_EVENT_BRANCH); } op(_ITER_CHECK_LIST, (iter -- iter)) { @@ -4736,6 +4736,10 @@ dummy_func( INSTRUMENTED_JUMP(this_instr, next_instr - oparg, PY_MONITORING_EVENT_JUMP); } + inst(INSTRUMENTED_NOT_TAKEN, ( -- )) { + INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT); + } + macro(INSTRUMENTED_JUMP_BACKWARD) = unused/1 + _CHECK_PERIODIC + @@ -4744,51 +4748,43 @@ dummy_func( inst(INSTRUMENTED_POP_JUMP_IF_TRUE, (unused/1 -- )) { _PyStackRef cond = POP(); assert(PyStackRef_BoolCheck(cond)); - int flag = PyStackRef_IsTrue(cond); - int offset = flag * oparg; - RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + int jump = PyStackRef_IsTrue(cond); + RECORD_BRANCH_TAKEN(this_instr[1].cache, jump); + if (jump) { + INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT); + } } inst(INSTRUMENTED_POP_JUMP_IF_FALSE, (unused/1 -- )) { _PyStackRef cond = POP(); assert(PyStackRef_BoolCheck(cond)); - int flag = PyStackRef_IsFalse(cond); - int offset = flag * oparg; - RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + int jump = PyStackRef_IsFalse(cond); + RECORD_BRANCH_TAKEN(this_instr[1].cache, jump); + if (jump) { + INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT); + } } inst(INSTRUMENTED_POP_JUMP_IF_NONE, (unused/1 -- )) { _PyStackRef value_stackref = POP(); - int flag = PyStackRef_IsNone(value_stackref); - int offset; - if (flag) { - offset = oparg; + int jump = PyStackRef_IsNone(value_stackref); + RECORD_BRANCH_TAKEN(this_instr[1].cache, jump); + if (jump) { + INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT); } else { PyStackRef_CLOSE(value_stackref); - offset = 0; } - RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); } inst(INSTRUMENTED_POP_JUMP_IF_NOT_NONE, (unused/1 -- )) { _PyStackRef value_stackref = POP(); - int offset; - int nflag = PyStackRef_IsNone(value_stackref); - if (nflag) { - offset = 0; - } - else { + int jump = !PyStackRef_IsNone(value_stackref); + RECORD_BRANCH_TAKEN(this_instr[1].cache, jump); + if (jump) { PyStackRef_CLOSE(value_stackref); - offset = oparg; + INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT); } - #if ENABLE_SPECIALIZATION - this_instr[1].cache = (this_instr[1].cache << 1) | !nflag; - #endif - INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); } tier1 inst(EXTENDED_ARG, ( -- )) { diff --git a/Python/codegen.c b/Python/codegen.c index a5e550cf8c947e..6d3272edfdbf94 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -406,7 +406,13 @@ codegen_addop_j(instr_sequence *seq, location loc, assert(IS_JUMP_TARGET_LABEL(target)); assert(OPCODE_HAS_JUMP(opcode) || IS_BLOCK_PUSH_OPCODE(opcode)); assert(!IS_ASSEMBLER_OPCODE(opcode)); - return _PyInstructionSequence_Addop(seq, opcode, target.id, loc); + if (_PyInstructionSequence_Addop(seq, opcode, target.id, loc) != SUCCESS) { + return ERROR; + } + if (IS_CONDITIONAL_JUMP_OPCODE(opcode) || opcode == FOR_ITER) { + return _PyInstructionSequence_Addop(seq, NOT_TAKEN, 0, NO_LOCATION); + } + return SUCCESS; } #define ADDOP_JUMP(C, LOC, OP, O) \ @@ -682,7 +688,6 @@ codegen_setup_annotations_scope(compiler *c, location loc, ADDOP_I(c, loc, COMPARE_OP, (Py_GT << 5) | compare_masks[Py_GT]); NEW_JUMP_TARGET_LABEL(c, body); ADDOP_JUMP(c, loc, POP_JUMP_IF_FALSE, body); - ADDOP_I(c, loc, LOAD_COMMON_CONSTANT, CONSTANT_NOTIMPLEMENTEDERROR); ADDOP_I(c, loc, RAISE_VARARGS, 1); USE_LABEL(c, body); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index de61a64a6e3374..9bfc3e7f0b112b 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -5668,6 +5668,8 @@ /* _MONITOR_JUMP_BACKWARD is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */ + /* _INSTRUMENTED_NOT_TAKEN is not a viable micro-op for tier 2 because it is instrumented */ + /* _INSTRUMENTED_POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 because it is instrumented */ /* _INSTRUMENTED_POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 because it is instrumented */ diff --git a/Python/flowgraph.c b/Python/flowgraph.c index b1097b64469ecd..64df6290de06ba 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -557,6 +557,12 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) { if (backwards_jump == NULL) { return ERROR; } + assert(b->b_next->b_iused > 0); + assert(b->b_next->b_instr[0].i_opcode == NOT_TAKEN); + b->b_next->b_instr[0].i_opcode = NOP; + b->b_next->b_instr[0].i_loc = NO_LOCATION; + RETURN_IF_ERROR( + basicblock_addop(backwards_jump, NOT_TAKEN, 0, last->i_loc)); RETURN_IF_ERROR( basicblock_add_jump(backwards_jump, JUMP, target, last->i_loc)); last->i_opcode = reversed_opcode; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 8a89ba890fd9c9..ac89891df80590 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -4618,7 +4618,6 @@ next_instr += 2; INSTRUCTION_STATS(INSTRUMENTED_FOR_ITER); /* Skip 1 cache entry */ - _Py_CODEUNIT *target; _PyStackRef iter_stackref = TOP(); PyObject *iter = PyStackRef_AsPyObjectBorrow(iter_stackref); _PyFrame_SetStackPointer(frame, stack_pointer); @@ -4626,7 +4625,6 @@ stack_pointer = _PyFrame_GetStackPointer(frame); if (next != NULL) { PUSH(PyStackRef_FromPyObjectSteal(next)); - target = next_instr; } else { if (_PyErr_Occurred(tstate)) { @@ -4647,9 +4645,9 @@ STACK_SHRINK(1); PyStackRef_CLOSE(iter_stackref); /* Skip END_FOR and POP_TOP */ - target = next_instr + oparg + 2; + _Py_CODEUNIT *target = next_instr + oparg + 2; + INSTRUMENTED_JUMP(this_instr, target, PY_MONITORING_EVENT_BRANCH_RIGHT); } - INSTRUMENTED_JUMP(this_instr, target, PY_MONITORING_EVENT_BRANCH); DISPATCH(); } @@ -4754,6 +4752,15 @@ GO_TO_INSTRUCTION(LOAD_SUPER_ATTR); } + TARGET(INSTRUMENTED_NOT_TAKEN) { + _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr; + (void)this_instr; + next_instr += 1; + INSTRUCTION_STATS(INSTRUMENTED_NOT_TAKEN); + INSTRUMENTED_JUMP(this_instr, next_instr, PY_MONITORING_EVENT_BRANCH_LEFT); + DISPATCH(); + } + TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) { _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr; (void)this_instr; @@ -4762,10 +4769,11 @@ /* Skip 1 cache entry */ _PyStackRef cond = POP(); assert(PyStackRef_BoolCheck(cond)); - int flag = PyStackRef_IsFalse(cond); - int offset = flag * oparg; - RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + int jump = PyStackRef_IsFalse(cond); + RECORD_BRANCH_TAKEN(this_instr[1].cache, jump); + if (jump) { + INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT); + } DISPATCH(); } @@ -4776,17 +4784,14 @@ INSTRUCTION_STATS(INSTRUMENTED_POP_JUMP_IF_NONE); /* Skip 1 cache entry */ _PyStackRef value_stackref = POP(); - int flag = PyStackRef_IsNone(value_stackref); - int offset; - if (flag) { - offset = oparg; + int jump = PyStackRef_IsNone(value_stackref); + RECORD_BRANCH_TAKEN(this_instr[1].cache, jump); + if (jump) { + INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT); } else { PyStackRef_CLOSE(value_stackref); - offset = 0; } - RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); DISPATCH(); } @@ -4797,19 +4802,12 @@ INSTRUCTION_STATS(INSTRUMENTED_POP_JUMP_IF_NOT_NONE); /* Skip 1 cache entry */ _PyStackRef value_stackref = POP(); - int offset; - int nflag = PyStackRef_IsNone(value_stackref); - if (nflag) { - offset = 0; - } - else { + int jump = !PyStackRef_IsNone(value_stackref); + RECORD_BRANCH_TAKEN(this_instr[1].cache, jump); + if (jump) { PyStackRef_CLOSE(value_stackref); - offset = oparg; + INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT); } - #if ENABLE_SPECIALIZATION - this_instr[1].cache = (this_instr[1].cache << 1) | !nflag; - #endif - INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); DISPATCH(); } @@ -4821,10 +4819,11 @@ /* Skip 1 cache entry */ _PyStackRef cond = POP(); assert(PyStackRef_BoolCheck(cond)); - int flag = PyStackRef_IsTrue(cond); - int offset = flag * oparg; - RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - INSTRUMENTED_JUMP(this_instr, next_instr + offset, PY_MONITORING_EVENT_BRANCH); + int jump = PyStackRef_IsTrue(cond); + RECORD_BRANCH_TAKEN(this_instr[1].cache, jump); + if (jump) { + INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT); + } DISPATCH(); } @@ -6659,6 +6658,13 @@ DISPATCH(); } + TARGET(NOT_TAKEN) { + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(NOT_TAKEN); + DISPATCH(); + } + TARGET(POP_EXCEPT) { frame->instr_ptr = next_instr; next_instr += 1; @@ -6687,7 +6693,7 @@ assert(PyStackRef_BoolCheck(cond)); int flag = PyStackRef_IsFalse(cond); RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - JUMPBY(oparg * flag); + JUMPBY(flag ? oparg : next_instr->op.code == NOT_TAKEN); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); @@ -6719,7 +6725,7 @@ assert(PyStackRef_BoolCheck(cond)); int flag = PyStackRef_IsTrue(cond); RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - JUMPBY(oparg * flag); + JUMPBY(flag ? oparg : next_instr->op.code == NOT_TAKEN); } stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -6752,7 +6758,7 @@ assert(PyStackRef_BoolCheck(cond)); int flag = PyStackRef_IsFalse(cond); RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - JUMPBY(oparg * flag); + JUMPBY(flag ? oparg : next_instr->op.code == NOT_TAKEN); } stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); @@ -6770,7 +6776,7 @@ assert(PyStackRef_BoolCheck(cond)); int flag = PyStackRef_IsTrue(cond); RECORD_BRANCH_TAKEN(this_instr[1].cache, flag); - JUMPBY(oparg * flag); + JUMPBY(flag ? oparg : next_instr->op.code == NOT_TAKEN); stack_pointer += -1; assert(WITHIN_STACK_BOUNDS()); DISPATCH(); diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 3503809e3306cb..e4255bfad8c41a 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -85,22 +85,24 @@ static const int8_t EVENT_FOR_OPCODE[256] = { [INSTRUMENTED_YIELD_VALUE] = PY_MONITORING_EVENT_PY_YIELD, [JUMP_FORWARD] = PY_MONITORING_EVENT_JUMP, [JUMP_BACKWARD] = PY_MONITORING_EVENT_JUMP, - [POP_JUMP_IF_FALSE] = PY_MONITORING_EVENT_BRANCH, - [POP_JUMP_IF_TRUE] = PY_MONITORING_EVENT_BRANCH, - [POP_JUMP_IF_NONE] = PY_MONITORING_EVENT_BRANCH, - [POP_JUMP_IF_NOT_NONE] = PY_MONITORING_EVENT_BRANCH, + [POP_JUMP_IF_FALSE] = PY_MONITORING_EVENT_BRANCH_RIGHT, + [POP_JUMP_IF_TRUE] = PY_MONITORING_EVENT_BRANCH_RIGHT, + [POP_JUMP_IF_NONE] = PY_MONITORING_EVENT_BRANCH_RIGHT, + [POP_JUMP_IF_NOT_NONE] = PY_MONITORING_EVENT_BRANCH_RIGHT, [INSTRUMENTED_JUMP_FORWARD] = PY_MONITORING_EVENT_JUMP, [INSTRUMENTED_JUMP_BACKWARD] = PY_MONITORING_EVENT_JUMP, - [INSTRUMENTED_POP_JUMP_IF_FALSE] = PY_MONITORING_EVENT_BRANCH, - [INSTRUMENTED_POP_JUMP_IF_TRUE] = PY_MONITORING_EVENT_BRANCH, - [INSTRUMENTED_POP_JUMP_IF_NONE] = PY_MONITORING_EVENT_BRANCH, - [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = PY_MONITORING_EVENT_BRANCH, - [FOR_ITER] = PY_MONITORING_EVENT_BRANCH, - [INSTRUMENTED_FOR_ITER] = PY_MONITORING_EVENT_BRANCH, + [INSTRUMENTED_POP_JUMP_IF_FALSE] = PY_MONITORING_EVENT_BRANCH_RIGHT, + [INSTRUMENTED_POP_JUMP_IF_TRUE] = PY_MONITORING_EVENT_BRANCH_RIGHT, + [INSTRUMENTED_POP_JUMP_IF_NONE] = PY_MONITORING_EVENT_BRANCH_RIGHT, + [INSTRUMENTED_POP_JUMP_IF_NOT_NONE] = PY_MONITORING_EVENT_BRANCH_RIGHT, + [FOR_ITER] = PY_MONITORING_EVENT_BRANCH_RIGHT, + [INSTRUMENTED_FOR_ITER] = PY_MONITORING_EVENT_BRANCH_RIGHT, [END_FOR] = PY_MONITORING_EVENT_STOP_ITERATION, [INSTRUMENTED_END_FOR] = PY_MONITORING_EVENT_STOP_ITERATION, [END_SEND] = PY_MONITORING_EVENT_STOP_ITERATION, [INSTRUMENTED_END_SEND] = PY_MONITORING_EVENT_STOP_ITERATION, + [NOT_TAKEN] = PY_MONITORING_EVENT_BRANCH_LEFT, + [INSTRUMENTED_NOT_TAKEN] = PY_MONITORING_EVENT_BRANCH_LEFT, }; static const uint8_t DE_INSTRUMENT[256] = { @@ -120,6 +122,7 @@ static const uint8_t DE_INSTRUMENT[256] = { [INSTRUMENTED_END_FOR] = END_FOR, [INSTRUMENTED_END_SEND] = END_SEND, [INSTRUMENTED_LOAD_SUPER_ATTR] = LOAD_SUPER_ATTR, + [INSTRUMENTED_NOT_TAKEN] = NOT_TAKEN, }; static const uint8_t INSTRUMENTED_OPCODES[256] = { @@ -155,6 +158,8 @@ static const uint8_t INSTRUMENTED_OPCODES[256] = { [INSTRUMENTED_FOR_ITER] = INSTRUMENTED_FOR_ITER, [LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR, [INSTRUMENTED_LOAD_SUPER_ATTR] = INSTRUMENTED_LOAD_SUPER_ATTR, + [NOT_TAKEN] = INSTRUMENTED_NOT_TAKEN, + [INSTRUMENTED_NOT_TAKEN] = INSTRUMENTED_NOT_TAKEN, [INSTRUMENTED_LINE] = INSTRUMENTED_LINE, [INSTRUMENTED_INSTRUCTION] = INSTRUMENTED_INSTRUCTION, @@ -323,33 +328,8 @@ _PyInstruction_GetLength(PyCodeObject *code, int offset) { ASSERT_WORLD_STOPPED_OR_LOCKED(code); - int opcode = - FT_ATOMIC_LOAD_UINT8_RELAXED(_PyCode_CODE(code)[offset].op.code); - assert(opcode != 0); - assert(opcode != RESERVED); - if (opcode == INSTRUMENTED_LINE) { - opcode = code->_co_monitoring->lines[offset].original_opcode; - } - if (opcode == INSTRUMENTED_INSTRUCTION) { - opcode = code->_co_monitoring->per_instruction_opcodes[offset]; - } - int deinstrumented = DE_INSTRUMENT[opcode]; - if (deinstrumented) { - opcode = deinstrumented; - } - else { - opcode = _PyOpcode_Deopt[opcode]; - } - assert(opcode != 0); - if (opcode == ENTER_EXECUTOR) { - int exec_index = _PyCode_CODE(code)[offset].op.arg; - _PyExecutorObject *exec = code->co_executors->executors[exec_index]; - opcode = _PyOpcode_Deopt[exec->vm_data.opcode]; - } - assert(!is_instrumented(opcode)); - assert(opcode != ENTER_EXECUTOR); - assert(opcode == _PyOpcode_Deopt[opcode]); - return 1 + _PyOpcode_Caches[opcode]; + _Py_CODEUNIT inst = _Py_GetBaseCodeUnit(code, offset); + return 1 + _PyOpcode_Caches[inst.op.code]; } #ifdef INSTRUMENT_DEBUG @@ -599,16 +579,15 @@ _Py_GetBaseCodeUnit(PyCodeObject *code, int i) int opcode = inst.op.code; if (opcode < MIN_INSTRUMENTED_OPCODE) { inst.op.code = _PyOpcode_Deopt[opcode]; - assert(inst.op.code <= RESUME); + assert(inst.op.code < MIN_SPECIALIZED_OPCODE); return inst; } if (opcode == ENTER_EXECUTOR) { _PyExecutorObject *exec = code->co_executors->executors[inst.op.arg]; opcode = _PyOpcode_Deopt[exec->vm_data.opcode]; inst.op.code = opcode; - assert(opcode <= RESUME); inst.op.arg = exec->vm_data.oparg; - assert(inst.op.code <= RESUME); + assert(inst.op.code < MIN_SPECIALIZED_OPCODE); return inst; } if (opcode == INSTRUMENTED_LINE) { @@ -1084,6 +1063,8 @@ static const char *const event_names [] = { [PY_MONITORING_EVENT_INSTRUCTION] = "INSTRUCTION", [PY_MONITORING_EVENT_JUMP] = "JUMP", [PY_MONITORING_EVENT_BRANCH] = "BRANCH", + [PY_MONITORING_EVENT_BRANCH_LEFT] = "BRANCH_LEFT", + [PY_MONITORING_EVENT_BRANCH_RIGHT] = "BRANCH_RIGHT", [PY_MONITORING_EVENT_C_RETURN] = "C_RETURN", [PY_MONITORING_EVENT_PY_THROW] = "PY_THROW", [PY_MONITORING_EVENT_RAISE] = "RAISE", @@ -1111,6 +1092,10 @@ call_instrumentation_vector( /* Offset visible to user should be the offset in bytes, as that is the * convention for APIs involving code offsets. */ int bytes_offset = offset * (int)sizeof(_Py_CODEUNIT); + if (event == PY_MONITORING_EVENT_BRANCH_LEFT) { + assert(EVENT_FOR_OPCODE[_Py_GetBaseCodeUnit(code, offset-2).op.code] == PY_MONITORING_EVENT_BRANCH_RIGHT); + bytes_offset -= 4; + } PyObject *offset_obj = PyLong_FromLong(bytes_offset); if (offset_obj == NULL) { return -1; @@ -1191,7 +1176,8 @@ _Py_call_instrumentation_jump( _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, _Py_CODEUNIT *target) { assert(event == PY_MONITORING_EVENT_JUMP || - event == PY_MONITORING_EVENT_BRANCH); + event == PY_MONITORING_EVENT_BRANCH_RIGHT || + event == PY_MONITORING_EVENT_BRANCH_LEFT); assert(frame->instr_ptr == instr); int to = (int)(target - _PyFrame_GetBytecode(frame)); PyObject *to_obj = PyLong_FromLong(to * (int)sizeof(_Py_CODEUNIT)); @@ -1427,19 +1413,6 @@ _Py_call_instrumentation_instruction(PyThreadState *tstate, _PyInterpreterFrame* return next_opcode; } - -PyObject * -_PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj) -{ - PyInterpreterState *is = _PyInterpreterState_GET(); - assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); - assert(0 <= event_id && event_id < _PY_MONITORING_EVENTS); - PyObject *callback = _Py_atomic_exchange_ptr(&is->monitoring_callables[tool_id][event_id], - Py_XNewRef(obj)); - - return callback; -} - static void initialize_tools(PyCodeObject *code) { @@ -2312,6 +2285,10 @@ monitoring_set_events_impl(PyObject *module, int tool_id, int event_set) return NULL; } event_set &= ~C_RETURN_EVENTS; + if (event_set & (1 << PY_MONITORING_EVENT_BRANCH)) { + event_set &= ~(1 << PY_MONITORING_EVENT_BRANCH); + event_set |= (1 << PY_MONITORING_EVENT_BRANCH_RIGHT) | (1 << PY_MONITORING_EVENT_BRANCH_LEFT); + } if (_PyMonitoring_SetEvents(tool_id, event_set)) { return NULL; } @@ -2384,6 +2361,10 @@ monitoring_set_local_events_impl(PyObject *module, int tool_id, return NULL; } event_set &= ~C_RETURN_EVENTS; + if (event_set & (1 << PY_MONITORING_EVENT_BRANCH)) { + event_set &= ~(1 << PY_MONITORING_EVENT_BRANCH); + event_set |= (1 << PY_MONITORING_EVENT_BRANCH_RIGHT) | (1 << PY_MONITORING_EVENT_BRANCH_LEFT); + } if (event_set < 0 || event_set >= (1 << _PY_MONITORING_LOCAL_EVENTS)) { PyErr_Format(PyExc_ValueError, "invalid local event set 0x%x", event_set); return NULL; @@ -2711,7 +2692,27 @@ _PyMonitoring_FireBranchEvent(PyMonitoringState *state, PyObject *codelike, int3 assert(state->active); PyObject *args[4] = { NULL, NULL, NULL, target_offset }; return capi_call_instrumentation(state, codelike, offset, args, 3, - PY_MONITORING_EVENT_BRANCH); + PY_MONITORING_EVENT_BRANCH_RIGHT); +} + +int +_PyMonitoring_FireBranchRightEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, + PyObject *target_offset) +{ + assert(state->active); + PyObject *args[4] = { NULL, NULL, NULL, target_offset }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_BRANCH_RIGHT); +} + +int +_PyMonitoring_FireBranchLeftEvent(PyMonitoringState *state, PyObject *codelike, int32_t offset, + PyObject *target_offset) +{ + assert(state->active); + PyObject *args[4] = { NULL, NULL, NULL, target_offset }; + return capi_call_instrumentation(state, codelike, offset, args, 3, + PY_MONITORING_EVENT_BRANCH_LEFT); } int @@ -2849,3 +2850,213 @@ _PyMonitoring_FireStopIterationEvent(PyMonitoringState *state, PyObject *codelik Py_DECREF(exc); return exception_event_teardown(err, NULL); } + + + +/* Handle legacy BRANCH event */ + +typedef struct _PyLegacyBranchEventHandler { + PyObject_HEAD + vectorcallfunc vectorcall; + PyObject *handler; + bool right; + int tool_id; +} _PyLegacyBranchEventHandler; + +static void +dealloc_branch_handler(_PyLegacyBranchEventHandler *self) +{ + Py_CLEAR(self->handler); + PyObject_Free((PyObject *)self); +} + +static PyTypeObject _PyLegacyBranchEventHandler_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "sys.monitoring.branch_event_handler", + sizeof(_PyLegacyBranchEventHandler), + .tp_dealloc = (destructor)dealloc_branch_handler, + .tp_vectorcall_offset = offsetof(_PyLegacyBranchEventHandler, vectorcall), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_DISALLOW_INSTANTIATION, + .tp_call = PyVectorcall_Call, +}; + + +static PyObject * +branch_handler( + _PyLegacyBranchEventHandler *self, PyObject *const *args, + size_t nargsf, PyObject *kwnames +) { + PyObject *res = PyObject_Vectorcall(self->handler, args, nargsf, kwnames); + if (res == &_PyInstrumentation_DISABLE) { + // Find the other instrumented instruction and remove tool + assert(PyVectorcall_NARGS(nargsf) >= 2); + PyObject *offset_obj = args[1]; + int bytes_offset = PyLong_AsLong(offset_obj); + if (PyErr_Occurred()) { + return NULL; + } + PyCodeObject *code = (PyCodeObject *)args[0]; + if (!PyCode_Check(code) || (bytes_offset & 1)) { + return res; + } + int offset = bytes_offset / 2; + /* We need FOR_ITER and POP_JUMP_ to be the same size */ + assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1); + if (self->right) { + offset += 2; + } + if (offset >= Py_SIZE(code)) { + return res; + } + int other_event = self->right ? + PY_MONITORING_EVENT_BRANCH_LEFT : PY_MONITORING_EVENT_BRANCH_RIGHT; + LOCK_CODE(code); + remove_tools(code, offset, other_event, 1 << self->tool_id); + UNLOCK_CODE(); + } + return res; +} + +static PyObject *make_branch_handler(int tool_id, PyObject *handler, bool right) +{ + _PyLegacyBranchEventHandler *callback = + PyObject_NEW(_PyLegacyBranchEventHandler, &_PyLegacyBranchEventHandler_Type); + if (callback == NULL) { + return NULL; + } + callback->vectorcall = (vectorcallfunc)branch_handler; + callback->handler = Py_NewRef(handler); + callback->right = right; + callback->tool_id = tool_id; + return (PyObject *)callback; +} + +/* Consumes a reference to obj */ +static PyObject *exchange_callables(int tool_id, int event_id, PyObject *obj) +{ + PyInterpreterState *is = _PyInterpreterState_GET(); + return _Py_atomic_exchange_ptr(&is->monitoring_callables[tool_id][event_id], obj); +} + +PyObject * +_PyMonitoring_RegisterCallback(int tool_id, int event_id, PyObject *obj) +{ + assert(0 <= tool_id && tool_id < PY_MONITORING_TOOL_IDS); + assert(0 <= event_id && event_id < _PY_MONITORING_EVENTS); + PyObject *res; + if (event_id == PY_MONITORING_EVENT_BRANCH) { + PyObject *left, *right; + if (obj == NULL) { + left = NULL; + right = NULL; + } + else { + right = make_branch_handler(tool_id, obj, true); + if (right == NULL) { + return NULL; + } + left = make_branch_handler(tool_id, obj, false); + if (left == NULL) { + Py_DECREF(right); + return NULL; + } + } + Py_XDECREF(exchange_callables(tool_id, PY_MONITORING_EVENT_BRANCH_RIGHT, right)); + res = exchange_callables(tool_id, PY_MONITORING_EVENT_BRANCH_LEFT, left); + } + else { + res = exchange_callables(tool_id, event_id, Py_XNewRef(obj)); + } + if (res != NULL && Py_TYPE(res) == &_PyLegacyBranchEventHandler_Type) { + _PyLegacyBranchEventHandler *wrapper = (_PyLegacyBranchEventHandler *)res; + res = Py_NewRef(wrapper->handler); + Py_DECREF(wrapper); + } + return res; +} + +/* Branch Iterator */ + +typedef struct { + PyObject_HEAD + PyCodeObject *bi_code; + int bi_offset; +} branchesiterator; + +static PyObject * +int_triple(int a, int b, int c) { + PyObject *obja = PyLong_FromLong(a); + PyObject *objb = NULL; + PyObject *objc = NULL; + if (obja == NULL) { + goto error; + } + objb = PyLong_FromLong(b); + if (objb == NULL) { + goto error; + } + objc = PyLong_FromLong(c); + if (objc == NULL) { + goto error; + } + PyObject *array[3] = { obja, objb, objc }; + return _PyTuple_FromArraySteal(array, 3); +error: + Py_XDECREF(obja); + Py_XDECREF(objb); + Py_XDECREF(objc); + return NULL; +} + +static PyObject * +branchesiter_next(branchesiterator *bi) +{ + int offset = bi->bi_offset; + while (offset < Py_SIZE(bi->bi_code)) { + _Py_CODEUNIT inst = _Py_GetBaseCodeUnit(bi->bi_code, offset); + int next_offset = offset + _PyInstruction_GetLength(bi->bi_code, offset); + int event = EVENT_FOR_OPCODE[inst.op.code]; + if (event == PY_MONITORING_EVENT_BRANCH_RIGHT) { + /* Skip NOT_TAKEN */ + int not_taken = next_offset + 1; + bi->bi_offset = not_taken; + return int_triple(offset*2, not_taken*2, (next_offset + inst.op.arg)*2); + } + offset = next_offset; + } + return NULL; +} + +static void +branchesiter_dealloc(branchesiterator *bi) +{ + Py_DECREF(bi->bi_code); + PyObject_Free(bi); +} + +static PyTypeObject _PyBranchesIterator = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "line_iterator", /* tp_name */ + sizeof(branchesiterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + .tp_dealloc = (destructor)branchesiter_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .tp_iter = PyObject_SelfIter, + .tp_iternext = (iternextfunc)branchesiter_next, + .tp_free = PyObject_Del, +}; + +PyObject * +_PyInstrumentation_BranchesIterator(PyCodeObject *code) +{ + + branchesiterator *bi = (branchesiterator *)PyType_GenericAlloc(&_PyBranchesIterator, 0); + if (bi == NULL) { + return NULL; + } + bi->bi_code = (PyCodeObject*)Py_NewRef(code); + bi->bi_offset = 0; + return (PyObject *)bi; +} diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index c93941dcac4abf..7f3fb9c9a63dd1 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -27,6 +27,7 @@ static void *opcode_targets[256] = { &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, &&TARGET_NOP, + &&TARGET_NOT_TAKEN, &&TARGET_POP_EXCEPT, &&TARGET_POP_TOP, &&TARGET_PUSH_EXC_INFO, @@ -147,7 +148,6 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -235,7 +235,6 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_END_SEND, &&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR, @@ -244,6 +243,7 @@ static void *opcode_targets[256] = { &&TARGET_INSTRUMENTED_CALL_FUNCTION_EX, &&TARGET_INSTRUMENTED_INSTRUCTION, &&TARGET_INSTRUMENTED_JUMP_FORWARD, + &&TARGET_INSTRUMENTED_NOT_TAKEN, &&TARGET_INSTRUMENTED_POP_JUMP_IF_TRUE, &&TARGET_INSTRUMENTED_POP_JUMP_IF_FALSE, &&TARGET_INSTRUMENTED_POP_JUMP_IF_NONE, diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 33b34d6fa0d3f9..2c3133d7107df2 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2343,6 +2343,8 @@ /* _MONITOR_JUMP_BACKWARD is not a viable micro-op for tier 2 */ + /* _INSTRUMENTED_NOT_TAKEN is not a viable micro-op for tier 2 */ + /* _INSTRUMENTED_POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */ /* _INSTRUMENTED_POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 */ diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index badd7b79102310..a1ec1927eb56df 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -106,6 +106,8 @@ Python/context.c - PyContextToken_Type - Python/context.c - PyContextVar_Type - Python/context.c - PyContext_Type - Python/instruction_sequence.c - _PyInstructionSequence_Type - +Python/instrumentation.c - _PyLegacyBranchEventHandler_Type - +Python/instrumentation.c - _PyBranchesIterator - Python/traceback.c - PyTraceBack_Type - ##-----------------------